hw/i386/acpi-build: Add DMAR support to bypass iommu
In DMAR table, the drhd is set to cover all PCI devices when intel_iommu is on. To support bypass iommu feature, we need to walk the PCI bus with bypass_iommu disabled and add explicit scope data in DMAR drhd structure. /mnt/sdb/wxg/qemu-next/qemu/build/x86_64-softmmu/qemu-system-x86_64 \ -machine q35,accel=kvm,default_bus_bypass_iommu=true \ -cpu host \ -m 16G \ -smp 36,sockets=2,cores=18,threads=1 \ -device pxb-pcie,bus_nr=0x10,id=pci.10,bus=pcie.0,addr=0x3 \ -device pxb-pcie,bus_nr=0x20,id=pci.20,bus=pcie.0,addr=0x4,bypass_iommu=true \ -device pcie-root-port,port=0x1,chassis=1,id=pci.11,bus=pci.10,addr=0x0 \ -device pcie-root-port,port=0x2,chassis=2,id=pci.21,bus=pci.20,addr=0x0 \ -device virtio-scsi-pci,id=scsi0,bus=pci.11,addr=0x0 \ -device virtio-scsi-pci,id=scsi1,bus=pci.21,addr=0x0 \ -drive file=/mnt/sdb/wxg/fedora-48g.qcow2,format=qcow2,if=none,id=drive-scsi0-0-0-0,cache=none,aio=native \ -device scsi-hd,bus=scsi1.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0,bootindex=1 \ -device intel-iommu \ -nographic \ And we get the guest configuration: ~ lspci -vt -+-[0000:20]---00.0-[21]----00.0 Red Hat, Inc. Virtio SCSI +-[0000:10]---00.0-[11]----00.0 Red Hat, Inc. Virtio SCSI \-[0000:00]-+-00.0 Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller +-01.0 Device 1234:1111 +-02.0 Intel Corporation 82574L Gigabit Network Connection +-03.0 Red Hat, Inc. QEMU PCIe Expander bridge +-04.0 Red Hat, Inc. QEMU PCIe Expander bridge +-1f.0 Intel Corporation 82801IB (ICH9) LPC Interface Controller +-1f.2 Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] \-1f.3 Intel Corporation 82801I (ICH9 Family) SMBus Controller With bypass_iommu enabled on root bus, the attached devices will bypass iommu: /sys/class/iommu/dmar0 ├── devices │ ├── 0000:10:00.0 -> ../../../../pci0000:10/0000:10:00.0 │ └── 0000:11:00.0 -> ../../../../pci0000:10/0000:10:00.0/0000:11:00.0 Signed-off-by: Xingang Wang <wangxingang5@huawei.com> Message-Id: <1625748919-52456-8-git-send-email-wangxingang5@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
42e0f050e3
commit
26863366b2
@ -2022,6 +2022,56 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
x86ms->oem_table_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert DMAR scope for PCI bridges and endpoint devcie
|
||||
*/
|
||||
static void
|
||||
insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque)
|
||||
{
|
||||
GArray *scope_blob = opaque;
|
||||
AcpiDmarDeviceScope *scope = NULL;
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
|
||||
/* Dmar Scope Type: 0x02 for PCI Bridge */
|
||||
build_append_int_noprefix(scope_blob, 0x02, 1);
|
||||
} else {
|
||||
/* Dmar Scope Type: 0x01 for PCI Endpoint Device */
|
||||
build_append_int_noprefix(scope_blob, 0x01, 1);
|
||||
}
|
||||
|
||||
/* length */
|
||||
build_append_int_noprefix(scope_blob,
|
||||
sizeof(*scope) + sizeof(scope->path[0]), 1);
|
||||
/* reserved */
|
||||
build_append_int_noprefix(scope_blob, 0, 2);
|
||||
/* enumeration_id */
|
||||
build_append_int_noprefix(scope_blob, 0, 1);
|
||||
/* bus */
|
||||
build_append_int_noprefix(scope_blob, pci_bus_num(bus), 1);
|
||||
/* device */
|
||||
build_append_int_noprefix(scope_blob, PCI_SLOT(dev->devfn), 1);
|
||||
/* function */
|
||||
build_append_int_noprefix(scope_blob, PCI_FUNC(dev->devfn), 1);
|
||||
}
|
||||
|
||||
/* For a given PCI host bridge, walk and insert DMAR scope */
|
||||
static int
|
||||
dmar_host_bridges(Object *obj, void *opaque)
|
||||
{
|
||||
GArray *scope_blob = opaque;
|
||||
|
||||
if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) {
|
||||
PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus;
|
||||
|
||||
if (bus && !pci_bus_bypass_iommu(bus)) {
|
||||
pci_for_each_device(bus, pci_bus_num(bus), insert_scope,
|
||||
scope_blob);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* VT-d spec 8.1 DMA Remapping Reporting Structure
|
||||
* (version Oct. 2014 or later)
|
||||
@ -2041,6 +2091,15 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
/* Root complex IOAPIC use one path[0] only */
|
||||
size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
|
||||
IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
|
||||
GArray *scope_blob = g_array_new(false, true, 1);
|
||||
|
||||
/*
|
||||
* A PCI bus walk, for each PCI host bridge.
|
||||
* Insert scope for each PCI bridge and endpoint device which
|
||||
* is attached to a bus with iommu enabled.
|
||||
*/
|
||||
object_child_foreach_recursive(object_get_root(),
|
||||
dmar_host_bridges, scope_blob);
|
||||
|
||||
assert(iommu);
|
||||
if (x86_iommu_ir_supported(iommu)) {
|
||||
@ -2054,8 +2113,9 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
/* DMAR Remapping Hardware Unit Definition structure */
|
||||
drhd = acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size);
|
||||
drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
|
||||
drhd->length = cpu_to_le16(sizeof(*drhd) + ioapic_scope_size);
|
||||
drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
|
||||
drhd->length =
|
||||
cpu_to_le16(sizeof(*drhd) + ioapic_scope_size + scope_blob->len);
|
||||
drhd->flags = 0; /* Don't include all pci device */
|
||||
drhd->pci_segment = cpu_to_le16(0);
|
||||
drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
|
||||
|
||||
@ -2069,6 +2129,10 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
scope->path[0].device = PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC);
|
||||
scope->path[0].function = PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC);
|
||||
|
||||
/* Add scope found above */
|
||||
g_array_append_vals(table_data, scope_blob->data, scope_blob->len);
|
||||
g_array_free(scope_blob, true);
|
||||
|
||||
if (iommu->dt_supported) {
|
||||
atsr = acpi_data_push(table_data, sizeof(*atsr));
|
||||
atsr->type = cpu_to_le16(ACPI_DMAR_TYPE_ATSR);
|
||||
|
Loading…
Reference in New Issue
Block a user