Hi Michael, On 1/9/20 1:02 PM, Michael S. Tsirkin wrote: > 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?
Yes I am about to send v12. Indeed I hope the DT integration in ARM virt can land in 5.0. All the kernel dependencies are resolved and it complies with the voted spec. Then I will push the non DT integration when Jean's series get stabilized and spec updated. Thanks Eric > >> --- >> 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 >