diff mbox series

[3/5] virtio-iommu: Declare topology in config space

Message ID 20200821162839.3182051-4-jean-philippe@linaro.org (mailing list archive)
State New, archived
Headers show
Series virtio-iommu: Built-in topology and x86 support | expand

Commit Message

Jean-Philippe Brucker Aug. 21, 2020, 4:28 p.m. UTC
When requested on the command-line, by adding topology=on to the
virtio-iommu device, provide the IOMMU topology in the virtio config
space. It describes which endpoints are managed by the IOMMU - all PCI
devices - and allows to support:
* virtio-iommu for platforms without ACPI or DT (e.g. microvm),
* virtio-iommu for ACPI platforms, temporarily. A new ACPI table will be
  introduced to handle those, but this provides a boot method in the
  meantime.

Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
---
 include/hw/virtio/virtio-iommu.h |  3 +++
 hw/virtio/virtio-iommu.c         | 40 ++++++++++++++++++++++++++++----
 hw/virtio/trace-events           |  4 ++--
 3 files changed, 40 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index ae57efab1f3..7ba1dacf75d 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -49,6 +49,7 @@  typedef struct VirtIOIOMMU {
     VirtQueue *req_vq;
     VirtQueue *event_vq;
     struct virtio_iommu_config config;
+    struct virtio_iommu_topo_pci_range pci_topo;
     uint64_t features;
     GHashTable *as_by_busptr;
     IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX];
@@ -59,6 +60,8 @@  typedef struct VirtIOIOMMU {
     QemuMutex mutex;
     GTree *endpoints;
     bool boot_bypass;
+    /* Declare topology in config space */
+    bool topology;
 } VirtIOIOMMU;
 
 #endif
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 3b821fc005d..08ab457ccf1 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -731,15 +731,24 @@  unlock:
 
 static void virtio_iommu_get_config(VirtIODevice *vdev, uint8_t *config_data)
 {
+    off_t offset;
     VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);
     struct virtio_iommu_config *config = &dev->config;
+    struct virtio_iommu_topo_pci_range *pci_topo = &dev->pci_topo;
 
     trace_virtio_iommu_get_config(config->page_size_mask,
                                   config->input_range.start,
                                   config->input_range.end,
                                   config->domain_range.end,
-                                  config->probe_size);
-    memcpy(config_data, &dev->config, sizeof(struct virtio_iommu_config));
+                                  config->probe_size,
+                                  config->topo_config.offset,
+                                  config->topo_config.count);
+    memcpy(config_data, config, sizeof(*config));
+
+    offset = config->topo_config.offset;
+    if (offset) {
+        memcpy(config_data + offset, pci_topo, sizeof(*pci_topo));
+    }
 }
 
 static void virtio_iommu_set_config(VirtIODevice *vdev,
@@ -747,12 +756,14 @@  static void virtio_iommu_set_config(VirtIODevice *vdev,
 {
     struct virtio_iommu_config config;
 
-    memcpy(&config, config_data, sizeof(struct virtio_iommu_config));
+    memcpy(&config, config_data, sizeof(config));
     trace_virtio_iommu_set_config(config.page_size_mask,
                                   config.input_range.start,
                                   config.input_range.end,
                                   config.domain_range.end,
-                                  config.probe_size);
+                                  config.probe_size,
+                                  config.topo_config.offset,
+                                  config.topo_config.count);
 }
 
 static uint64_t virtio_iommu_get_features(VirtIODevice *vdev, uint64_t f,
@@ -776,9 +787,10 @@  static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VirtIOIOMMU *s = VIRTIO_IOMMU(dev);
+    size_t aligned_config_size = QEMU_ALIGN_UP(sizeof(s->config), 8);
 
     virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU,
-                sizeof(struct virtio_iommu_config));
+                aligned_config_size + sizeof(s->pci_topo));
 
     memset(s->iommu_pcibus_by_bus_num, 0, sizeof(s->iommu_pcibus_by_bus_num));
 
@@ -791,6 +803,12 @@  static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
     s->config.domain_range.end = 32;
     s->config.probe_size = VIOMMU_PROBE_SIZE;
 
+    if (s->topology) {
+        s->config.topo_config.offset = aligned_config_size;
+        s->config.topo_config.count = 1;
+        virtio_add_feature(&s->features, VIRTIO_IOMMU_F_TOPOLOGY);
+    }
+
     virtio_add_feature(&s->features, VIRTIO_RING_F_EVENT_IDX);
     virtio_add_feature(&s->features, VIRTIO_RING_F_INDIRECT_DESC);
     virtio_add_feature(&s->features, VIRTIO_F_VERSION_1);
@@ -810,6 +828,17 @@  static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
     } else {
         error_setg(errp, "VIRTIO-IOMMU is not attached to any PCI bus!");
     }
+
+    if (s->topology) {
+        s->pci_topo = (struct virtio_iommu_topo_pci_range) {
+            .type               = cpu_to_le16(VIRTIO_IOMMU_TOPO_PCI_RANGE),
+            .length             = cpu_to_le16(sizeof(s->pci_topo)),
+            .endpoint_start     = 0,
+            .segment            = 0,
+            .bdf_start          = 0,
+            .bdf_end            = 0xffff,
+        };
+    }
 }
 
 static void virtio_iommu_device_unrealize(DeviceState *dev)
@@ -965,6 +994,7 @@  static const VMStateDescription vmstate_virtio_iommu = {
 static Property virtio_iommu_properties[] = {
     DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, "PCI", PCIBus *),
     DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true),
+    DEFINE_PROP_BOOL("topology", VirtIOIOMMU, topology, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 045e89cae69..6c5830ca47c 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -59,8 +59,8 @@  virtio_mmio_setting_irq(int level) "virtio_mmio setting IRQ %d"
 virtio_iommu_device_reset(void) "reset!"
 virtio_iommu_get_features(uint64_t features) "device supports features=0x%"PRIx64
 virtio_iommu_device_status(uint8_t status) "driver status = %d"
-virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_range, uint32_t probe_size) "page_size_mask=0x%"PRIx64" start=0x%"PRIx64" end=0x%"PRIx64" domain_range=%d probe_size=0x%x"
-virtio_iommu_set_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_range, uint32_t probe_size) "page_size_mask=0x%"PRIx64" start=0x%"PRIx64" end=0x%"PRIx64" domain_bits=%d probe_size=0x%x"
+virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_range, uint32_t probe_size, uint16_t topo_offset, uint16_t topo_count) "page_size_mask=0x%"PRIx64" start=0x%"PRIx64" end=0x%"PRIx64" domain_range=%d probe_size=0x%x topo_off=0x%x topo_count=%u"
+virtio_iommu_set_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_range, uint32_t probe_size, uint16_t topo_offset, uint16_t topo_count) "page_size_mask=0x%"PRIx64" start=0x%"PRIx64" end=0x%"PRIx64" domain_bits=%d probe_size=0x%x topo_off=0x%x topo_count=%u"
 virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "domain=%d endpoint=%d"
 virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=%d endpoint=%d"
 virtio_iommu_map(uint32_t domain_id, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start, uint32_t flags) "domain=%d virt_start=0x%"PRIx64" virt_end=0x%"PRIx64 " phys_start=0x%"PRIx64" flags=%d"