ap.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * VFIO based AP matrix device assignment
  3. *
  4. * Copyright 2018 IBM Corp.
  5. * Author(s): Tony Krowiak <akrowiak@linux.ibm.com>
  6. * Halil Pasic <pasic@linux.ibm.com>
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or (at
  9. * your option) any later version. See the COPYING file in the top-level
  10. * directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include <linux/vfio.h>
  14. #include <sys/ioctl.h>
  15. #include "qapi/error.h"
  16. #include "hw/sysbus.h"
  17. #include "hw/vfio/vfio.h"
  18. #include "hw/vfio/vfio-common.h"
  19. #include "hw/s390x/ap-device.h"
  20. #include "qemu/error-report.h"
  21. #include "qemu/module.h"
  22. #include "qemu/option.h"
  23. #include "qemu/config-file.h"
  24. #include "cpu.h"
  25. #include "kvm_s390x.h"
  26. #include "migration/vmstate.h"
  27. #include "hw/qdev-properties.h"
  28. #include "hw/s390x/ap-bridge.h"
  29. #include "exec/address-spaces.h"
  30. #define VFIO_AP_DEVICE_TYPE "vfio-ap"
  31. typedef struct VFIOAPDevice {
  32. APDevice apdev;
  33. VFIODevice vdev;
  34. } VFIOAPDevice;
  35. #define VFIO_AP_DEVICE(obj) \
  36. OBJECT_CHECK(VFIOAPDevice, (obj), VFIO_AP_DEVICE_TYPE)
  37. static void vfio_ap_compute_needs_reset(VFIODevice *vdev)
  38. {
  39. vdev->needs_reset = false;
  40. }
  41. /*
  42. * We don't need vfio_hot_reset_multi and vfio_eoi operations for
  43. * vfio-ap device now.
  44. */
  45. struct VFIODeviceOps vfio_ap_ops = {
  46. .vfio_compute_needs_reset = vfio_ap_compute_needs_reset,
  47. };
  48. static void vfio_ap_put_device(VFIOAPDevice *vapdev)
  49. {
  50. g_free(vapdev->vdev.name);
  51. vfio_put_base_device(&vapdev->vdev);
  52. }
  53. static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, Error **errp)
  54. {
  55. GError *gerror = NULL;
  56. char *symlink, *group_path;
  57. int groupid;
  58. symlink = g_strdup_printf("%s/iommu_group", vapdev->vdev.sysfsdev);
  59. group_path = g_file_read_link(symlink, &gerror);
  60. g_free(symlink);
  61. if (!group_path) {
  62. error_setg(errp, "%s: no iommu_group found for %s: %s",
  63. VFIO_AP_DEVICE_TYPE, vapdev->vdev.sysfsdev, gerror->message);
  64. return NULL;
  65. }
  66. if (sscanf(basename(group_path), "%d", &groupid) != 1) {
  67. error_setg(errp, "vfio: failed to read %s", group_path);
  68. g_free(group_path);
  69. return NULL;
  70. }
  71. g_free(group_path);
  72. return vfio_get_group(groupid, &address_space_memory, errp);
  73. }
  74. static void vfio_ap_realize(DeviceState *dev, Error **errp)
  75. {
  76. int ret;
  77. char *mdevid;
  78. Error *local_err = NULL;
  79. VFIOGroup *vfio_group;
  80. APDevice *apdev = AP_DEVICE(dev);
  81. VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
  82. vfio_group = vfio_ap_get_group(vapdev, &local_err);
  83. if (!vfio_group) {
  84. goto out_err;
  85. }
  86. vapdev->vdev.ops = &vfio_ap_ops;
  87. vapdev->vdev.type = VFIO_DEVICE_TYPE_AP;
  88. mdevid = basename(vapdev->vdev.sysfsdev);
  89. vapdev->vdev.name = g_strdup_printf("%s", mdevid);
  90. vapdev->vdev.dev = dev;
  91. /*
  92. * vfio-ap devices operate in a way compatible with
  93. * memory ballooning, as no pages are pinned in the host.
  94. * This needs to be set before vfio_get_device() for vfio common to
  95. * handle the balloon inhibitor.
  96. */
  97. vapdev->vdev.balloon_allowed = true;
  98. ret = vfio_get_device(vfio_group, mdevid, &vapdev->vdev, &local_err);
  99. if (ret) {
  100. goto out_get_dev_err;
  101. }
  102. return;
  103. out_get_dev_err:
  104. vfio_ap_put_device(vapdev);
  105. vfio_put_group(vfio_group);
  106. out_err:
  107. error_propagate(errp, local_err);
  108. }
  109. static void vfio_ap_unrealize(DeviceState *dev, Error **errp)
  110. {
  111. APDevice *apdev = AP_DEVICE(dev);
  112. VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
  113. VFIOGroup *group = vapdev->vdev.group;
  114. vfio_ap_put_device(vapdev);
  115. vfio_put_group(group);
  116. }
  117. static Property vfio_ap_properties[] = {
  118. DEFINE_PROP_STRING("sysfsdev", VFIOAPDevice, vdev.sysfsdev),
  119. DEFINE_PROP_END_OF_LIST(),
  120. };
  121. static void vfio_ap_reset(DeviceState *dev)
  122. {
  123. int ret;
  124. APDevice *apdev = AP_DEVICE(dev);
  125. VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
  126. ret = ioctl(vapdev->vdev.fd, VFIO_DEVICE_RESET);
  127. if (ret) {
  128. error_report("%s: failed to reset %s device: %s", __func__,
  129. vapdev->vdev.name, strerror(errno));
  130. }
  131. }
  132. static const VMStateDescription vfio_ap_vmstate = {
  133. .name = "vfio-ap",
  134. .unmigratable = 1,
  135. };
  136. static void vfio_ap_class_init(ObjectClass *klass, void *data)
  137. {
  138. DeviceClass *dc = DEVICE_CLASS(klass);
  139. dc->props = vfio_ap_properties;
  140. dc->vmsd = &vfio_ap_vmstate;
  141. dc->desc = "VFIO-based AP device assignment";
  142. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  143. dc->realize = vfio_ap_realize;
  144. dc->unrealize = vfio_ap_unrealize;
  145. dc->hotpluggable = true;
  146. dc->reset = vfio_ap_reset;
  147. dc->bus_type = TYPE_AP_BUS;
  148. }
  149. static const TypeInfo vfio_ap_info = {
  150. .name = VFIO_AP_DEVICE_TYPE,
  151. .parent = AP_DEVICE_TYPE,
  152. .instance_size = sizeof(VFIOAPDevice),
  153. .class_init = vfio_ap_class_init,
  154. };
  155. static void vfio_ap_type_init(void)
  156. {
  157. type_register_static(&vfio_ap_info);
  158. }
  159. type_init(vfio_ap_type_init)