From nobody Tue Apr 23 21:02:26 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+96509+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+96509+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1669009433; cv=none; d=zohomail.com; s=zohoarc; b=fKCAbkGQ84lZcXEv5pHjayB/68lvF5V1JQCyO2Gy0++7tqvNObSo7kWEgFrqyPBwdRGOMuD0QPwRAc98cFHwOXa1QXgeZU7WxAVt7yTvekJPS3pljPobxcZe3QWF/CXHtztuZm2glA1g7rk85cRYqtIUXJVWOkvN6SpHPByAa7A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1669009433; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To; bh=47AovIdeVLzEz2ZUY1cfBUJfV/u2UXjIaZc35CJFASo=; b=dsVBKIGMSo3oRqkgqnfNjmoKnq0Djt+aoXQcEemtxbilTvhdFtl6r+3p/wKthiL5ZUjJRVYqjCYKerO//05Ps6BwaRiMBINJMXKiWeSUZtXgO08KpHTgMXfQeXDYZ5DNvoJMmw9/n0OcQASEDepjXNa9UmPJdmEqyXyqUXt0Ypw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+96509+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 166900943335539.908179813740844; Sun, 20 Nov 2022 21:43:53 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id ZbT5YY1788612xr2zR6VQRcf; Sun, 20 Nov 2022 21:43:52 -0800 X-Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mx.groups.io with SMTP id smtpd.web11.31875.1669009432226712829 for ; Sun, 20 Nov 2022 21:43:52 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10537"; a="312178987" X-IronPort-AV: E=Sophos;i="5.96,180,1665471600"; d="scan'208";a="312178987" X-Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Nov 2022 21:43:51 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10537"; a="746766659" X-IronPort-AV: E=Sophos;i="5.96,180,1665471600"; d="scan'208";a="746766659" X-Received: from shwdesssddpdwei.ccr.corp.intel.com ([10.239.157.43]) by fmsmga002.fm.intel.com with ESMTP; 20 Nov 2022 21:43:49 -0800 From: "Sheng Wei" To: devel@edk2.groups.io Cc: Ray Ni , Rangasai V Chaganty , Jenny Huang , Robert Kowalewski Subject: [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Use 256-bit invaildation queue descriptor Date: Mon, 21 Nov 2022 13:43:41 +0800 Message-Id: <20221121054341.1088-1-w.sheng@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,w.sheng@intel.com X-Gm-Message-State: JLCUIZl7gToqMxzJWKy6XToWx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1669009432; bh=/hJTgODT64EMMbDlKLGEkJlFwpkIfodEVDT415nMwE4=; h=Cc:Date:From:Reply-To:Subject:To; b=VVc5iakFmo2qTuhSIJ4R0HaWhCaoyXJk6PRkgl2P4pAz1d0bbJoROmvS/YcAMofeM8i lS4FECpbbnvQjedvpTgfeWzsfDhJQwk9laCtCMKoBholtzmf6ApUf6N0oSnXtnlDLxErd g2lSdsUmoOvM68dvLUnTKYS+Nmwq4jMpg5w= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1669009434655100003 Content-Type: text/plain; charset="utf-8" 256-bit invaildation queue descriptor could be used for both abort DMA mode and legacy mode. Change-Id: Ib3b94d6c5782d42c53056204312f6f4ad513344e Signed-off-by: Sheng Wei Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski --- .../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 172 ++++++++----- .../VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 5 +- .../Feature/VTd/IntelVTdDxe/DmaProtection.c | 3 + .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 5 +- .../Feature/VTd/IntelVTdDxe/VtdReg.c | 232 +++++++++++------- .../Include/IndustryStandard/Vtd.h | 65 ++++- 6 files changed, 329 insertions(+), 153 deletions(-) diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/Inte= lVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/Inte= lVTdDmar.c index af85a3d8e..87d5edaa6 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDma= r.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDma= r.c @@ -79,10 +79,11 @@ PerpareCacheInvalidationInterface ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT16 QueueSize; - UINT64 Reg64; + UINT8 DescriptorWidth; + UINTN QueueSize; UINT32 Reg32; VTD_ECAP_REG ECapReg; + VTD_IQA_REG IqaReg; UINTN VtdUnitBaseAddress; =20 VtdUnitBaseAddress =3D VTdUnitInfo->VtdUnitBaseAddress; @@ -121,20 +122,32 @@ PerpareCacheInvalidationInterface ( // // Setup the IQ address, size and descriptor width through the Invalidat= ion Queue Address Register // - if (VTdUnitInfo->QiDesc =3D=3D NULL) { + if (VTdUnitInfo->QiDescBuffer =3D=3D NULL) { + // + // It uses 256-bit descriptor + // Queue size is 128. + // + DescriptorWidth =3D 1; QueueSize =3D 0; - VTdUnitInfo->QiDescLength =3D 1 << (QueueSize + 8); - VTdUnitInfo->QiDesc =3D (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES (= sizeof (QI_DESC) * VTdUnitInfo->QiDescLength)); - if (VTdUnitInfo->QiDesc =3D=3D NULL) { + + VTdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <= < (QueueSize + 7))); + VTdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VTdUni= tInfo->QiDescBufferSize)); + if (VTdUnitInfo->QiDescBuffer =3D=3D NULL) { DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); return EFI_OUT_OF_RESOURCES; } } =20 - DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiD= escLength)); - Reg64 =3D (UINT64) (UINTN) VTdUnitInfo->QiDesc; - Reg64 |=3D QueueSize; - MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64); + DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VTdUnitInfo= ->QiDescBufferSize)); + // + // 4KB Aligned address + // + IqaReg.Uint64 =3D (UINT64) (UINTN) VTdUnitInfo->QiDescBuffer; + IqaReg.Bits.DW =3D DescriptorWidth; + IqaReg.Bits.QS =3D QueueSize; + MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64); + IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG); + DEBUG ((DEBUG_INFO, "IQA_REG [0x%x]\n", IqaReg.Uint64)); =20 // // Enable the queued invalidation interface through the Global Command R= egister. @@ -148,8 +161,6 @@ PerpareCacheInvalidationInterface ( Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0); =20 - VTdUnitInfo->QiFreeHead =3D 0; - return EFI_SUCCESS; } =20 @@ -174,10 +185,10 @@ DisableQueuedInvalidationInterface ( Reg32 =3D MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0); =20 - if (VTdUnitInfo->QiDesc !=3D NULL) { - FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES (sizeof (QI_DESC) *= VTdUnitInfo->QiDescLength)); - VTdUnitInfo->QiDesc =3D NULL; - VTdUnitInfo->QiDescLength =3D 0; + if (VTdUnitInfo->QiDescBuffer !=3D NULL) { + FreePages(VTdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VTdUnitInfo-= >QiDescBufferSize)); + VTdUnitInfo->QiDescBuffer =3D NULL; + VTdUnitInfo->QiDescBufferSize =3D 0; } =20 VTdUnitInfo->EnableQueuedInvalidation =3D 0; @@ -197,12 +208,15 @@ QueuedInvalidationCheckFault ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT32 FaultReg; + UINT32 FaultReg; + VTD_IQERCD_REG IqercdReg; =20 FaultReg =3D MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG); if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) { - DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", Faul= tReg)); - FaultReg |=3D (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE); + IqercdReg.Uint64 =3D MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_I= QERCD_REG); + + DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x] - IQERCD= [0x%016lx]\n", FaultReg, IqercdReg.Uint64)); + MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); return RETURN_DEVICE_ERROR; } @@ -223,37 +237,82 @@ QueuedInvalidationCheckFault ( **/ EFI_STATUS SubmitQueuedInvalidationDescriptor ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN QI_DESC *Desc + IN VTD_UNIT_INFO *VTdUnitInfo, + IN QI_256_DESC *Desc ) { - EFI_STATUS Status; - UINT16 QiDescLength; - QI_DESC *BaseDesc; - UINT64 Reg64Iqt; - UINT64 Reg64Iqh; + EFI_STATUS Status; + UINTN VtdUnitBaseAddress; + UINTN QueueSize; + UINTN QueueTail; + UINTN QueueHead; + QI_DESC *Qi128Desc; + QI_256_DESC *Qi256Desc; + VTD_IQA_REG IqaReg; + VTD_IQT_REG IqtReg; + VTD_IQH_REG IqhReg; =20 if (Desc =3D=3D NULL) { return EFI_INVALID_PARAMETER; } =20 - QiDescLength =3D VTdUnitInfo->QiDescLength; - BaseDesc =3D VTdUnitInfo->QiDesc; - - DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%016lx, 0x%016lx]\n",= VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High)); - - BaseDesc[VTdUnitInfo->QiFreeHead].Low =3D Desc->Low; - BaseDesc[VTdUnitInfo->QiFreeHead].High =3D Desc->High; - FlushPageTableMemory(VTdUnitInfo, (UINTN) &BaseDesc[VTdUnitInfo->QiFreeH= ead], sizeof(QI_DESC)); + VtdUnitBaseAddress =3D VTdUnitInfo->VtdUnitBaseAddress; + IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG); + if (IqaReg.Bits.IQA =3D=3D 0) { + return EFI_NOT_READY; + } + IqtReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQT_REG); =20 - DEBUG((DEBUG_INFO,"QI Free Head=3D0x%x\n", VTdUnitInfo->QiFreeHead)); - VTdUnitInfo->QiFreeHead =3D (VTdUnitInfo->QiFreeHead + 1) % QiDescLength; + if (IqaReg.Bits.DW =3D=3D 0) { + // + // 128-bit descriptor + // + QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 8)); + Qi128Desc =3D (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT); + QueueTail =3D (UINTN) IqtReg.Bits128Desc.QT; + Qi128Desc +=3D QueueTail; + Qi128Desc->Low =3D Desc->Uint64[0]; + Qi128Desc->High =3D Desc->Uint64[1]; + FlushPageTableMemory (VTdUnitInfo, (UINTN) Qi128Desc, sizeof(QI_DESC)); + QueueTail =3D (QueueTail + 1) % QueueSize; + + DEBUG ((DEBUG_INFO, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%01= 6lx]\n", + VtdUnitBaseAddress, + QueueTail, + Desc->Uint64[0], + Desc->Uint64[1])); + + IqtReg.Bits128Desc.QT =3D QueueTail; + } else { + // + // 256-bit descriptor + // + QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 7)); + Qi256Desc =3D (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHI= FT); + QueueTail =3D (UINTN) IqtReg.Bits256Desc.QT; + Qi256Desc +=3D QueueTail; + Qi256Desc->Uint64[0] =3D Desc->Uint64[0]; + Qi256Desc->Uint64[1] =3D Desc->Uint64[1]; + Qi256Desc->Uint64[2] =3D Desc->Uint64[2]; + Qi256Desc->Uint64[3] =3D Desc->Uint64[3]; + FlushPageTableMemory (VTdUnitInfo, (UINTN) Qi256Desc, sizeof(QI_256_DE= SC)); + QueueTail =3D (QueueTail + 1) % QueueSize; + + DEBUG ((DEBUG_INFO, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%01= 6lx, 0x%016lx, 0x%016lx]\n", + VtdUnitBaseAddress, + QueueTail, + Desc->Uint64[0], + Desc->Uint64[1], + Desc->Uint64[2], + Desc->Uint64[3])); + + IqtReg.Bits256Desc.QT =3D QueueTail; + } =20 // // Update the HW tail register indicating the presence of new descriptor= s. // - Reg64Iqt =3D VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT; - MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt); + MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64); =20 Status =3D EFI_SUCCESS; do { @@ -263,10 +322,15 @@ SubmitQueuedInvalidationDescriptor ( break; } =20 - Reg64Iqh =3D MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG); - } while (Reg64Iqt !=3D Reg64Iqh); + IqhReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQH_REG); + if (IqaReg.Bits.DW =3D=3D 0) { + QueueHead =3D (UINTN) IqhReg.Bits128Desc.QH; + } else { + QueueHead =3D (UINTN) IqhReg.Bits256Desc.QH; + } + } while (QueueTail !=3D QueueHead); =20 - DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n")); + DEBUG((DEBUG_INFO,"SubmitQueuedInvalidationDescriptor end\n")); return Status; } =20 @@ -281,7 +345,7 @@ InvalidateContextCache ( ) { UINT64 Reg64; - QI_DESC QiDesc; + QI_256_DESC QiDesc; =20 if (VTdUnitInfo->EnableQueuedInvalidation =3D=3D 0) { // @@ -304,8 +368,10 @@ InvalidateContextCache ( // // Queued Invalidation // - QiDesc.Low =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(= 1) | QI_CC_TYPE; - QiDesc.High =3D 0; + QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC= _GRAN(1) | QI_CC_TYPE; + QiDesc.Uint64[1] =3D 0; + QiDesc.Uint64[2] =3D 0; + QiDesc.Uint64[3] =3D 0; =20 return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc); } @@ -326,7 +392,7 @@ InvalidateIOTLB ( UINT64 Reg64; VTD_ECAP_REG ECapReg; VTD_CAP_REG CapReg; - QI_DESC QiDesc; + QI_256_DESC QiDesc; =20 if (VTdUnitInfo->EnableQueuedInvalidation =3D=3D 0) { // @@ -352,8 +418,10 @@ InvalidateIOTLB ( // Queued Invalidation // CapReg.Uint64 =3D MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CAP_= REG); - QiDesc.Low =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapReg.Uin= t64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI= _IOTLB_TYPE; - QiDesc.High =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0); + QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapR= eg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1= ) | QI_IOTLB_TYPE; + QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0= ); + QiDesc.Uint64[2] =3D 0; + QiDesc.Uint64[3] =3D 0; =20 return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc); } @@ -451,11 +519,6 @@ EnableDmarPreMem ( Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG =3D 0x%x \n", Reg32)); =20 - // - // Init DMAr Fault Event and Data registers - // - Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG); - // // Write Buffer Flush // @@ -525,11 +588,6 @@ EnableDmar ( DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n")); SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP); =20 - // - // Init DMAr Fault Event and Data registers - // - MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG); - // // Write Buffer Flush before invalidation // diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/Inte= lVTdDmarPei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/I= ntelVTdDmarPei.h index 5ade9ec35..4d4b912f2 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDma= rPei.h +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDma= rPei.h @@ -21,9 +21,8 @@ typedef struct { VTD_ECAP_REG ECapReg; BOOLEAN Is5LevelPaging; UINT8 EnableQueuedInvalidation; - UINT16 QiDescLength; - QI_DESC *QiDesc; - UINT16 QiFreeHead; + VOID *QiDescBuffer; + UINTN QiDescBufferSize; UINTN FixedSecondLevelPagingEntry; UINTN RootEntryTable; UINTN ExtRootEntryTable; diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProte= ction.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtecti= on.c index 628565ee7..878c952b7 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c @@ -496,6 +496,9 @@ SetupVtd ( if (EFI_ERROR (Status)) { return; } + + DumpVtdIfError (); + DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); PrepareVtdConfig (); =20 diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProte= ction.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtecti= on.h index 7dd29a243..e83ebff41 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h @@ -81,9 +81,8 @@ typedef struct { PCI_DEVICE_INFORMATION PciDeviceInfo; BOOLEAN Is5LevelPaging; UINT8 EnableQueuedInvalidation; - UINT16 QiDescLength; - QI_DESC *QiDesc; - UINT16 QiFreeHead; + VOID *QiDescBuffer; + UINTN QiDescBufferSize; } VTD_UNIT_INFORMATION; =20 // diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c= b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c index 8e834f4c4..7e45ac2d2 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c @@ -68,71 +68,87 @@ PerpareCacheInvalidationInterface ( IN UINTN VtdIndex ) { - UINT16 QueueSize; - UINT64 Reg64; - UINT32 Reg32; - - if (mVtdUnitInformation[VtdIndex].VerReg.Bits.Major <=3D 5) { - mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D 0; + UINT8 DescriptorWidth; + UINTN QueueSize; + UINT32 Reg32; + VTD_IQA_REG IqaReg; + VTD_UNIT_INFORMATION *VTdUnitInfo; + UINTN VtdUnitBaseAddress; + + VTdUnitInfo =3D &mVtdUnitInformation[VtdIndex]; + VtdUnitBaseAddress =3D VTdUnitInfo->VtdUnitBaseAddress; + + if (VTdUnitInfo->VerReg.Bits.Major <=3D 5) { + VTdUnitInfo->EnableQueuedInvalidation =3D 0; DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng= ine [%d]\n", VtdIndex)); return EFI_SUCCESS; } =20 - if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.QI =3D=3D 0) { + if (VTdUnitInfo->ECapReg.Bits.QI =3D=3D 0) { DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i= nterface for engine [%d]\n", VtdIndex)); return EFI_UNSUPPORTED; } =20 - mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D 1; + VTdUnitInfo->EnableQueuedInvalidation =3D 1; DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n= ", VtdIndex)); =20 - Reg32 =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress += R_GSTS_REG); + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) { DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n")); Reg32 &=3D (~B_GSTS_REG_QIES); - MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD= _REG, Reg32); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32); do { - Reg32 =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre= ss + R_GSTS_REG); + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0); } =20 // // Initialize the Invalidation Queue Tail Register to zero. // - MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQT_RE= G, 0); + MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0); =20 // // Setup the IQ address, size and descriptor width through the Invalidat= ion Queue Address Register // - QueueSize =3D 0; - mVtdUnitInformation[VtdIndex].QiDescLength =3D 1 << (QueueSize + 8); - mVtdUnitInformation[VtdIndex].QiDesc =3D (QI_DESC *) AllocatePages (EFI_= SIZE_TO_PAGES(sizeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength)= ); - - if (mVtdUnitInformation[VtdIndex].QiDesc =3D=3D NULL) { - mVtdUnitInformation[VtdIndex].QiDescLength =3D 0; - DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); - return EFI_OUT_OF_RESOURCES; + if (VTdUnitInfo->QiDescBuffer =3D=3D NULL) { + // + // It uses 256-bit descriptor + // Queue size is 128. + // + DescriptorWidth =3D 1; + QueueSize =3D 0; + + VTdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <= < (QueueSize + 7))); + VTdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VTdUni= tInfo->QiDescBufferSize)); + if (VTdUnitInfo->QiDescBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); + return EFI_OUT_OF_RESOURCES; + } } =20 - DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", mVtdUnitInformat= ion[VtdIndex].QiDescLength)); - Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].QiDesc; - Reg64 |=3D QueueSize; - MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQA_RE= G, Reg64); + DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VTdUnitInfo= ->QiDescBufferSize)); + // + // 4KB Aligned address + // + IqaReg.Uint64 =3D (UINT64) (UINTN) VTdUnitInfo->QiDescBuffer; + IqaReg.Bits.DW =3D DescriptorWidth; + IqaReg.Bits.QS =3D QueueSize; + MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64); + IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG); + DEBUG ((DEBUG_INFO, "IQA_REG [0x%x]\n", IqaReg.Uint64)); =20 // // Enable the queued invalidation interface through the Global Command R= egister. // When enabled, hardware sets the QIES field in the Global Status Regis= ter. // - Reg32 =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress += R_GSTS_REG); + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); Reg32 |=3D B_GMCD_REG_QIE; - MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_R= EG, Reg32); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32); DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D = 0x%x\n", Reg32)); do { - Reg32 =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress= + R_GSTS_REG); + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0); =20 - mVtdUnitInformation[VtdIndex].QiFreeHead =3D 0; - return EFI_SUCCESS; } =20 @@ -146,21 +162,24 @@ DisableQueuedInvalidationInterface ( IN UINTN VtdIndex ) { - UINT32 Reg32; + UINT32 Reg32; + VTD_UNIT_INFORMATION *VTdUnitInfo; =20 - if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation !=3D 0) { - Reg32 =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress= + R_GSTS_REG); + VTdUnitInfo =3D &mVtdUnitInformation[VtdIndex]; + + if (VTdUnitInfo->EnableQueuedInvalidation !=3D 0) { + Reg32 =3D MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); Reg32 &=3D (~B_GMCD_REG_QIE); - MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD= _REG, Reg32); + MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32); DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = =3D 0x%x\n", Reg32)); do { - Reg32 =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre= ss + R_GSTS_REG); + Reg32 =3D MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0); =20 - if (mVtdUnitInformation[VtdIndex].QiDesc !=3D NULL) { - FreePages(mVtdUnitInformation[VtdIndex].QiDesc, EFI_SIZE_TO_PAGES(si= zeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength)); - mVtdUnitInformation[VtdIndex].QiDesc =3D NULL; - mVtdUnitInformation[VtdIndex].QiDescLength =3D 0; + if (VTdUnitInfo->QiDescBuffer !=3D NULL) { + FreePages(VTdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VTdUnitInfo-= >QiDescBufferSize)); + VTdUnitInfo->QiDescBuffer =3D NULL; + VTdUnitInfo->QiDescBufferSize =3D 0; } =20 mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D 0; @@ -180,27 +199,16 @@ QueuedInvalidationCheckFault ( IN UINTN VtdIndex ) { - UINT32 FaultReg; + UINT32 FaultReg; + VTD_IQERCD_REG IqercdReg; =20 FaultReg =3D MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddres= s + R_FSTS_REG); =20 - if (FaultReg & B_FSTS_REG_IQE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", Faul= tReg)); - FaultReg |=3D B_FSTS_REG_IQE; - MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS= _REG, FaultReg); - return RETURN_DEVICE_ERROR; - } + if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) { + IqercdReg.Uint64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnit= BaseAddress + R_IQERCD_REG); =20 - if (FaultReg & B_FSTS_REG_ITE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", F= aultReg)); - FaultReg |=3D B_FSTS_REG_ITE; - MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS= _REG, FaultReg); - return RETURN_DEVICE_ERROR; - } + DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x] - IQERCD= [0x%016lx]\n", FaultReg, IqercdReg.Uint64)); =20 - if (FaultReg & B_FSTS_REG_ICE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n",= FaultReg)); - FaultReg |=3D B_FSTS_REG_ICE; MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS= _REG, FaultReg); return RETURN_DEVICE_ERROR; } @@ -221,36 +229,82 @@ QueuedInvalidationCheckFault ( **/ EFI_STATUS SubmitQueuedInvalidationDescriptor ( - IN UINTN VtdIndex, - IN QI_DESC *Desc + IN UINTN VtdIndex, + IN QI_256_DESC *Desc ) { - EFI_STATUS Status; - UINT16 QiDescLength; - QI_DESC *BaseDesc; - UINT64 Reg64Iqt; - UINT64 Reg64Iqh; + EFI_STATUS Status; + UINTN VtdUnitBaseAddress; + UINTN QueueSize; + UINTN QueueTail; + UINTN QueueHead; + QI_DESC *Qi128Desc; + QI_256_DESC *Qi256Desc; + VTD_IQA_REG IqaReg; + VTD_IQT_REG IqtReg; + VTD_IQH_REG IqhReg; =20 if (Desc =3D=3D NULL) { return EFI_INVALID_PARAMETER; } =20 - QiDescLength =3D mVtdUnitInformation[VtdIndex].QiDescLength; - BaseDesc =3D mVtdUnitInformation[VtdIndex].QiDesc; - - DEBUG((DEBUG_VERBOSE, "[%d] Submit QI Descriptor [0x%08x, 0x%08x] Free H= ead (%d)\n", VtdIndex, Desc->Low, Desc->High, mVtdUnitInformation[VtdIndex]= .QiFreeHead)); - - BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].Low =3D Desc->Low; - BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].High =3D Desc->High; - FlushPageTableMemory(VtdIndex, (UINTN) &BaseDesc[mVtdUnitInformation[Vtd= Index].QiFreeHead], sizeof(QI_DESC)); + VtdUnitBaseAddress =3D mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress; + IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG); + if (IqaReg.Bits.IQA =3D=3D 0) { + return EFI_NOT_READY; + } + IqtReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQT_REG); =20 - mVtdUnitInformation[VtdIndex].QiFreeHead =3D (mVtdUnitInformation[VtdInd= ex].QiFreeHead + 1) % QiDescLength; + if (IqaReg.Bits.DW =3D=3D 0) { + // + // 128-bit descriptor + // + QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 8)); + Qi128Desc =3D (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT); + QueueTail =3D (UINTN) IqtReg.Bits128Desc.QT; + Qi128Desc +=3D QueueTail; + Qi128Desc->Low =3D Desc->Uint64[0]; + Qi128Desc->High =3D Desc->Uint64[1]; + FlushPageTableMemory (VtdIndex, (UINTN) Qi128Desc, sizeof(QI_DESC)); + QueueTail =3D (QueueTail + 1) % QueueSize; + + DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x= %016lx]\n", + VtdUnitBaseAddress, + QueueTail, + Desc->Uint64[0], + Desc->Uint64[1])); + + IqtReg.Bits128Desc.QT =3D QueueTail; + } else { + // + // 256-bit descriptor + // + QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 7)); + Qi256Desc =3D (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHI= FT); + QueueTail =3D (UINTN) IqtReg.Bits256Desc.QT; + Qi256Desc +=3D QueueTail; + Qi256Desc->Uint64[0] =3D Desc->Uint64[0]; + Qi256Desc->Uint64[1] =3D Desc->Uint64[1]; + Qi256Desc->Uint64[2] =3D Desc->Uint64[2]; + Qi256Desc->Uint64[3] =3D Desc->Uint64[3]; + FlushPageTableMemory (VtdIndex, (UINTN) Qi256Desc, sizeof(QI_256_DESC)= ); + QueueTail =3D (QueueTail + 1) % QueueSize; + + DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x= %016lx, 0x%016lx, 0x%016lx]\n", + VtdUnitBaseAddress, + QueueTail, + Desc->Uint64[0], + Desc->Uint64[1], + Desc->Uint64[2], + Desc->Uint64[3])); + + IqtReg.Bits256Desc.QT =3D QueueTail; + } =20 // // Update the HW tail register indicating the presence of new descriptor= s. // - Reg64Iqt =3D mVtdUnitInformation[VtdIndex].QiFreeHead << DMAR_IQ_SHIFT; - MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQT_RE= G, Reg64Iqt); + MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64); =20 Status =3D EFI_SUCCESS; do { @@ -260,8 +314,13 @@ SubmitQueuedInvalidationDescriptor ( break; } =20 - Reg64Iqh =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddr= ess + R_IQH_REG); - } while (Reg64Iqt !=3D Reg64Iqh); + IqhReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQH_REG); + if (IqaReg.Bits.DW =3D=3D 0) { + QueueHead =3D (UINTN) IqhReg.Bits128Desc.QH; + } else { + QueueHead =3D (UINTN) IqhReg.Bits256Desc.QH; + } + } while (QueueTail !=3D QueueHead); =20 return Status; } @@ -276,8 +335,8 @@ InvalidateContextCache ( IN UINTN VtdIndex ) { - UINT64 Reg64; - QI_DESC QiDesc; + UINT64 Reg64; + QI_256_DESC QiDesc; =20 if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) { // @@ -300,8 +359,10 @@ InvalidateContextCache ( // // Queued Invalidation // - QiDesc.Low =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(= 1) | QI_CC_TYPE; - QiDesc.High =3D 0; + QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC= _GRAN(1) | QI_CC_TYPE; + QiDesc.Uint64[1] =3D 0; + QiDesc.Uint64[2] =3D 0; + QiDesc.Uint64[3] =3D 0; =20 return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc); } @@ -318,8 +379,8 @@ InvalidateIOTLB ( IN UINTN VtdIndex ) { - UINT64 Reg64; - QI_DESC QiDesc; + UINT64 Reg64; + QI_256_DESC QiDesc; =20 if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) { // @@ -342,8 +403,10 @@ InvalidateIOTLB ( // // Queued Invalidation // - QiDesc.Low =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtdUnitIn= formation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVtdUnitI= nformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE; - QiDesc.High =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0); + QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtd= UnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVt= dUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TY= PE; + QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0= ); + QiDesc.Uint64[2] =3D 0; + QiDesc.Uint64[3] =3D 0; =20 return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc); } @@ -611,11 +674,6 @@ EnableDmar ( DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n")= ); SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP); =20 - // - // Init DMAr Fault Event and Data registers - // - MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_R= EG); - // // Write Buffer Flush before invalidation // diff --git a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b= /Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h index 32fbdd02e..3e1b8c3c5 100644 --- a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h +++ b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h @@ -259,6 +259,8 @@ typedef union { =20 #define R_IQA_REG 0x90 =20 +#define R_IQERCD_REG 0xB0 + #define VTD_PAGE_SHIFT (12) #define VTD_PAGE_SIZE (1UL << VTD_PAGE_SHIFT) #define VTD_PAGE_MASK (((UINT64)-1) << VTD_PAGE_SHIFT) @@ -289,13 +291,20 @@ typedef union { #define QI_IWD_STATUS_WRITE (((UINT64)1) << 5) =20 // -// This is the queued invalidate descriptor. +// queued invalidation 128-bit descriptor // typedef struct { - UINT64 Low; - UINT64 High; + UINT64 Low; + UINT64 High; } QI_DESC; =20 +// +// queued invalidation 256-bit descriptor +// +typedef struct { + UINT64 Uint64[4]; +} QI_256_DESC; + typedef union { struct { UINT8 Minor:4; @@ -411,6 +420,56 @@ typedef union { UINT64 Uint64[2]; } VTD_FRCD_REG; =20 +typedef union { + struct { + UINT32 IQEI:4; // Invalidation Queue Error Info + UINT32 Rsvd_4:28; + UINT32 ITESID:16; // Invalidation Time-out Error Source Identifier + UINT32 ICESID:16; // Invalidation Completion Error Source Identif= ier + } Bits; + UINT64 Uint64; +} VTD_IQERCD_REG; + +typedef union { + struct { + UINT64 Rsvd_0:4; + UINT64 QH:15; // Queue Head + UINT64 Rsvd_19:45; + } Bits128Desc; + struct { + UINT64 Rsvd_0:4; + UINT64 Rsvd_4:1; + UINT64 QH:14; // Queue Head + UINT64 Rsvd_19:45; + } Bits256Desc; + UINT64 Uint64; +} VTD_IQH_REG; + +typedef union { + struct { + UINT64 Rsvd_0:4; + UINT64 QT:15; // Queue Tail + UINT64 Rsvd_19:45; + } Bits128Desc; + struct { + UINT64 Rsvd_0:4; + UINT64 Rsvd_4:1; + UINT64 QT:14; // Queue Tail + UINT64 Rsvd_19:45; + } Bits256Desc; + UINT64 Uint64; +} VTD_IQT_REG; + +typedef union { + struct { + UINT64 QS:3; // Queue Size + UINT64 Rsvd_3:8; + UINT64 DW:1; // Descriptor Width + UINT64 IQA:52; // Invalidation Queue Base Address + } Bits; + UINT64 Uint64; +} VTD_IQA_REG; + typedef union { struct { UINT8 Function:3; --=20 2.26.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#96509): https://edk2.groups.io/g/devel/message/96509 Mute This Topic: https://groups.io/mt/95166947/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-