From patchwork Fri Nov 9 12:02:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yu Zhang X-Patchwork-Id: 10675819 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4FA255A4 for ; Fri, 9 Nov 2018 12:04:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A92F2E4D2 for ; Fri, 9 Nov 2018 12:04:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2EC5A2EA8E; Fri, 9 Nov 2018 12:04:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A70612E4D2 for ; Fri, 9 Nov 2018 12:04:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728130AbeKIVpF (ORCPT ); Fri, 9 Nov 2018 16:45:05 -0500 Received: from mga05.intel.com ([192.55.52.43]:57280 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727742AbeKIVpF (ORCPT ); Fri, 9 Nov 2018 16:45:05 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Nov 2018 04:04:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,483,1534834800"; d="scan'208";a="98940257" Received: from zhangyu-optiplex-9020.bj.intel.com ([10.238.135.159]) by orsmga003.jf.intel.com with ESMTP; 09 Nov 2018 04:04:43 -0800 From: Yu Zhang To: kvm@vger.kernel.org Cc: peterx@redhat.com, pbonzini@redhat.com, ehabkost@redhat.com, mst@redhat.com Subject: [kvm-unit-tests PATCH] x86/intel-iommu: add test for address width 48 and 57. Date: Fri, 9 Nov 2018 20:02:40 +0800 Message-Id: <1541764960-11322-1-git-send-email-yu.c.zhang@linux.intel.com> X-Mailer: git-send-email 1.9.1 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current iommu test only covers 39-bit address width. This patch extends the test case to based on the supported maximum guest address width. Signed-off-by: Yu Zhang Reviewed-by: Michael S. Tsirkin Reviewed-by: Peter Xu --- lib/x86/intel-iommu.c | 14 ++++---------- lib/x86/intel-iommu.h | 11 ++++++++++- x86/intel-iommu.c | 21 ++++++++++++++++----- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c index 3f3f211..e1ea9d2 100644 --- a/lib/x86/intel-iommu.c +++ b/lib/x86/intel-iommu.c @@ -16,13 +16,6 @@ #include "atomic.h" #include "alloc_page.h" -/* - * VT-d in QEMU currently only support 39 bits address width, which is - * 3-level translation. - */ -#define VTD_PAGE_LEVEL 3 -#define VTD_CE_AW_39BIT 0x1 - typedef uint64_t vtd_pte_t; struct vtd_root_entry { @@ -75,6 +68,8 @@ typedef struct vtd_irte vtd_irte_t; #define VTD_IRTA_MASK (PAGE_MASK) void *vtd_reg_base; +uint8_t max_gaw; +uint8_t max_page_level; static uint64_t vtd_root_table(void) { @@ -149,7 +144,7 @@ static void vtd_install_pte(vtd_pte_t *root, iova_t iova, unsigned int offset; void *page; - for (level = VTD_PAGE_LEVEL; level > level_target; level--) { + for (level = max_page_level; level > level_target; level--) { offset = PGDIR_OFFSET(iova, level); if (!(root[offset] & VTD_PTE_RW)) { page = alloc_page(); @@ -213,8 +208,7 @@ void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size) memset(ce, 0, sizeof(*ce)); /* To make it simple, domain ID is the same as SID */ ce->domain_id = sid; - /* We only test 39 bits width case (3-level paging) */ - ce->addr_width = VTD_CE_AW_39BIT; + ce->addr_width = max_page_level - 2; ce->slptptr = virt_to_phys(slptptr) >> VTD_PAGE_SHIFT; ce->trans_type = VTD_CONTEXT_TT_MULTI_LEVEL; ce->present = 1; diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h index 05b9744..7057417 100644 --- a/lib/x86/intel-iommu.h +++ b/lib/x86/intel-iommu.h @@ -26,6 +26,7 @@ #define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL #define VTD_PAGE_SHIFT PAGE_SHIFT #define VTD_PAGE_SIZE PAGE_SIZE +#define VTD_PAGE_LEVEL_STRIDE 9 /* * Intel IOMMU register specification @@ -100,7 +101,13 @@ #define VTD_CAP_SAGAW_39bit (0x2ULL << VTD_CAP_SAGAW_SHIFT) /* 48-bit AGAW, 4-level page-table */ #define VTD_CAP_SAGAW_48bit (0x4ULL << VTD_CAP_SAGAW_SHIFT) -#define VTD_CAP_SAGAW VTD_CAP_SAGAW_39bit +/* 57-bit AGAW, 5-level page-table */ +#define VTD_CAP_SAGAW_57bit (0x8ULL << VTD_CAP_SAGAW_SHIFT) +#define VTD_CAP_SAGAW(cap) (((cap) >> VTD_CAP_SAGAW_SHIFT) & 0x1fULL) + +/* Maximum Guest Address Widths */ +#define VTD_CAP_MGAW_SHIFT 16 +#define VTD_CAP_MGAW(cap) ((((cap) >> VTD_CAP_MGAW_SHIFT) & 0x3fULL) + 1) /* Both 1G/2M huge pages */ #define VTD_CAP_SLLPS ((1ULL << 34) | (1ULL << 35)) @@ -118,6 +125,8 @@ extern void *vtd_reg_base; #define vtd_reg(reg) ({ assert(vtd_reg_base); \ (volatile void *)(vtd_reg_base + reg); }) +extern uint8_t max_gaw; +extern uint8_t max_page_level; static inline void vtd_writel(unsigned int reg, uint32_t value) { diff --git a/x86/intel-iommu.c b/x86/intel-iommu.c index f24170d..9d2194d 100644 --- a/x86/intel-iommu.c +++ b/x86/intel-iommu.c @@ -132,25 +132,36 @@ static void vtd_test_ir(void) int main(int argc, char *argv[]) { + uint64_t dmar_cap; + uint8_t sagaw; + setup_vm(); smp_init(); - vtd_init(); report_prefix_push("vtd_init"); - report("fault status check", vtd_readl(DMAR_FSTS_REG) == 0); report("QI enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_QI); report("DMAR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_ROOT); report("IR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR_TABLE); report("DMAR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_DMAR); report("IR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR); - report("DMAR support 39 bits address width", - vtd_readq(DMAR_CAP_REG) & VTD_CAP_SAGAW); report("DMAR support huge pages", vtd_readq(DMAR_CAP_REG) & VTD_CAP_SLLPS); - report_prefix_pop(); + dmar_cap = vtd_readq(DMAR_CAP_REG); + max_gaw = VTD_CAP_MGAW(dmar_cap); + sagaw = VTD_CAP_SAGAW(dmar_cap); + max_page_level = (max_gaw - VTD_PAGE_SHIFT)/VTD_PAGE_LEVEL_STRIDE; + + report("address width check", ((1 << (max_page_level - 2)) & sagaw)); + if (dmar_cap & VTD_CAP_SAGAW_39bit) + printf("DMAR supports 39 bits address width.\n"); + if (dmar_cap & VTD_CAP_SAGAW_48bit) + printf("DMAR supports 48 bits address width.\n"); + if (dmar_cap & VTD_CAP_SAGAW_57bit) + printf("DMAR supports 57 bits address width.\n"); + if (!edu_init(&edu_dev)) { printf("Please specify \"-device edu\" to do " "further IOMMU tests.\n");