From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6037EC433ED for ; Wed, 21 Apr 2021 08:12:57 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 887A26102A for ; Wed, 21 Apr 2021 08:12:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 887A26102A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=huawei.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59252 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lZ7yd-0001uv-NL for qemu-devel@archiver.kernel.org; Wed, 21 Apr 2021 04:12:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51930) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lZ7rc-0001Ct-E2; Wed, 21 Apr 2021 04:05:36 -0400 Received: from szxga06-in.huawei.com ([45.249.212.32]:5037) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lZ7rZ-00023u-V6; Wed, 21 Apr 2021 04:05:36 -0400 Received: from DGGEMS411-HUB.china.huawei.com (unknown [172.30.72.60]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4FQCjW4m1pzlYc2; Wed, 21 Apr 2021 16:03:27 +0800 (CST) Received: from huawei.com (10.174.185.226) by DGGEMS411-HUB.china.huawei.com (10.3.19.211) with Microsoft SMTP Server id 14.3.498.0; Wed, 21 Apr 2021 16:05:17 +0800 From: Wang Xingang To: , , , , , , , , , , Subject: [PATCH RFC v3 6/8] hw/arm/virt-acpi-build: Add explicit IORT idmap for smmuv3 node Date: Wed, 21 Apr 2021 08:05:01 +0000 Message-ID: <1618992303-19556-7-git-send-email-wangxingang5@huawei.com> X-Mailer: git-send-email 2.6.4.windows.1 In-Reply-To: <1618992303-19556-1-git-send-email-wangxingang5@huawei.com> References: <1618992303-19556-1-git-send-email-wangxingang5@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.174.185.226] X-CFilter-Loop: Reflected Received-SPF: pass client-ip=45.249.212.32; envelope-from=wangxingang5@huawei.com; helo=szxga06-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_H3=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, cenjiahui@huawei.com, wangxingang5@huawei.com Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" From: Xingang Wang This add explicit IORT idmap info according to pci root bus number range, and only add smmu idmap for those which does not bypass iommu. For idmap directly to ITS node, this split the whole RID mapping to smmu idmap and its idmap. So this should cover the whole idmap for through/bypass SMMUv3 node. Signed-off-by: Xingang Wang Signed-off-by: Jiahui Cen --- hw/arm/virt-acpi-build.c | 128 +++++++++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 19 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 60fe2e65a7..661b84edec 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -44,6 +44,7 @@ #include "hw/acpi/tpm.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" #include "hw/pci-host/gpex.h" #include "hw/arm/virt.h" #include "hw/mem/nvdimm.h" @@ -237,6 +238,41 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) aml_append(scope, dev); } +/* Build the iort ID mapping to SMMUv3 for a given PCI host bridge */ +static int +iort_host_bridges(Object *obj, void *opaque) +{ + GArray *idmap_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)) { + int min_bus, max_bus; + pci_bus_range(bus, &min_bus, &max_bus); + + AcpiIortIdMapping idmap = { + .input_base = cpu_to_le32(min_bus << 8), + .id_count = cpu_to_le32((max_bus - min_bus + 1) << 8), + .output_base = cpu_to_le32(min_bus << 8), + .output_reference = cpu_to_le32(0), + .flags = cpu_to_le32(0), + }; + g_array_append_val(idmap_blob, idmap); + } + } + + return 0; +} + +static int smmu_idmap_sort_func(gconstpointer a, gconstpointer b) +{ + AcpiIortIdMapping *idmap_a = (AcpiIortIdMapping *)a; + AcpiIortIdMapping *idmap_b = (AcpiIortIdMapping *)b; + + return idmap_a->input_base - idmap_b->input_base; +} + static void build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { @@ -247,6 +283,45 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) AcpiIortSmmu3 *smmu; size_t node_size, iort_node_offset, iort_length, smmu_offset = 0; AcpiIortRC *rc; + uint32_t base, i, rc_map_count; + GArray *smmu_idmap_blob = + g_array_new(false, true, sizeof(AcpiIortIdMapping)); + GArray *its_idmap_blob = + g_array_new(false, true, sizeof(AcpiIortIdMapping)); + + object_child_foreach_recursive(object_get_root(), + iort_host_bridges, smmu_idmap_blob); + + g_array_sort(smmu_idmap_blob, smmu_idmap_sort_func); + + /* Build the iort ID mapping to ITS directly */ + i = 0, base = 0; + while (base < 0xFFFF && i <= smmu_idmap_blob->len) { + AcpiIortIdMapping new_idmap = { + .input_base = cpu_to_le32(base), + .id_count = cpu_to_le32(0), + .output_base = cpu_to_le32(base), + .output_reference = cpu_to_le32(0), + .flags = cpu_to_le32(0), + }; + + if (i == smmu_idmap_blob->len) { + if (base < 0xFFFF) { + new_idmap.id_count = cpu_to_le32(0xFFFF - base); + g_array_append_val(its_idmap_blob, new_idmap); + } + break; + } + + idmap = &g_array_index(smmu_idmap_blob, AcpiIortIdMapping, i); + if (base < idmap->input_base) { + new_idmap.id_count = cpu_to_le32(idmap->input_base - base); + g_array_append_val(its_idmap_blob, new_idmap); + } + + i++; + base = idmap->input_base + idmap->id_count; + } iort = acpi_data_push(table_data, sizeof(*iort)); @@ -280,13 +355,13 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) /* SMMUv3 node */ smmu_offset = iort_node_offset + node_size; - node_size = sizeof(*smmu) + sizeof(*idmap); + node_size = sizeof(*smmu) + sizeof(*idmap) * smmu_idmap_blob->len; iort_length += node_size; smmu = acpi_data_push(table_data, node_size); smmu->type = ACPI_IORT_NODE_SMMU_V3; smmu->length = cpu_to_le16(node_size); - smmu->mapping_count = cpu_to_le32(1); + smmu->mapping_count = cpu_to_le32(smmu_idmap_blob->len); smmu->mapping_offset = cpu_to_le32(sizeof(*smmu)); smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base); smmu->flags = cpu_to_le32(ACPI_IORT_SMMU_V3_COHACC_OVERRIDE); @@ -295,23 +370,24 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) smmu->sync_gsiv = cpu_to_le32(irq + 2); smmu->gerr_gsiv = cpu_to_le32(irq + 3); - /* Identity RID mapping covering the whole input RID range */ - idmap = &smmu->id_mapping_array[0]; - idmap->input_base = 0; - idmap->id_count = cpu_to_le32(0xFFFF); - idmap->output_base = 0; - /* output IORT node is the ITS group node (the first node) */ - idmap->output_reference = cpu_to_le32(iort_node_offset); + for (i = 0; i < smmu_idmap_blob->len; i++) { + idmap = &smmu->id_mapping_array[i]; + *idmap = g_array_index(smmu_idmap_blob, AcpiIortIdMapping, i); + /* output IORT node is the ITS group node (the first node) */ + idmap->output_reference = cpu_to_le32(iort_node_offset); + } } /* Root Complex Node */ - node_size = sizeof(*rc) + sizeof(*idmap); + rc_map_count = (vms->iommu == VIRT_IOMMU_SMMUV3) ? + smmu_idmap_blob->len + its_idmap_blob->len : 1; + node_size = sizeof(*rc) + sizeof(*idmap) * rc_map_count; iort_length += node_size; rc = acpi_data_push(table_data, node_size); rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX; rc->length = cpu_to_le16(node_size); - rc->mapping_count = cpu_to_le32(1); + rc->mapping_count = cpu_to_le32(rc_map_count); rc->mapping_offset = cpu_to_le32(sizeof(*rc)); /* fully coherent device */ @@ -319,20 +395,34 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) rc->memory_properties.memory_flags = 0x3; /* CCA = CPM = DCAS = 1 */ rc->pci_segment_number = 0; /* MCFG pci_segment */ - /* Identity RID mapping covering the whole input RID range */ - idmap = &rc->id_mapping_array[0]; - idmap->input_base = 0; - idmap->id_count = cpu_to_le32(0xFFFF); - idmap->output_base = 0; - if (vms->iommu == VIRT_IOMMU_SMMUV3) { - /* output IORT node is the smmuv3 node */ - idmap->output_reference = cpu_to_le32(smmu_offset); + for (i = 0; i < rc_map_count; i++) { + idmap = &rc->id_mapping_array[i]; + + if (i < smmu_idmap_blob->len) { + *idmap = g_array_index(smmu_idmap_blob, AcpiIortIdMapping, i); + /* output IORT node is the smmuv3 node */ + idmap->output_reference = cpu_to_le32(smmu_offset); + } else { + *idmap = g_array_index(its_idmap_blob, + AcpiIortIdMapping, i - smmu_idmap_blob->len); + /* output IORT node is the ITS group node (the first node) */ + idmap->output_reference = cpu_to_le32(iort_node_offset); + } + } } else { + /* Identity RID mapping covering the whole input RID range */ + idmap = &rc->id_mapping_array[0]; + idmap->input_base = cpu_to_le32(0); + idmap->id_count = cpu_to_le32(0xFFFF); + idmap->output_base = cpu_to_le32(0); /* output IORT node is the ITS group node (the first node) */ idmap->output_reference = cpu_to_le32(iort_node_offset); } + g_array_free(smmu_idmap_blob, true); + g_array_free(its_idmap_blob, true); + /* * Update the pointer address in case table_data->data moves during above * acpi_data_push operations. -- 2.19.1