On Wed, 20 Oct 2021 18:27:38 +0100 Jean-Philippe Brucker <jean-phili...@linaro.org> wrote:
> Allow instantiating a virtio-iommu device by adding an ACPI Virtual I/O > Translation table (VIOT), which describes the relation between the > virtio-iommu and the endpoints it manages. > > Add a hotplug handler for virtio-iommu on x86 and set the necessary > reserved region property. On x86, the [0xfee00000, 0xfeefffff] DMA > region is reserved for MSIs. DMA transactions to this range either > trigger IRQ remapping in the IOMMU or bypasses IOMMU translation. shouldn't above be "IO remapping"? > Although virtio-iommu does not support IRQ remapping it must be informed > of the reserved region so that it can forward DMA transactions targeting > this region. > > Reviewed-by: Eric Auger <eric.au...@redhat.com> > Tested-by: Eric Auger <eric.au...@redhat.com> > Signed-off-by: Jean-Philippe Brucker <jean-phili...@linaro.org> Reviewed-by: Igor Mammedov <imamm...@redhat.com> > --- > hw/i386/acpi-build.c | 10 +++++++++- > hw/i386/pc.c | 16 +++++++++++++++- > hw/i386/Kconfig | 1 + > 3 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index ab49e799ff..3ca6cc8118 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -68,9 +68,11 @@ > #include "qom/qom-qobject.h" > #include "hw/i386/amd_iommu.h" > #include "hw/i386/intel_iommu.h" > +#include "hw/virtio/virtio-iommu.h" > > #include "hw/acpi/ipmi.h" > #include "hw/acpi/hmat.h" > +#include "hw/acpi/viot.h" > > /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and > * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows > @@ -2488,7 +2490,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState > *machine) > PCMachineState *pcms = PC_MACHINE(machine); > PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); > X86MachineState *x86ms = X86_MACHINE(machine); > - X86IOMMUState *iommu = x86_iommu_get_default(); > + DeviceState *iommu = pcms->iommu; > GArray *table_offsets; > unsigned facs, dsdt, rsdt, fadt; > AcpiPmInfo pm; > @@ -2613,6 +2615,12 @@ void acpi_build(AcpiBuildTables *tables, MachineState > *machine) > acpi_add_table(table_offsets, tables_blob); > build_dmar_q35(tables_blob, tables->linker, x86ms->oem_id, > x86ms->oem_table_id); > + } else if (object_dynamic_cast(OBJECT(iommu), TYPE_VIRTIO_IOMMU_PCI)) { > + PCIDevice *pdev = PCI_DEVICE(iommu); > + > + acpi_add_table(table_offsets, tables_blob); > + build_viot(machine, tables_blob, tables->linker, pci_get_bdf(pdev), > + x86ms->oem_id, x86ms->oem_table_id); > } > if (machine->nvdimms_state->is_enabled) { > nvdimm_build_acpi(table_offsets, tables_blob, tables->linker, > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > index fcbf328e8d..f47f7866c7 100644 > --- a/hw/i386/pc.c > +++ b/hw/i386/pc.c > @@ -83,6 +83,7 @@ > #include "hw/i386/intel_iommu.h" > #include "hw/net/ne2000-isa.h" > #include "standard-headers/asm-x86/bootparam.h" > +#include "hw/virtio/virtio-iommu.h" > #include "hw/virtio/virtio-pmem-pci.h" > #include "hw/virtio/virtio-mem-pci.h" > #include "hw/mem/memory-device.h" > @@ -1330,7 +1331,19 @@ static void > pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, > } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || > object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { > pc_virtio_md_pci_pre_plug(hotplug_dev, dev, errp); > - } else if (object_dynamic_cast(OBJECT(dev), TYPE_X86_IOMMU_DEVICE)) { > + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { > + /* Declare the APIC range as the reserved MSI region */ > + char *resv_prop_str = g_strdup_printf("0xfee00000:0xfeefffff:%d", > + VIRTIO_IOMMU_RESV_MEM_T_MSI); > + > + object_property_set_uint(OBJECT(dev), "len-reserved-regions", 1, > errp); > + object_property_set_str(OBJECT(dev), "reserved-regions[0]", > + resv_prop_str, errp); > + g_free(resv_prop_str); > + } > + > + if (object_dynamic_cast(OBJECT(dev), TYPE_X86_IOMMU_DEVICE) || > + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { > PCMachineState *pcms = PC_MACHINE(hotplug_dev); > > if (pcms->iommu) { > @@ -1394,6 +1407,7 @@ static HotplugHandler > *pc_get_hotplug_handler(MachineState *machine, > object_dynamic_cast(OBJECT(dev), TYPE_CPU) || > object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_PMEM_PCI) || > object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI) || > + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) || > object_dynamic_cast(OBJECT(dev), TYPE_X86_IOMMU_DEVICE)) { > return HOTPLUG_HANDLER(machine); > } > diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig > index 962d2c981b..d22ac4a4b9 100644 > --- a/hw/i386/Kconfig > +++ b/hw/i386/Kconfig > @@ -59,6 +59,7 @@ config PC_ACPI > select ACPI_X86 > select ACPI_CPU_HOTPLUG > select ACPI_MEMORY_HOTPLUG > + select ACPI_VIOT > select SMBUS_EEPROM > select PFLASH_CFI01 > depends on ACPI_SMBUS