virtio-mem-pci.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Virtio MEM PCI device
  3. *
  4. * Copyright (C) 2020 Red Hat, Inc.
  5. *
  6. * Authors:
  7. * David Hildenbrand <david@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "virtio-mem-pci.h"
  14. #include "hw/mem/memory-device.h"
  15. #include "qapi/error.h"
  16. #include "qapi/qapi-events-misc.h"
  17. static void virtio_mem_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
  18. {
  19. VirtIOMEMPCI *mem_pci = VIRTIO_MEM_PCI(vpci_dev);
  20. DeviceState *vdev = DEVICE(&mem_pci->vdev);
  21. virtio_pci_force_virtio_1(vpci_dev);
  22. qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
  23. }
  24. static void virtio_mem_pci_set_addr(MemoryDeviceState *md, uint64_t addr,
  25. Error **errp)
  26. {
  27. object_property_set_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP, addr, errp);
  28. }
  29. static uint64_t virtio_mem_pci_get_addr(const MemoryDeviceState *md)
  30. {
  31. return object_property_get_uint(OBJECT(md), VIRTIO_MEM_ADDR_PROP,
  32. &error_abort);
  33. }
  34. static MemoryRegion *virtio_mem_pci_get_memory_region(MemoryDeviceState *md,
  35. Error **errp)
  36. {
  37. VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);
  38. VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev);
  39. VirtIOMEMClass *vmc = VIRTIO_MEM_GET_CLASS(vmem);
  40. return vmc->get_memory_region(vmem, errp);
  41. }
  42. static uint64_t virtio_mem_pci_get_plugged_size(const MemoryDeviceState *md,
  43. Error **errp)
  44. {
  45. return object_property_get_uint(OBJECT(md), VIRTIO_MEM_SIZE_PROP,
  46. errp);
  47. }
  48. static void virtio_mem_pci_fill_device_info(const MemoryDeviceState *md,
  49. MemoryDeviceInfo *info)
  50. {
  51. VirtioMEMDeviceInfo *vi = g_new0(VirtioMEMDeviceInfo, 1);
  52. VirtIOMEMPCI *pci_mem = VIRTIO_MEM_PCI(md);
  53. VirtIOMEM *vmem = VIRTIO_MEM(&pci_mem->vdev);
  54. VirtIOMEMClass *vpc = VIRTIO_MEM_GET_CLASS(vmem);
  55. DeviceState *dev = DEVICE(md);
  56. if (dev->id) {
  57. vi->has_id = true;
  58. vi->id = g_strdup(dev->id);
  59. }
  60. /* let the real device handle everything else */
  61. vpc->fill_device_info(vmem, vi);
  62. info->u.virtio_mem.data = vi;
  63. info->type = MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM;
  64. }
  65. static void virtio_mem_pci_size_change_notify(Notifier *notifier, void *data)
  66. {
  67. VirtIOMEMPCI *pci_mem = container_of(notifier, VirtIOMEMPCI,
  68. size_change_notifier);
  69. DeviceState *dev = DEVICE(pci_mem);
  70. const uint64_t * const size_p = data;
  71. const char *id = NULL;
  72. if (dev->id) {
  73. id = g_strdup(dev->id);
  74. }
  75. qapi_event_send_memory_device_size_change(!!id, id, *size_p);
  76. }
  77. static void virtio_mem_pci_class_init(ObjectClass *klass, void *data)
  78. {
  79. DeviceClass *dc = DEVICE_CLASS(klass);
  80. VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
  81. PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
  82. MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(klass);
  83. k->realize = virtio_mem_pci_realize;
  84. set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  85. pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
  86. pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_MEM;
  87. pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
  88. pcidev_k->class_id = PCI_CLASS_OTHERS;
  89. mdc->get_addr = virtio_mem_pci_get_addr;
  90. mdc->set_addr = virtio_mem_pci_set_addr;
  91. mdc->get_plugged_size = virtio_mem_pci_get_plugged_size;
  92. mdc->get_memory_region = virtio_mem_pci_get_memory_region;
  93. mdc->fill_device_info = virtio_mem_pci_fill_device_info;
  94. }
  95. static void virtio_mem_pci_instance_init(Object *obj)
  96. {
  97. VirtIOMEMPCI *dev = VIRTIO_MEM_PCI(obj);
  98. VirtIOMEMClass *vmc;
  99. VirtIOMEM *vmem;
  100. virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
  101. TYPE_VIRTIO_MEM);
  102. dev->size_change_notifier.notify = virtio_mem_pci_size_change_notify;
  103. vmem = VIRTIO_MEM(&dev->vdev);
  104. vmc = VIRTIO_MEM_GET_CLASS(vmem);
  105. /*
  106. * We never remove the notifier again, as we expect both devices to
  107. * disappear at the same time.
  108. */
  109. vmc->add_size_change_notifier(vmem, &dev->size_change_notifier);
  110. object_property_add_alias(obj, VIRTIO_MEM_BLOCK_SIZE_PROP,
  111. OBJECT(&dev->vdev), VIRTIO_MEM_BLOCK_SIZE_PROP);
  112. object_property_add_alias(obj, VIRTIO_MEM_SIZE_PROP, OBJECT(&dev->vdev),
  113. VIRTIO_MEM_SIZE_PROP);
  114. object_property_add_alias(obj, VIRTIO_MEM_REQUESTED_SIZE_PROP,
  115. OBJECT(&dev->vdev),
  116. VIRTIO_MEM_REQUESTED_SIZE_PROP);
  117. }
  118. static const VirtioPCIDeviceTypeInfo virtio_mem_pci_info = {
  119. .base_name = TYPE_VIRTIO_MEM_PCI,
  120. .generic_name = "virtio-mem-pci",
  121. .instance_size = sizeof(VirtIOMEMPCI),
  122. .instance_init = virtio_mem_pci_instance_init,
  123. .class_init = virtio_mem_pci_class_init,
  124. .interfaces = (InterfaceInfo[]) {
  125. { TYPE_MEMORY_DEVICE },
  126. { }
  127. },
  128. };
  129. static void virtio_mem_pci_register_types(void)
  130. {
  131. virtio_pci_types_register(&virtio_mem_pci_info);
  132. }
  133. type_init(virtio_mem_pci_register_types)