From nobody Mon Feb 9 20:34:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=huawei.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1625749060402558.8616225967979; Thu, 8 Jul 2021 05:57:40 -0700 (PDT) Received: from localhost ([::1]:53852 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m1Tb0-00078v-Rs for importer@patchew.org; Thu, 08 Jul 2021 08:57:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41302) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1TZI-0004LM-OF; Thu, 08 Jul 2021 08:55:53 -0400 Received: from szxga03-in.huawei.com ([45.249.212.189]:2189) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m1TZE-0005bS-Qj; Thu, 08 Jul 2021 08:55:52 -0400 Received: from dggemv711-chm.china.huawei.com (unknown [172.30.72.53]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4GLGPT3y4dz77Qk; Thu, 8 Jul 2021 20:51:09 +0800 (CST) Received: from dggpemm500009.china.huawei.com (7.185.36.225) by dggemv711-chm.china.huawei.com (10.1.198.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Thu, 8 Jul 2021 20:55:32 +0800 Received: from huawei.com (10.174.185.226) by dggpemm500009.china.huawei.com (7.185.36.225) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Thu, 8 Jul 2021 20:55:31 +0800 From: Wang Xingang To: , , , , , , , , , , Subject: [PATCH v5 7/9] hw/i386/acpi-build: Add DMAR support to bypass iommu Date: Thu, 8 Jul 2021 12:55:17 +0000 Message-ID: <1625748919-52456-8-git-send-email-wangxingang5@huawei.com> X-Mailer: git-send-email 2.6.4.windows.1 In-Reply-To: <1625748919-52456-1-git-send-email-wangxingang5@huawei.com> References: <1625748919-52456-1-git-send-email-wangxingang5@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.174.185.226] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To dggpemm500009.china.huawei.com (7.185.36.225) X-CFilter-Loop: Reflected Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=45.249.212.189; envelope-from=wangxingang5@huawei.com; helo=szxga03-in.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: xieyingtai@huawei.com, wangxingang5@huawei.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1625749062543100005 From: Xingang Wang 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=3Dkvm,default_bus_bypass_iommu=3Dtrue \ -cpu host \ -m 16G \ -smp 36,sockets=3D2,cores=3D18,threads=3D1 \ -device pxb-pcie,bus_nr=3D0x10,id=3Dpci.10,bus=3Dpcie.0,addr=3D0x3 \ -device pxb-pcie,bus_nr=3D0x20,id=3Dpci.20,bus=3Dpcie.0,addr=3D0x4,bypass_= iommu=3Dtrue \ -device pcie-root-port,port=3D0x1,chassis=3D1,id=3Dpci.11,bus=3Dpci.10,add= r=3D0x0 \ -device pcie-root-port,port=3D0x2,chassis=3D2,id=3Dpci.21,bus=3Dpci.20,add= r=3D0x0 \ -device virtio-scsi-pci,id=3Dscsi0,bus=3Dpci.11,addr=3D0x0 \ -device virtio-scsi-pci,id=3Dscsi1,bus=3Dpci.21,addr=3D0x0 \ -drive file=3D/mnt/sdb/wxg/fedora-48g.qcow2,format=3Dqcow2,if=3Dnone,id=3D= drive-scsi0-0-0-0,cache=3Dnone,aio=3Dnative \ -device scsi-hd,bus=3Dscsi1.0,channel=3D0,scsi-id=3D0,lun=3D0,drive=3Ddriv= e-scsi0-0-0-0,id=3Dscsi0-0-0-0,bootindex=3D1 \ -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 Contr= oller +-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 Control= ler +-1f.2 Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port S= ATA Controller [AHCI mode] \-1f.3 Intel Corporation 82801I (ICH9 Family) SMBus Controller With bypass_iommu enabled on root bus, the attached devices will bypass iom= mu: /sys/class/iommu/dmar0 =E2=94=9C=E2=94=80=E2=94=80 devices =E2=94=82=C2=A0=C2=A0 =E2=94=9C=E2=94=80=E2=94=80 0000:10:00.0 -> ../../../= ../pci0000:10/0000:10:00.0 =E2=94=82=C2=A0=C2=A0 =E2=94=94=E2=94=80=E2=94=80 0000:11:00.0 -> ../../../= ../pci0000:10/0000:10:00.0/0000:11:00.0 Signed-off-by: Xingang Wang --- hw/i386/acpi-build.c | 68 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 796ffc6f5c..1b972b4913 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2005,6 +2005,56 @@ build_srat(GArray *table_data, BIOSLinker *linker, M= achineState *machine) x86ms->oem_table_id); } =20 +/* + * Insert DMAR scope for PCI bridges and endpoint devcie + */ +static void +insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque) +{ + GArray *scope_blob =3D opaque; + AcpiDmarDeviceScope *scope =3D 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 =3D opaque; + + if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) { + PCIBus *bus =3D 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) @@ -2024,6 +2074,15 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linke= r, const char *oem_id, /* Root complex IOAPIC use one path[0] only */ size_t ioapic_scope_size =3D sizeof(*scope) + sizeof(scope->path[0]); IntelIOMMUState *intel_iommu =3D INTEL_IOMMU_DEVICE(iommu); + GArray *scope_blob =3D 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); =20 assert(iommu); if (x86_iommu_ir_supported(iommu)) { @@ -2037,8 +2096,9 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker= , const char *oem_id, /* DMAR Remapping Hardware Unit Definition structure */ drhd =3D acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size); drhd->type =3D cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT); - drhd->length =3D cpu_to_le16(sizeof(*drhd) + ioapic_scope_size); - drhd->flags =3D ACPI_DMAR_INCLUDE_PCI_ALL; + drhd->length =3D + cpu_to_le16(sizeof(*drhd) + ioapic_scope_size + scope_blob->len); + drhd->flags =3D 0; /* Don't include all pci device */ drhd->pci_segment =3D cpu_to_le16(0); drhd->address =3D cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR); =20 @@ -2052,6 +2112,10 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linke= r, const char *oem_id, scope->path[0].device =3D PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC); scope->path[0].function =3D PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC); =20 + /* 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 =3D acpi_data_push(table_data, sizeof(*atsr)); atsr->type =3D cpu_to_le16(ACPI_DMAR_TYPE_ATSR); --=20 2.19.1