On Fri, Nov 22, 2019 at 07:29:42PM +0100, Eric Auger wrote: > The virtio-iommu-pci is instantiated through the -device QEMU > option. However if instantiated it also requires an IORT ACPI table > to describe the ID mappings between the root complex and the iommu. > > This patch adds the generation of the IORT table if the > virtio-iommu-pci device is instantiated. > > We also declare the [0xfee00000 - 0xfeefffff] MSI reserved region > so that it gets bypassed by the IOMMU. > > Signed-off-by: Eric Auger <eric.au...@redhat.com>
So I'd like us to use virtio config space in preference to ACPI. Guest bits for that are not ready yet, but I think it's better to wait than maintaining both ACPI and config space forever later. Could you send a smaller patchset without pci/acpi bits for now? > --- > hw/i386/acpi-build.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ > hw/i386/pc.c | 15 ++++++++- > include/hw/i386/pc.h | 2 ++ > 3 files changed, 88 insertions(+), 1 deletion(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index 12ff55fcfb..f09cabdcae 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -2744,6 +2744,72 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg) > return true; > } > > +static inline void > +fill_iort_idmap(AcpiIortIdMapping *idmap, int i, > + uint32_t input_base, uint32_t id_count, > + uint32_t output_base, uint32_t output_reference) > +{ > + idmap[i].input_base = cpu_to_le32(input_base); > + idmap[i].id_count = cpu_to_le32(id_count); > + idmap[i].output_base = cpu_to_le32(output_base); > + idmap[i].output_reference = cpu_to_le32(output_reference); > +} > + > +static void > +build_iort(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms) > +{ > + size_t iommu_node_size, rc_node_size, iommu_node_offset; > + int iort_start = table_data->len; > + AcpiIortPVIommuPCI *iommu; > + AcpiIortIdMapping *idmap; > + AcpiIortTable *iort; > + size_t iort_length; > + AcpiIortRC *rc; > + > + iort = acpi_data_push(table_data, sizeof(*iort)); > + iort_length = sizeof(*iort); > + iort->node_count = cpu_to_le32(2); > + > + /* virtio-iommu node */ > + > + iommu_node_offset = sizeof(*iort); > + iort->node_offset = cpu_to_le32(iommu_node_offset); > + iommu_node_size = sizeof(*iommu); > + iort_length += iommu_node_offset; > + iommu = acpi_data_push(table_data, iommu_node_size); > + iommu->type = ACPI_IORT_NODE_PARAVIRT; > + iommu->length = cpu_to_le16(iommu_node_size); > + iommu->mapping_count = 0; > + iommu->devid = cpu_to_le32(pcms->virtio_iommu_bdf); > + iommu->model = cpu_to_le32(ACPI_IORT_NODE_PV_VIRTIO_IOMMU_PCI); > + > + /* Root Complex Node */ > + rc_node_size = sizeof(*rc) + 2 * sizeof(*idmap); > + iort_length += rc_node_size; > + rc = acpi_data_push(table_data, rc_node_size); > + > + rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX; > + rc->length = cpu_to_le16(rc_node_size); > + rc->mapping_count = cpu_to_le32(2); > + rc->mapping_offset = cpu_to_le32(sizeof(*rc)); > + > + /* fully coherent device */ > + rc->memory_properties.cache_coherency = cpu_to_le32(1); > + rc->memory_properties.memory_flags = 0x3; /* CCA = CPM = DCAS = 1 */ > + rc->pci_segment_number = 0; /* MCFG pci_segment */ > + fill_iort_idmap(rc->id_mapping_array, 0, 0, pcms->virtio_iommu_bdf, 0, > + iommu_node_offset); > + fill_iort_idmap(rc->id_mapping_array, 1, pcms->virtio_iommu_bdf + 1, > + 0xFFFF - pcms->virtio_iommu_bdf, > + pcms->virtio_iommu_bdf + 1, iommu_node_offset); > + > + iort = (AcpiIortTable *)(table_data->data + iort_start); > + iort->length = cpu_to_le32(iort_length); > + > + build_header(linker, table_data, (void *)(table_data->data + iort_start), > + "IORT", table_data->len - iort_start, 0, NULL, NULL); > +} > + > static > void acpi_build(AcpiBuildTables *tables, MachineState *machine) > { > @@ -2835,6 +2901,12 @@ void acpi_build(AcpiBuildTables *tables, MachineState > *machine) > build_slit(tables_blob, tables->linker, machine); > } > } > + > + if (pcms->virtio_iommu) { > + acpi_add_table(table_offsets, tables_blob); > + build_iort(tables_blob, tables->linker, pcms); > + } > + > if (acpi_get_mcfg(&mcfg)) { > acpi_add_table(table_offsets, tables_blob); > build_mcfg(tables_blob, tables->linker, &mcfg); > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > index ac08e63604..af984ee041 100644 > --- a/hw/i386/pc.c > +++ b/hw/i386/pc.c > @@ -84,6 +84,7 @@ > #include "hw/net/ne2000-isa.h" > #include "standard-headers/asm-x86/bootparam.h" > #include "hw/virtio/virtio-pmem-pci.h" > +#include "hw/virtio/virtio-iommu.h" > #include "hw/mem/memory-device.h" > #include "sysemu/replay.h" > #include "qapi/qmp/qerror.h" > @@ -1940,6 +1941,11 @@ static void > pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, > pc_cpu_pre_plug(hotplug_dev, dev, errp); > } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { > pc_virtio_pmem_pci_pre_plug(hotplug_dev, dev, errp); > + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { > + /* we declare a VIRTIO_IOMMU_RESV_MEM_T_MSI region */ > + qdev_prop_set_uint32(dev, "len-reserved-regions", 1); > + qdev_prop_set_string(dev, "reserved-regions[0]", > + "0xfee00000, 0xfeefffff, 1"); > } > } > > @@ -1952,6 +1958,12 @@ static void pc_machine_device_plug_cb(HotplugHandler > *hotplug_dev, > pc_cpu_plug(hotplug_dev, dev, errp); > } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { > pc_virtio_pmem_pci_plug(hotplug_dev, dev, errp); > + } else if (object_dynamic_cast(OBJECT(dev), "virtio-iommu-pci")) { > + PCMachineState *pcms = PC_MACHINE(hotplug_dev); > + PCIDevice *pdev = PCI_DEVICE(dev); > + > + pcms->virtio_iommu = true; > + pcms->virtio_iommu_bdf = pci_get_bdf(pdev); > } > } > > @@ -1990,7 +2002,8 @@ static HotplugHandler > *pc_get_hotplug_handler(MachineState *machine, > { > if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || > object_dynamic_cast(OBJECT(dev), TYPE_CPU) || > - object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI)) { > + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || > + object_dynamic_cast(OBJECT(dev), "virtio-iommu-pci")) { > return HOTPLUG_HANDLER(machine); > } > > diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h > index 1f86eba3f9..221b4c6ef9 100644 > --- a/include/hw/i386/pc.h > +++ b/include/hw/i386/pc.h > @@ -49,6 +49,8 @@ struct PCMachineState { > bool smbus_enabled; > bool sata_enabled; > bool pit_enabled; > + bool virtio_iommu; > + uint16_t virtio_iommu_bdf; > > /* NUMA information: */ > uint64_t numa_nodes; > -- > 2.20.1