[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH for-5.0 v11 19/20] pc: Add support for virtio-iommu-pci
From: |
Eric Auger |
Subject: |
[PATCH for-5.0 v11 19/20] pc: Add support for virtio-iommu-pci |
Date: |
Fri, 22 Nov 2019 19:29:42 +0100 |
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 <address@hidden>
---
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
- [PATCH for-5.0 v11 12/20] qapi: Introduce DEFINE_PROP_INTERVAL, (continued)
- [PATCH for-5.0 v11 12/20] qapi: Introduce DEFINE_PROP_INTERVAL, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 13/20] virtio-iommu: Implement probe request, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 14/20] virtio-iommu: Handle reserved regions in the translation process, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 15/20] virtio-iommu-pci: Add array of Interval properties, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 16/20] hw/arm/virt-acpi-build: Introduce fill_iort_idmap helper, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 17/20] hw/arm/virt-acpi-build: Add virtio-iommu node in IORT table, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 18/20] virtio-iommu: Support migration, Eric Auger, 2019/11/22
- [PATCH for-5.0 v11 19/20] pc: Add support for virtio-iommu-pci,
Eric Auger <=
- [PATCH for-5.0 v11 20/20] tests: Add virtio-iommu test, Eric Auger, 2019/11/22
- Re: [PATCH for-5.0 v11 00/20] VIRTIO-IOMMU device, no-reply, 2019/11/22