From nobody Mon Apr 29 18:43:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510701336934704.9148360518312; Tue, 14 Nov 2017 15:15:36 -0800 (PST) Received: from localhost ([::1]:33956 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEkQP-00052X-Lh for importer@patchew.org; Tue, 14 Nov 2017 18:15:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58022) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEkPF-0004QT-2V for qemu-devel@nongnu.org; Tue, 14 Nov 2017 18:14:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEkP9-0006fV-Pf for qemu-devel@nongnu.org; Tue, 14 Nov 2017 18:14:13 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:43186) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEkP9-0006dL-Di for qemu-devel@nongnu.org; Tue, 14 Nov 2017 18:14:07 -0500 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id vAENE5Bb027437 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 14 Nov 2017 23:14:06 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.14.4/8.14.4) with ESMTP id vAENE3BK009768 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 14 Nov 2017 23:14:04 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id vAENE3V3016954; Tue, 14 Nov 2017 23:14:03 GMT Received: from pslinux.us.oracle.com (/10.129.250.229) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 14 Nov 2017 15:14:03 -0800 From: prasad.singamsetty@oracle.com To: qemu-devel@nongnu.org, pbonzini@redhat.com, rth@twiddle.net, ehabkost@redhat.com, mst@redhat.com, imammedo@redhat.com Date: Tue, 14 Nov 2017 18:13:49 -0500 Message-Id: <20171114231350.286025-2-prasad.singamsetty@oracle.com> X-Mailer: git-send-email 2.14.0-rc1 In-Reply-To: <20171114231350.286025-1-prasad.singamsetty@oracle.com> References: <20171114231350.286025-1-prasad.singamsetty@oracle.com> X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] [fuzzy] X-Received-From: 141.146.126.69 Subject: [Qemu-devel] [PATCH v1 1/2] intel-iommu: Redefine macros to enable supporting 48 bit address width X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peterx@redhat.com, konrad.wilk@oracle.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prasad Singamsetty The current implementation of Intel IOMMU code only supports 39 bits host/iova address width so number of macros use hard coded values based on that. This patch is to redefine them so they can be used with variable address widths. This patch doesn't add any new functionality but enables adding support for 48 bit address width. Signed-off-by: Prasad Singamsetty Reviewed-by: Peter Xu --- hw/i386/intel_iommu.c | 54 ++++++++++++++++++++++++--------------= ---- hw/i386/intel_iommu_internal.h | 34 +++++++++++++++++++------- include/hw/i386/intel_iommu.h | 6 +++-- 3 files changed, 61 insertions(+), 33 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 3a5bb0bc2e..53b3bf244d 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -523,7 +523,7 @@ static inline dma_addr_t vtd_ce_get_slpt_base(VTDContex= tEntry *ce) =20 static inline uint64_t vtd_get_slpte_addr(uint64_t slpte) { - return slpte & VTD_SL_PT_BASE_ADDR_MASK; + return slpte & VTD_SL_PT_BASE_ADDR_MASK(VTD_HOST_ADDRESS_WIDTH); } =20 /* Whether the pte indicates the address of the page frame */ @@ -624,19 +624,12 @@ static inline bool vtd_iova_range_check(uint64_t iova= , VTDContextEntry *ce) return !(iova & ~(vtd_iova_limit(ce) - 1)); } =20 -static const uint64_t vtd_paging_entry_rsvd_field[] =3D { - [0] =3D ~0ULL, - /* For not large page */ - [1] =3D 0x800ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - [2] =3D 0x800ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - [3] =3D 0x800ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - [4] =3D 0x880ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - /* For large page */ - [5] =3D 0x800ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - [6] =3D 0x1ff800ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - [7] =3D 0x3ffff800ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), - [8] =3D 0x880ULL | ~(VTD_HAW_MASK | VTD_SL_IGN_COM), -}; +/* + * Rsvd field masks for spte: + * Index [1] to [4] 4k pages + * Index [5] to [8] large pages + */ +static uint64_t vtd_paging_entry_rsvd_field[9]; =20 static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level) { @@ -874,7 +867,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s,= uint8_t bus_num, return -VTD_FR_ROOT_ENTRY_P; } =20 - if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD)) { + if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD(VTD_HOST_ADDRESS_WIDTH)))= { trace_vtd_re_invalid(re.rsvd, re.val); return -VTD_FR_ROOT_ENTRY_RSVD; } @@ -891,7 +884,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s,= uint8_t bus_num, } =20 if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) || - (ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO)) { + (ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO(VTD_HOST_ADDRESS_WIDTH)= )) { trace_vtd_ce_invalid(ce->hi, ce->lo); return -VTD_FR_CONTEXT_ENTRY_RSVD; } @@ -1207,7 +1200,7 @@ static void vtd_root_table_setup(IntelIOMMUState *s) { s->root =3D vtd_get_quad_raw(s, DMAR_RTADDR_REG); s->root_extended =3D s->root & VTD_RTADDR_RTT; - s->root &=3D VTD_RTADDR_ADDR_MASK; + s->root &=3D VTD_RTADDR_ADDR_MASK(VTD_HOST_ADDRESS_WIDTH); =20 trace_vtd_reg_dmar_root(s->root, s->root_extended); } @@ -1223,7 +1216,7 @@ static void vtd_interrupt_remap_table_setup(IntelIOMM= UState *s) uint64_t value =3D 0; value =3D vtd_get_quad_raw(s, DMAR_IRTA_REG); s->intr_size =3D 1UL << ((value & VTD_IRTA_SIZE_MASK) + 1); - s->intr_root =3D value & VTD_IRTA_ADDR_MASK; + s->intr_root =3D value & VTD_IRTA_ADDR_MASK(VTD_HOST_ADDRESS_WIDTH); s->intr_eime =3D value & VTD_IRTA_EIME; =20 /* Notify global invalidation */ @@ -1479,7 +1472,7 @@ static void vtd_handle_gcmd_qie(IntelIOMMUState *s, b= ool en) trace_vtd_inv_qi_enable(en); =20 if (en) { - s->iq =3D iqa_val & VTD_IQA_IQA_MASK; + s->iq =3D iqa_val & VTD_IQA_IQA_MASK(VTD_HOST_ADDRESS_WIDTH); /* 2^(x+8) entries */ s->iq_size =3D 1UL << ((iqa_val & VTD_IQA_QS) + 8); s->qi_enabled =3D true; @@ -2772,12 +2765,12 @@ static void vtd_address_space_unmap(VTDAddressSpace= *as, IOMMUNotifier *n) * VT-d spec), otherwise we need to consider overflow of 64 bits. */ =20 - if (end > VTD_ADDRESS_SIZE) { + if (end > VTD_ADDRESS_SIZE(VTD_HOST_ADDRESS_WIDTH)) { /* * Don't need to unmap regions that is bigger than the whole * VT-d supported address space size */ - end =3D VTD_ADDRESS_SIZE; + end =3D VTD_ADDRESS_SIZE(VTD_HOST_ADDRESS_WIDTH); } =20 assert(start <=3D end); @@ -2866,6 +2859,7 @@ static void vtd_iommu_replay(IOMMUMemoryRegion *iommu= _mr, IOMMUNotifier *n) static void vtd_init(IntelIOMMUState *s) { X86IOMMUState *x86_iommu =3D X86_IOMMU_DEVICE(s); + uint8_t aw_bits =3D VTD_HOST_ADDRESS_WIDTH; =20 memset(s->csr, 0, DMAR_REG_SIZE); memset(s->wmask, 0, DMAR_REG_SIZE); @@ -2882,10 +2876,24 @@ static void vtd_init(IntelIOMMUState *s) s->qi_enabled =3D false; s->iq_last_desc_type =3D VTD_INV_DESC_NONE; s->next_frcd_reg =3D 0; - s->cap =3D VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND | VTD_CAP_MGAW | - VTD_CAP_SAGAW | VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS; + s->cap =3D VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND | + VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS | + VTD_CAP_SAGAW_39bit | VTD_CAP_MGAW(VTD_HOST_ADDRESS_WIDTH); s->ecap =3D VTD_ECAP_QI | VTD_ECAP_IRO; =20 + /* + * Rsvd field masks for spte + */ + vtd_paging_entry_rsvd_field[0] =3D ~0ULL; + vtd_paging_entry_rsvd_field[1] =3D VTD_SPTE_PAGE_L1_RSVD_MASK(aw_bits); + vtd_paging_entry_rsvd_field[2] =3D VTD_SPTE_PAGE_L2_RSVD_MASK(aw_bits); + vtd_paging_entry_rsvd_field[3] =3D VTD_SPTE_PAGE_L3_RSVD_MASK(aw_bits); + vtd_paging_entry_rsvd_field[4] =3D VTD_SPTE_PAGE_L4_RSVD_MASK(aw_bits); + vtd_paging_entry_rsvd_field[5] =3D VTD_SPTE_LPAGE_L1_RSVD_MASK(aw_bits= ); + vtd_paging_entry_rsvd_field[6] =3D VTD_SPTE_LPAGE_L2_RSVD_MASK(aw_bits= ); + vtd_paging_entry_rsvd_field[7] =3D VTD_SPTE_LPAGE_L3_RSVD_MASK(aw_bits= ); + vtd_paging_entry_rsvd_field[8] =3D VTD_SPTE_LPAGE_L4_RSVD_MASK(aw_bits= ); + if (x86_iommu->intr_supported) { s->ecap |=3D VTD_ECAP_IR | VTD_ECAP_MHMV; if (s->intr_eim =3D=3D ON_OFF_AUTO_ON) { diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 0e73a65bf2..77e4a9833a 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -172,10 +172,10 @@ =20 /* RTADDR_REG */ #define VTD_RTADDR_RTT (1ULL << 11) -#define VTD_RTADDR_ADDR_MASK (VTD_HAW_MASK ^ 0xfffULL) +#define VTD_RTADDR_ADDR_MASK(aw) (VTD_HAW_MASK(aw) ^ 0xfffULL) =20 /* IRTA_REG */ -#define VTD_IRTA_ADDR_MASK (VTD_HAW_MASK ^ 0xfffULL) +#define VTD_IRTA_ADDR_MASK(aw) (VTD_HAW_MASK(aw) ^ 0xfffULL) #define VTD_IRTA_EIME (1ULL << 11) #define VTD_IRTA_SIZE_MASK (0xfULL) =20 @@ -198,8 +198,8 @@ #define VTD_DOMAIN_ID_MASK ((1UL << VTD_DOMAIN_ID_SHIFT) - 1) #define VTD_CAP_ND (((VTD_DOMAIN_ID_SHIFT - 4) / 2) & 7UL= L) #define VTD_MGAW 39 /* Maximum Guest Address Width */ -#define VTD_ADDRESS_SIZE (1ULL << VTD_MGAW) -#define VTD_CAP_MGAW (((VTD_MGAW - 1) & 0x3fULL) << 16) +#define VTD_ADDRESS_SIZE(aw) (1ULL << (aw)) +#define VTD_CAP_MGAW(aw) ((((aw) - 1) & 0x3fULL) << 16) #define VTD_MAMV 18ULL #define VTD_CAP_MAMV (VTD_MAMV << 48) #define VTD_CAP_PSI (1ULL << 39) @@ -219,7 +219,7 @@ #define VTD_IQT_QT(val) (((val) >> 4) & 0x7fffULL) =20 /* IQA_REG */ -#define VTD_IQA_IQA_MASK (VTD_HAW_MASK ^ 0xfffULL) +#define VTD_IQA_IQA_MASK(aw) (VTD_HAW_MASK(aw) ^ 0xfffULL) #define VTD_IQA_QS 0x7ULL =20 /* IQH_REG */ @@ -373,6 +373,24 @@ typedef union VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 =20 +/* Rsvd field masks for spte */ +#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw) \ + (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_PAGE_L2_RSVD_MASK(aw) \ + (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_PAGE_L3_RSVD_MASK(aw) \ + (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_PAGE_L4_RSVD_MASK(aw) \ + (0x880ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_LPAGE_L1_RSVD_MASK(aw) \ + (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_LPAGE_L2_RSVD_MASK(aw) \ + (0x1ff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_LPAGE_L3_RSVD_MASK(aw) \ + (0x3ffff800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) +#define VTD_SPTE_LPAGE_L4_RSVD_MASK(aw) \ + (0x880ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM)) + /* Information about page-selective IOTLB invalidate */ struct VTDIOTLBPageInvInfo { uint16_t domain_id; @@ -403,7 +421,7 @@ typedef struct VTDRootEntry VTDRootEntry; #define VTD_ROOT_ENTRY_CTP (~0xfffULL) =20 #define VTD_ROOT_ENTRY_NR (VTD_PAGE_SIZE / sizeof(VTDRootEntry)) -#define VTD_ROOT_ENTRY_RSVD (0xffeULL | ~VTD_HAW_MASK) +#define VTD_ROOT_ENTRY_RSVD(aw) (0xffeULL | ~VTD_HAW_MASK(aw)) =20 /* Masks for struct VTDContextEntry */ /* lo */ @@ -415,7 +433,7 @@ typedef struct VTDRootEntry VTDRootEntry; #define VTD_CONTEXT_TT_PASS_THROUGH (2ULL << 2) /* Second Level Page Translation Pointer*/ #define VTD_CONTEXT_ENTRY_SLPTPTR (~0xfffULL) -#define VTD_CONTEXT_ENTRY_RSVD_LO (0xff0ULL | ~VTD_HAW_MASK) +#define VTD_CONTEXT_ENTRY_RSVD_LO(aw) (0xff0ULL | ~VTD_HAW_MASK(aw)) /* hi */ #define VTD_CONTEXT_ENTRY_AW 7ULL /* Adjusted guest-address-width */ #define VTD_CONTEXT_ENTRY_DID(val) (((val) >> 8) & VTD_DOMAIN_ID_MASK) @@ -439,7 +457,7 @@ typedef struct VTDRootEntry VTDRootEntry; #define VTD_SL_RW_MASK 3ULL #define VTD_SL_R 1ULL #define VTD_SL_W (1ULL << 1) -#define VTD_SL_PT_BASE_ADDR_MASK (~(VTD_PAGE_SIZE - 1) & VTD_HAW_MASK) +#define VTD_SL_PT_BASE_ADDR_MASK(aw) (~(VTD_PAGE_SIZE - 1) & VTD_HAW_MASK(= aw)) #define VTD_SL_IGN_COM 0xbff0000000000000ULL =20 #endif diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index ac15e6be14..372b06df45 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -46,8 +46,10 @@ #define VTD_SID_TO_DEVFN(sid) ((sid) & 0xff) =20 #define DMAR_REG_SIZE 0x230 -#define VTD_HOST_ADDRESS_WIDTH 39 -#define VTD_HAW_MASK ((1ULL << VTD_HOST_ADDRESS_WIDTH) - 1) +#define VTD_HOST_AW_39BIT 39 +#define VTD_HOST_AW_48BIT 48 +#define VTD_HOST_ADDRESS_WIDTH VTD_HOST_AW_39BIT +#define VTD_HAW_MASK(aw) ((1ULL << (aw)) - 1) =20 #define DMAR_REPORT_F_INTR (1) =20 --=20 2.14.0-rc1 From nobody Mon Apr 29 18:43:47 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1510701412711393.4026209895429; Tue, 14 Nov 2017 15:16:52 -0800 (PST) Received: from localhost ([::1]:33961 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEkRg-0005vs-Q4 for importer@patchew.org; Tue, 14 Nov 2017 18:16:44 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58024) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eEkPF-0004QU-2Y for qemu-devel@nongnu.org; Tue, 14 Nov 2017 18:14:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eEkPA-0006gC-8R for qemu-devel@nongnu.org; Tue, 14 Nov 2017 18:14:13 -0500 Received: from aserp1040.oracle.com ([141.146.126.69]:43180) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eEkP9-0006cg-Om for qemu-devel@nongnu.org; Tue, 14 Nov 2017 18:14:08 -0500 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id vAENE4bh027425 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 14 Nov 2017 23:14:05 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id vAENE45U030430 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 14 Nov 2017 23:14:04 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id vAENE3O3005129; Tue, 14 Nov 2017 23:14:04 GMT Received: from pslinux.us.oracle.com (/10.129.250.229) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 14 Nov 2017 15:14:03 -0800 From: prasad.singamsetty@oracle.com To: qemu-devel@nongnu.org, pbonzini@redhat.com, rth@twiddle.net, ehabkost@redhat.com, mst@redhat.com, imammedo@redhat.com Date: Tue, 14 Nov 2017 18:13:50 -0500 Message-Id: <20171114231350.286025-3-prasad.singamsetty@oracle.com> X-Mailer: git-send-email 2.14.0-rc1 In-Reply-To: <20171114231350.286025-1-prasad.singamsetty@oracle.com> References: <20171114231350.286025-1-prasad.singamsetty@oracle.com> X-Source-IP: userv0022.oracle.com [156.151.31.74] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] [fuzzy] X-Received-From: 141.146.126.69 Subject: [Qemu-devel] [PATCH v1 2/2] intel-iommu: Extend address width to 48 bits X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peterx@redhat.com, konrad.wilk@oracle.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prasad Singamsetty The current implementation of Intel IOMMU code only supports 39 bits iova address width. This patch provides a new parameter (x-aw-bits) for intel-iommu to extend its address width to 48 bits but keeping the default the same (39 bits). The reason for not changing the default is to avoid potential compatibility problems with live migration of intel-iommu enabled QEMU guest. The only valid values for 'x-aw-bits' parameter are 39 and 48. After enabling larger address width (48), we should be able to map larger iova addresses in the guest. For example, a QEMU guest that is configured with large memory ( >=3D1TB ). To check whether 48 bits aw is enabled, we can grep in the guest dmesg output with line: "DMAR: Host address width 48". Signed-off-by: Prasad Singamsetty Reviewed-by: Peter Xu --- hw/i386/acpi-build.c | 3 +- hw/i386/intel_iommu.c | 101 ++++++++++++++++++++++++-------------= ---- hw/i386/intel_iommu_internal.h | 9 ++-- include/hw/i386/intel_iommu.h | 1 + 4 files changed, 65 insertions(+), 49 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 73519ab3ac..537957c89a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2460,6 +2460,7 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) AcpiDmarDeviceScope *scope =3D NULL; /* 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); =20 assert(iommu); if (iommu->intr_supported) { @@ -2467,7 +2468,7 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) } =20 dmar =3D acpi_data_push(table_data, sizeof(*dmar)); - dmar->host_address_width =3D VTD_HOST_ADDRESS_WIDTH - 1; + dmar->host_address_width =3D intel_iommu->aw_bits - 1; dmar->flags =3D dmar_flags; =20 /* DMAR Remapping Hardware Unit Definition structure */ diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 53b3bf244d..c2380fdfdc 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -521,9 +521,9 @@ static inline dma_addr_t vtd_ce_get_slpt_base(VTDContex= tEntry *ce) return ce->lo & VTD_CONTEXT_ENTRY_SLPTPTR; } =20 -static inline uint64_t vtd_get_slpte_addr(uint64_t slpte) +static inline uint64_t vtd_get_slpte_addr(uint64_t slpte, uint8_t aw) { - return slpte & VTD_SL_PT_BASE_ADDR_MASK(VTD_HOST_ADDRESS_WIDTH); + return slpte & VTD_SL_PT_BASE_ADDR_MASK(aw); } =20 /* Whether the pte indicates the address of the page frame */ @@ -608,20 +608,21 @@ static inline bool vtd_ce_type_check(X86IOMMUState *x= 86_iommu, return true; } =20 -static inline uint64_t vtd_iova_limit(VTDContextEntry *ce) +static inline uint64_t vtd_iova_limit(VTDContextEntry *ce, uint8_t aw) { uint32_t ce_agaw =3D vtd_ce_get_agaw(ce); - return 1ULL << MIN(ce_agaw, VTD_MGAW); + return 1ULL << MIN(ce_agaw, aw); } =20 /* Return true if IOVA passes range check, otherwise false. */ -static inline bool vtd_iova_range_check(uint64_t iova, VTDContextEntry *ce) +static inline bool vtd_iova_range_check(uint64_t iova, VTDContextEntry *ce, + uint8_t aw) { /* * Check if @iova is above 2^X-1, where X is the minimum of MGAW * in CAP_REG and AW in context-entry. */ - return !(iova & ~(vtd_iova_limit(ce) - 1)); + return !(iova & ~(vtd_iova_limit(ce, aw) - 1)); } =20 /* @@ -669,7 +670,7 @@ static VTDBus *vtd_find_as_from_bus_num(IntelIOMMUState= *s, uint8_t bus_num) */ static int vtd_iova_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_w= rite, uint64_t *slptep, uint32_t *slpte_level, - bool *reads, bool *writes) + bool *reads, bool *writes, uint8_t aw_bits) { dma_addr_t addr =3D vtd_ce_get_slpt_base(ce); uint32_t level =3D vtd_ce_get_level(ce); @@ -677,7 +678,7 @@ static int vtd_iova_to_slpte(VTDContextEntry *ce, uint6= 4_t iova, bool is_write, uint64_t slpte; uint64_t access_right_check; =20 - if (!vtd_iova_range_check(iova, ce)) { + if (!vtd_iova_range_check(iova, ce, aw_bits)) { trace_vtd_err_dmar_iova_overflow(iova); return -VTD_FR_ADDR_BEYOND_MGAW; } @@ -714,7 +715,7 @@ static int vtd_iova_to_slpte(VTDContextEntry *ce, uint6= 4_t iova, bool is_write, *slpte_level =3D level; return 0; } - addr =3D vtd_get_slpte_addr(slpte); + addr =3D vtd_get_slpte_addr(slpte, aw_bits); level--; } } @@ -732,11 +733,12 @@ typedef int (*vtd_page_walk_hook)(IOMMUTLBEntry *entr= y, void *private); * @read: whether parent level has read permission * @write: whether parent level has write permission * @notify_unmap: whether we should notify invalid entries + * @aw: maximum address width */ static int vtd_page_walk_level(dma_addr_t addr, uint64_t start, uint64_t end, vtd_page_walk_hook hook_fn, - void *private, uint32_t level, - bool read, bool write, bool notify_unmap) + void *private, uint32_t level, bool read, + bool write, bool notify_unmap, uint8_t aw) { bool read_cur, write_cur, entry_valid; uint32_t offset; @@ -783,7 +785,7 @@ static int vtd_page_walk_level(dma_addr_t addr, uint64_= t start, entry.target_as =3D &address_space_memory; entry.iova =3D iova & subpage_mask; /* NOTE: this is only meaningful if entry_valid =3D=3D true */ - entry.translated_addr =3D vtd_get_slpte_addr(slpte); + entry.translated_addr =3D vtd_get_slpte_addr(slpte, aw); entry.addr_mask =3D ~subpage_mask; entry.perm =3D IOMMU_ACCESS_FLAG(read_cur, write_cur); if (!entry_valid && !notify_unmap) { @@ -803,10 +805,10 @@ static int vtd_page_walk_level(dma_addr_t addr, uint6= 4_t start, trace_vtd_page_walk_skip_perm(iova, iova_next); goto next; } - ret =3D vtd_page_walk_level(vtd_get_slpte_addr(slpte), iova, + ret =3D vtd_page_walk_level(vtd_get_slpte_addr(slpte, aw), iov= a, MIN(iova_next, end), hook_fn, privat= e, level - 1, read_cur, write_cur, - notify_unmap); + notify_unmap, aw); if (ret < 0) { return ret; } @@ -827,25 +829,26 @@ next: * @end: IOVA range end address (start <=3D addr < end) * @hook_fn: the hook that to be called for each detected area * @private: private data for the hook function + * @aw: maximum address width */ static int vtd_page_walk(VTDContextEntry *ce, uint64_t start, uint64_t end, vtd_page_walk_hook hook_fn, void *private, - bool notify_unmap) + bool notify_unmap, uint8_t aw) { dma_addr_t addr =3D vtd_ce_get_slpt_base(ce); uint32_t level =3D vtd_ce_get_level(ce); =20 - if (!vtd_iova_range_check(start, ce)) { + if (!vtd_iova_range_check(start, ce, aw)) { return -VTD_FR_ADDR_BEYOND_MGAW; } =20 - if (!vtd_iova_range_check(end, ce)) { + if (!vtd_iova_range_check(end, ce, aw)) { /* Fix end so that it reaches the maximum */ - end =3D vtd_iova_limit(ce); + end =3D vtd_iova_limit(ce, aw); } =20 return vtd_page_walk_level(addr, start, end, hook_fn, private, - level, true, true, notify_unmap); + level, true, true, notify_unmap, aw); } =20 /* Map a device to its corresponding domain (context-entry) */ @@ -867,7 +870,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s,= uint8_t bus_num, return -VTD_FR_ROOT_ENTRY_P; } =20 - if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD(VTD_HOST_ADDRESS_WIDTH)))= { + if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD(s->aw_bits))) { trace_vtd_re_invalid(re.rsvd, re.val); return -VTD_FR_ROOT_ENTRY_RSVD; } @@ -884,7 +887,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s,= uint8_t bus_num, } =20 if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) || - (ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO(VTD_HOST_ADDRESS_WIDTH)= )) { + (ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO(s->aw_bits))) { trace_vtd_ce_invalid(ce->hi, ce->lo); return -VTD_FR_CONTEXT_ENTRY_RSVD; } @@ -1166,7 +1169,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *v= td_as, PCIBus *bus, } =20 ret_fr =3D vtd_iova_to_slpte(&ce, addr, is_write, &slpte, &level, - &reads, &writes); + &reads, &writes, s->aw_bits); if (ret_fr) { ret_fr =3D -ret_fr; if (is_fpd_set && vtd_is_qualified_fault(ret_fr)) { @@ -1183,7 +1186,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *v= td_as, PCIBus *bus, access_flags, level); out: entry->iova =3D addr & page_mask; - entry->translated_addr =3D vtd_get_slpte_addr(slpte) & page_mask; + entry->translated_addr =3D vtd_get_slpte_addr(slpte, s->aw_bits) & pag= e_mask; entry->addr_mask =3D ~page_mask; entry->perm =3D access_flags; return true; @@ -1200,7 +1203,7 @@ static void vtd_root_table_setup(IntelIOMMUState *s) { s->root =3D vtd_get_quad_raw(s, DMAR_RTADDR_REG); s->root_extended =3D s->root & VTD_RTADDR_RTT; - s->root &=3D VTD_RTADDR_ADDR_MASK(VTD_HOST_ADDRESS_WIDTH); + s->root &=3D VTD_RTADDR_ADDR_MASK(s->aw_bits); =20 trace_vtd_reg_dmar_root(s->root, s->root_extended); } @@ -1216,7 +1219,7 @@ static void vtd_interrupt_remap_table_setup(IntelIOMM= UState *s) uint64_t value =3D 0; value =3D vtd_get_quad_raw(s, DMAR_IRTA_REG); s->intr_size =3D 1UL << ((value & VTD_IRTA_SIZE_MASK) + 1); - s->intr_root =3D value & VTD_IRTA_ADDR_MASK(VTD_HOST_ADDRESS_WIDTH); + s->intr_root =3D value & VTD_IRTA_ADDR_MASK(s->aw_bits); s->intr_eime =3D value & VTD_IRTA_EIME; =20 /* Notify global invalidation */ @@ -1392,7 +1395,7 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOM= MUState *s, if (!ret && domain_id =3D=3D VTD_CONTEXT_ENTRY_DID(ce.hi)) { vtd_page_walk(&ce, addr, addr + (1 << am) * VTD_PAGE_SIZE, vtd_page_invalidate_notify_hook, - (void *)&vtd_as->iommu, true); + (void *)&vtd_as->iommu, true, s->aw_bits); } } } @@ -1472,7 +1475,7 @@ static void vtd_handle_gcmd_qie(IntelIOMMUState *s, b= ool en) trace_vtd_inv_qi_enable(en); =20 if (en) { - s->iq =3D iqa_val & VTD_IQA_IQA_MASK(VTD_HOST_ADDRESS_WIDTH); + s->iq =3D iqa_val & VTD_IQA_IQA_MASK(s->aw_bits); /* 2^(x+8) entries */ s->iq_size =3D 1UL << ((iqa_val & VTD_IQA_QS) + 8); s->qi_enabled =3D true; @@ -2403,6 +2406,8 @@ static Property vtd_properties[] =3D { DEFINE_PROP_ON_OFF_AUTO("eim", IntelIOMMUState, intr_eim, ON_OFF_AUTO_AUTO), DEFINE_PROP_BOOL("x-buggy-eim", IntelIOMMUState, buggy_eim, false), + DEFINE_PROP_UINT8("x-aw-bits", IntelIOMMUState, aw_bits, + VTD_HOST_ADDRESS_WIDTH), DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE), DEFINE_PROP_END_OF_LIST(), }; @@ -2758,6 +2763,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *= as, IOMMUNotifier *n) hwaddr size; hwaddr start =3D n->start; hwaddr end =3D n->end; + IntelIOMMUState *s =3D as->iommu_state; =20 /* * Note: all the codes in this function has a assumption that IOVA @@ -2765,12 +2771,12 @@ static void vtd_address_space_unmap(VTDAddressSpace= *as, IOMMUNotifier *n) * VT-d spec), otherwise we need to consider overflow of 64 bits. */ =20 - if (end > VTD_ADDRESS_SIZE(VTD_HOST_ADDRESS_WIDTH)) { + if (end > VTD_ADDRESS_SIZE(s->aw_bits)) { /* * Don't need to unmap regions that is bigger than the whole * VT-d supported address space size */ - end =3D VTD_ADDRESS_SIZE(VTD_HOST_ADDRESS_WIDTH); + end =3D VTD_ADDRESS_SIZE(s->aw_bits); } =20 assert(start <=3D end); @@ -2782,9 +2788,9 @@ static void vtd_address_space_unmap(VTDAddressSpace *= as, IOMMUNotifier *n) * suite the minimum available mask. */ int n =3D 64 - clz64(size); - if (n > VTD_MGAW) { + if (n > s->aw_bits) { /* should not happen, but in case it happens, limit it */ - n =3D VTD_MGAW; + n =3D s->aw_bits; } size =3D 1ULL << n; } @@ -2844,7 +2850,8 @@ static void vtd_iommu_replay(IOMMUMemoryRegion *iommu= _mr, IOMMUNotifier *n) PCI_FUNC(vtd_as->devfn), VTD_CONTEXT_ENTRY_DID(ce.hi), ce.hi, ce.lo); - vtd_page_walk(&ce, 0, ~0ULL, vtd_replay_hook, (void *)n, false); + vtd_page_walk(&ce, 0, ~0ULL, vtd_replay_hook, (void *)n, false, + s->aw_bits); } else { trace_vtd_replay_ce_invalid(bus_n, PCI_SLOT(vtd_as->devfn), PCI_FUNC(vtd_as->devfn)); @@ -2859,7 +2866,6 @@ static void vtd_iommu_replay(IOMMUMemoryRegion *iommu= _mr, IOMMUNotifier *n) static void vtd_init(IntelIOMMUState *s) { X86IOMMUState *x86_iommu =3D X86_IOMMU_DEVICE(s); - uint8_t aw_bits =3D VTD_HOST_ADDRESS_WIDTH; =20 memset(s->csr, 0, DMAR_REG_SIZE); memset(s->wmask, 0, DMAR_REG_SIZE); @@ -2878,21 +2884,24 @@ static void vtd_init(IntelIOMMUState *s) s->next_frcd_reg =3D 0; s->cap =3D VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND | VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS | - VTD_CAP_SAGAW_39bit | VTD_CAP_MGAW(VTD_HOST_ADDRESS_WIDTH); + VTD_CAP_SAGAW_39bit | VTD_CAP_MGAW(s->aw_bits); + if (s->aw_bits =3D=3D VTD_HOST_AW_48BIT) { + s->cap |=3D VTD_CAP_SAGAW_48bit; + } s->ecap =3D VTD_ECAP_QI | VTD_ECAP_IRO; =20 /* * Rsvd field masks for spte */ vtd_paging_entry_rsvd_field[0] =3D ~0ULL; - vtd_paging_entry_rsvd_field[1] =3D VTD_SPTE_PAGE_L1_RSVD_MASK(aw_bits); - vtd_paging_entry_rsvd_field[2] =3D VTD_SPTE_PAGE_L2_RSVD_MASK(aw_bits); - vtd_paging_entry_rsvd_field[3] =3D VTD_SPTE_PAGE_L3_RSVD_MASK(aw_bits); - vtd_paging_entry_rsvd_field[4] =3D VTD_SPTE_PAGE_L4_RSVD_MASK(aw_bits); - vtd_paging_entry_rsvd_field[5] =3D VTD_SPTE_LPAGE_L1_RSVD_MASK(aw_bits= ); - vtd_paging_entry_rsvd_field[6] =3D VTD_SPTE_LPAGE_L2_RSVD_MASK(aw_bits= ); - vtd_paging_entry_rsvd_field[7] =3D VTD_SPTE_LPAGE_L3_RSVD_MASK(aw_bits= ); - vtd_paging_entry_rsvd_field[8] =3D VTD_SPTE_LPAGE_L4_RSVD_MASK(aw_bits= ); + vtd_paging_entry_rsvd_field[1] =3D VTD_SPTE_PAGE_L1_RSVD_MASK(s->aw_bi= ts); + vtd_paging_entry_rsvd_field[2] =3D VTD_SPTE_PAGE_L2_RSVD_MASK(s->aw_bi= ts); + vtd_paging_entry_rsvd_field[3] =3D VTD_SPTE_PAGE_L3_RSVD_MASK(s->aw_bi= ts); + vtd_paging_entry_rsvd_field[4] =3D VTD_SPTE_PAGE_L4_RSVD_MASK(s->aw_bi= ts); + vtd_paging_entry_rsvd_field[5] =3D VTD_SPTE_LPAGE_L1_RSVD_MASK(s->aw_b= its); + vtd_paging_entry_rsvd_field[6] =3D VTD_SPTE_LPAGE_L2_RSVD_MASK(s->aw_b= its); + vtd_paging_entry_rsvd_field[7] =3D VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_b= its); + vtd_paging_entry_rsvd_field[8] =3D VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_b= its); =20 if (x86_iommu->intr_supported) { s->ecap |=3D VTD_ECAP_IR | VTD_ECAP_MHMV; @@ -3029,6 +3038,14 @@ static bool vtd_decide_config(IntelIOMMUState *s, Er= ror **errp) } } =20 + /* Currently only address widths supported are 39 and 48 bits */ + if ((s->aw_bits !=3D VTD_HOST_AW_39BIT) && + (s->aw_bits !=3D VTD_HOST_AW_48BIT)) { + error_setg(errp, "Supported values for x-aw-bits are: %d, %d", + VTD_HOST_AW_39BIT, VTD_HOST_AW_48BIT); + return false; + } + return true; } =20 diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 77e4a9833a..d084099ed9 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -131,7 +131,7 @@ #define VTD_TLB_DID(val) (((val) >> 32) & VTD_DOMAIN_ID_MASK) =20 /* IVA_REG */ -#define VTD_IVA_ADDR(val) ((val) & ~0xfffULL & ((1ULL << VTD_MGAW) -= 1)) +#define VTD_IVA_ADDR(val) ((val) & ~0xfffULL) #define VTD_IVA_AM(val) ((val) & 0x3fULL) =20 /* GCMD_REG */ @@ -197,7 +197,6 @@ #define VTD_DOMAIN_ID_SHIFT 16 /* 16-bit domain id for 64K domain= s */ #define VTD_DOMAIN_ID_MASK ((1UL << VTD_DOMAIN_ID_SHIFT) - 1) #define VTD_CAP_ND (((VTD_DOMAIN_ID_SHIFT - 4) / 2) & 7UL= L) -#define VTD_MGAW 39 /* Maximum Guest Address Width */ #define VTD_ADDRESS_SIZE(aw) (1ULL << (aw)) #define VTD_CAP_MGAW(aw) ((((aw) - 1) & 0x3fULL) << 16) #define VTD_MAMV 18ULL @@ -213,7 +212,6 @@ #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 =20 /* IQT_REG */ #define VTD_IQT_QT(val) (((val) >> 4) & 0x7fffULL) @@ -252,7 +250,7 @@ #define VTD_FRCD_SID_MASK 0xffffULL #define VTD_FRCD_SID(val) ((val) & VTD_FRCD_SID_MASK) /* For the low 64-bit of 128-bit */ -#define VTD_FRCD_FI(val) ((val) & (((1ULL << VTD_MGAW) - 1) ^ 0xfff= ULL)) +#define VTD_FRCD_FI(val) ((val) & ~0xfffULL) =20 /* DMA Remapping Fault Conditions */ typedef enum VTDFaultReason { @@ -360,8 +358,7 @@ typedef union VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_IOTLB_DOMAIN (2ULL << 4) #define VTD_INV_DESC_IOTLB_PAGE (3ULL << 4) #define VTD_INV_DESC_IOTLB_DID(val) (((val) >> 16) & VTD_DOMAIN_ID_MAS= K) -#define VTD_INV_DESC_IOTLB_ADDR(val) ((val) & ~0xfffULL & \ - ((1ULL << VTD_MGAW) - 1)) +#define VTD_INV_DESC_IOTLB_ADDR(val) ((val) & ~0xfffULL) #define VTD_INV_DESC_IOTLB_AM(val) ((val) & 0x3fULL) #define VTD_INV_DESC_IOTLB_RSVD_LO 0xffffffff0000ff00ULL #define VTD_INV_DESC_IOTLB_RSVD_HI 0xf80ULL diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 372b06df45..45ec8919b6 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -304,6 +304,7 @@ struct IntelIOMMUState { bool intr_eime; /* Extended interrupt mode enabled */ OnOffAuto intr_eim; /* Toggle for EIM cabability */ bool buggy_eim; /* Force buggy EIM unless eim=3Doff */ + uint8_t aw_bits; /* Host/IOVA address width (in bits) */ }; =20 /* Find the VTD Address space associated with the given bus pointer, --=20 2.14.0-rc1