Message ID | 20211020172745.620101-5-jean-philippe@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | virtio-iommu: Add ACPI support | expand |
On Wed, 20 Oct 2021 18:27:38 +0100 Jean-Philippe Brucker <jean-philippe@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.auger@redhat.com> > Tested-by: Eric Auger <eric.auger@redhat.com> > Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Reviewed-by: Igor Mammedov <imammedo@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
On Thu, Oct 21, 2021 at 03:47:09PM +0200, Igor Mammedov wrote: > On Wed, 20 Oct 2021 18:27:38 +0100 > Jean-Philippe Brucker <jean-philippe@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"? No it is IRQ remapping: DMA writes to this address range are interrupt requests and the IOMMU may either perform interrupt remapping or pass it to the APIC directly > > > 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.auger@redhat.com> > > Tested-by: Eric Auger <eric.auger@redhat.com> > > Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> > > Reviewed-by: Igor Mammedov <imammedo@redhat.com> Thanks! Jean
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