From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web10.61624.1638842224513682690 for ; Mon, 06 Dec 2021 17:57:04 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: w.sheng@intel.com) X-IronPort-AV: E=McAfee;i="6200,9189,10190"; a="224329474" X-IronPort-AV: E=Sophos;i="5.87,293,1631602800"; d="scan'208";a="224329474" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Dec 2021 17:56:13 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.87,293,1631602800"; d="scan'208";a="462109565" Received: from shwdesssddpdwei.ccr.corp.intel.com ([10.239.157.43]) by orsmga006.jf.intel.com with ESMTP; 06 Dec 2021 17:56:11 -0800 From: "Sheng Wei" To: devel@edk2.groups.io Cc: Ray Ni , Rangasai V Chaganty , Jenny Huang , Robert Kowalewski Subject: [PATCH 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once. Date: Tue, 7 Dec 2021 09:55:36 +0800 Message-Id: <20211207015536.18228-5-w.sheng@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20211207015536.18228-1-w.sheng@intel.com> References: <20211207015536.18228-1-w.sheng@intel.com> VTdInfoNotify may be called manay times, PEI DMA buffer should be generated only once. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3667 Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski Signed-off-by: Sheng Wei --- .../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 405 +++++------------ .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 340 ++++++-------- .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 501 ++++++++++++--------- .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 109 +++-- .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 175 ++++--- 5 files changed, 696 insertions(+), 834 deletions(-) diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c index e9c99d0a..a3ae65c3 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c @@ -1,6 +1,7 @@ /** @file - Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -413,142 +414,53 @@ GetPciBusDeviceFunction ( } /** - Return the index of PCI data. - - @param[in] VTdUnitInfo The VTd engine unit information. - @param[in] Segment The Segment used to identify a VTd engine. - @param[in] SourceId The SourceId used to identify a VTd engine and table entry. - - @return The index of the PCI data. - @retval (UINTN)-1 The PCI data is not found. -**/ -UINTN -GetPciDataIndex ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId - ) -{ - UINTN Index; - VTD_SOURCE_ID *PciSourceId; - PEI_PCI_DEVICE_DATA *PciDeviceDataBase; - - if (Segment != VTdUnitInfo->Segment) { - return (UINTN)-1; - } - - for (Index = 0; Index < VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber; Index++) { - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA*) (UINTN) VTdUnitInfo->PciDeviceInfo.PciDeviceData; - PciSourceId = &PciDeviceDataBase[Index].PciSourceId; - if ((PciSourceId->Bits.Bus == SourceId.Bits.Bus) && - (PciSourceId->Bits.Device == SourceId.Bits.Device) && - (PciSourceId->Bits.Function == SourceId.Bits.Function) ) { - return Index; - } - } - - return (UINTN)-1; -} - - -/** - Register PCI device to VTd engine. + Parse DMAR DRHD table. - @param[in] VTdUnitInfo The VTd engine unit information. - @param[in] Segment The segment of the source. - @param[in] SourceId The SourceId of the source. - @param[in] DeviceType The DMAR device scope type. - @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered. - FALSE: SUCCESS will be returned if the PCI device is registered. + @param[in] AcpiDmarTable DMAR ACPI table + @param[in] Callback Callback function for handle DRHD + @param[in] Context Callback function Context - @retval EFI_SUCCESS The PCI device is registered. - @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device. - @retval EFI_ALREADY_STARTED The device is already registered. + @return EFI_SUCCESS The DMAR DRHD table is parsed. **/ EFI_STATUS -RegisterPciDevice ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId, - IN UINT8 DeviceType, - IN BOOLEAN CheckExist +ParseDmarAcpiTableDrhd ( + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable, + IN PROCESS_DRHD_CALLBACK_FUNC Callback, + IN VOID *Context ) { - PEI_PCI_DEVICE_INFORMATION *PciDeviceInfo; - VTD_SOURCE_ID *PciSourceId; - UINTN PciDataIndex; - UINTN PciDeviceDataSize; - PEI_PCI_DEVICE_DATA *NewPciDeviceData; - PEI_PCI_DEVICE_DATA *PciDeviceDataBase; - - PciDeviceInfo = &VTdUnitInfo->PciDeviceInfo; - - PciDataIndex = GetPciDataIndex (VTdUnitInfo, Segment, SourceId); - if (PciDataIndex == (UINTN)-1) { - // - // Register new - // - - if (PciDeviceInfo->PciDeviceDataNumber >= PciDeviceInfo->PciDeviceDataMaxNumber) { - // - // Reallocate - // - PciDeviceDataSize = sizeof(*NewPciDeviceData) * (PciDeviceInfo->PciDeviceDataMaxNumber + MAX_VTD_PCI_DATA_NUMBER); - DEBUG ((DEBUG_INFO, "New PciDeviceDataSize:%d Page:%d\n", PciDeviceDataSize, EFI_SIZE_TO_PAGES (PciDeviceDataSize))); - NewPciDeviceData = AllocateZeroPages (EFI_SIZE_TO_PAGES(PciDeviceDataSize)); - if (NewPciDeviceData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - PciDeviceInfo->PciDeviceDataMaxNumber += MAX_VTD_PCI_DATA_NUMBER; - if (PciDeviceInfo->PciDeviceData != 0) { - CopyMem (NewPciDeviceData, (VOID *) (UINTN) PciDeviceInfo->PciDeviceData, sizeof (*NewPciDeviceData) * PciDeviceInfo->PciDeviceDataNumber); - FreePages((VOID *) (UINTN) PciDeviceInfo->PciDeviceData, PciDeviceInfo->PciDeviceDataPageSize); - } - PciDeviceInfo->PciDeviceData = (UINT32) (UINTN) NewPciDeviceData; - PciDeviceInfo->PciDeviceDataPageSize = (UINT32) EFI_SIZE_TO_PAGES (PciDeviceDataSize); - } - - ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceDataMaxNumber); - - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) PciDeviceInfo->PciDeviceData; - PciSourceId = &PciDeviceDataBase[PciDeviceInfo->PciDeviceDataNumber].PciSourceId; - PciSourceId->Bits.Bus = SourceId.Bits.Bus; - PciSourceId->Bits.Device = SourceId.Bits.Device; - PciSourceId->Bits.Function = SourceId.Bits.Function; - - DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - - PciDeviceDataBase[PciDeviceInfo->PciDeviceDataNumber].DeviceType = DeviceType; - - if ((DeviceType != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) && - (DeviceType != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) { - DEBUG ((DEBUG_INFO, " (*)")); - } - DEBUG ((DEBUG_INFO, "\n")); + EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; + UINT32 VtdIndex; - PciDeviceInfo->PciDeviceDataNumber++; - } else { - if (CheckExist) { - DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - return EFI_ALREADY_STARTED; + VtdIndex = 0; + DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1)); + while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) { + switch (DmarHeader->Type) { + case EFI_ACPI_DMAR_TYPE_DRHD: + Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); + VtdIndex++; + break; + default: + break; } + DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length); } return EFI_SUCCESS; } /** - Process DMAR DRHD table. + Parse DMAR RMRR table to get device number. + + @param[in] DmarRmrr The RMRR table. - @param[in] VTdUnitInfo The VTd engine unit information. - @param[in] DmarDrhd The DRHD table. + @return the device number **/ -VOID -ProcessDrhd ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd +UINTN +ProcessRmrrGetDeviceNumber ( + IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr ) { EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry; @@ -556,189 +468,83 @@ ProcessDrhd ( UINT8 Device; UINT8 Function; EFI_STATUS Status; - VTD_SOURCE_ID SourceId; - - DEBUG ((DEBUG_INFO," VTD BaseAddress - 0x%016lx\n", DmarDrhd->RegisterBaseAddress)); - VTdUnitInfo->VtdUnitBaseAddress = (UINT32) DmarDrhd->RegisterBaseAddress; - - VTdUnitInfo->EnableQueuedInvalidation = 0; - - DEBUG ((DEBUG_INFO," VTD Segment - %d\n", DmarDrhd->SegmentNumber)); - VTdUnitInfo->Segment = DmarDrhd->SegmentNumber; - - VTdUnitInfo->FixedSecondLevelPagingEntry = 0; - VTdUnitInfo->RmrrSecondLevelPagingEntry = 0; - VTdUnitInfo->RootEntryTable = 0; - VTdUnitInfo->ExtRootEntryTable = 0; - VTdUnitInfo->RootEntryTablePageSize = 0; - VTdUnitInfo->ExtRootEntryTablePageSize = 0; - - VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0; - - if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) { - VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE; - DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n")); - } else { - VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE; - DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n")); - } + UINTN DeviceNumber; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0; + DEBUG ((DEBUG_INFO," PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress)); - DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1)); - while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) { + DeviceNumber = 0; - Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function); - if (EFI_ERROR (Status)) { - return; - } + if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) || + (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) { + return DeviceNumber; + } - DEBUG ((DEBUG_INFO," ProcessDrhd: ")); - switch (DmarDevScopeEntry->Type) { - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT: - DEBUG ((DEBUG_INFO,"PCI Endpoint")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE: - DEBUG ((DEBUG_INFO,"PCI-PCI bridge")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC: - DEBUG ((DEBUG_INFO,"IOAPIC")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET: - DEBUG ((DEBUG_INFO,"MSI Capable HPET")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE: - DEBUG ((DEBUG_INFO,"ACPI Namespace Device")); - break; + DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1)); + while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) { + if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) { + DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%x] \n", DmarDevScopeEntry->Type)); + return DeviceNumber; } - DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumber, Bus, Device, Function)); - - SourceId.Bits.Bus = Bus; - SourceId.Bits.Device = Device; - SourceId.Bits.Function = Function; - Status = RegisterPciDevice (VTdUnitInfo, DmarDrhd->SegmentNumber, SourceId, DmarDevScopeEntry->Type, TRUE); + Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n")); + continue; } - DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length); - } -} - -/** - Dump the PCI device information managed by this VTd engine. - - @param[in] VTdInfo The VTd engine context information. - @param[in] VtdIndex The index of VTd engine. - -**/ -VOID -DumpPciDeviceInfo ( - IN VTD_INFO *VTdInfo, - IN UINTN VtdIndex - ) -{ - UINTN Index; - PEI_PCI_DEVICE_DATA *PciDeviceDataBase; - - DEBUG ((DEBUG_INFO,"PCI Device Information (Number 0x%x, IncludeAll - %d):\n", - VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceDataNumber, - VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.IncludeAllFlag - )); + DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function)); - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData; + DeviceNumber++; - for (Index = 0; Index < VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) { - DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", - VTdInfo->VtdUnitInfo[VtdIndex].Segment, - PciDeviceDataBase[Index].PciSourceId.Bits.Bus, - PciDeviceDataBase[Index].PciSourceId.Bits.Device, - PciDeviceDataBase[Index].PciSourceId.Bits.Function - )); + DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length); } + + return DeviceNumber; } /** - Parse DMAR DRHD table. + Get VTd DMAR RMRR device number. @param[in] AcpiDmarTable DMAR ACPI table - @return EFI_SUCCESS The DMAR DRHD table is parsed. - + @return the device number **/ -EFI_STATUS -ParseDmarAcpiTableDrhd ( - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable +UINTN +GetVtdRmrrDeviceNumber ( + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable ) { - EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - UINTN VtdUnitNumber; - UINTN VtdIndex; - VTD_INFO *VTdInfo; - - VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable); - if (VtdUnitNumber == 0) { - return EFI_UNSUPPORTED; - } + UINTN DeviceNumber; + EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO) + (VtdUnitNumber - 1) * sizeof (VTD_UNIT_INFO)); - ASSERT(VTdInfo != NULL); - if (VTdInfo == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Initialize the engine mask to all. - // - VTdInfo->AcpiDmarTable = (UINT32) (UINTN) AcpiDmarTable; - VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth; - VTdInfo->VTdEngineCount = (UINT32) VtdUnitNumber; + DeviceNumber = 0; - VtdIndex = 0; DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1)); while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) { switch (DmarHeader->Type) { - case EFI_ACPI_DMAR_TYPE_DRHD: - ASSERT (VtdIndex < VtdUnitNumber); - ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); - VtdIndex++; - + case EFI_ACPI_DMAR_TYPE_RMRR: + DeviceNumber += ProcessRmrrGetDeviceNumber ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader); break; - default: break; } DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length); } - ASSERT (VtdIndex == VtdUnitNumber); - - for (VtdIndex = 0; VtdIndex < VtdUnitNumber; VtdIndex++) { - DumpPciDeviceInfo (VTdInfo, VtdIndex); - } - - return EFI_SUCCESS; + return DeviceNumber; } - /** - Process DMAR RMRR table. + Parse RMRR table. - @param[in] VTdInfo The VTd engine context information. - @param[in] DmarRmrr The RMRR table. + @param[in] DmarRmrr RMRR table + @param[out] RmrrInfo The VTd RMRR information. + + @return EFI_SUCCESS The DMAR DRHD table is parsed. **/ VOID ProcessRmrr ( - IN VTD_INFO *VTdInfo, - IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr + IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr, + OUT VTD_RMRR_INFO *RmrrInfo ) { EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry; @@ -746,7 +552,7 @@ ProcessRmrr ( UINT8 Device; UINT8 Function; EFI_STATUS Status; - VTD_SOURCE_ID SourceId; + UINTN DeviceIndex; DEBUG ((DEBUG_INFO," PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress)); @@ -755,6 +561,11 @@ ProcessRmrr ( return ; } + RmrrInfo->SegmentNumber = DmarRmrr->SegmentNumber; + RmrrInfo->ReservedMemoryRegionBaseAddress = DmarRmrr->ReservedMemoryRegionBaseAddress; + RmrrInfo->ReservedMemoryRegionLimitAddress = DmarRmrr->ReservedMemoryRegionLimitAddress; + DeviceIndex = 0; + DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1)); while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) { if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) { @@ -766,50 +577,39 @@ ProcessRmrr ( if (EFI_ERROR (Status)) { continue; } + ASSERT (DeviceIndex < RmrrInfo->DeviceNumber); DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function)); - SourceId.Bits.Bus = Bus; - SourceId.Bits.Device = Device; - SourceId.Bits.Function = Function; - - Status = EnableRmrrPageAttribute ( - VTdInfo, - DmarRmrr->SegmentNumber, - SourceId, - DmarRmrr->ReservedMemoryRegionBaseAddress, - DmarRmrr->ReservedMemoryRegionLimitAddress, - EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "EnableRmrrPageAttribute : %r\n", Status)); - } + RmrrInfo->SourceId[DeviceIndex].Bits.Bus = Bus; + RmrrInfo->SourceId[DeviceIndex].Bits.Device = Device; + RmrrInfo->SourceId[DeviceIndex].Bits.Function = Function; + DeviceIndex++; DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length); } } /** - Parse DMAR DRHD table. + Parse DMAR RMRR table. - @param[in] VTdInfo The VTd engine context information. + @param[in] AcpiDmarTable DMAR ACPI table + @param[out] RmrrInfo The VTd RMRR information. **/ VOID -ParseDmarAcpiTableRmrr ( - IN VTD_INFO *VTdInfo +ParseRmrrDmarAcpiTable ( + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable, + OUT VTD_RMRR_INFO *RmrrInfo ) { - EFI_ACPI_DMAR_HEADER *AcpiDmarTable; EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - AcpiDmarTable = (EFI_ACPI_DMAR_HEADER *) (UINTN) VTdInfo->AcpiDmarTable; - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1)); while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) { switch (DmarHeader->Type) { case EFI_ACPI_DMAR_TYPE_RMRR: - ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader); + ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader, RmrrInfo); break; default: break; @@ -818,3 +618,36 @@ ParseDmarAcpiTableRmrr ( } } +/** + Get RMRR Info from ACPI DMAR Table. + + @param[in] AcpiDmarTable DMAR ACPI table + + @return the VTd engine number. +**/ +VTD_RMRR_INFO * +GetVtdRmrrInfo ( + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable + ) +{ + UINTN DeviceNumber; + VTD_RMRR_INFO *RmrrInfo; + UINTN InfoSize; + + RmrrInfo = NULL; + DeviceNumber = GetVtdRmrrDeviceNumber (AcpiDmarTable); + + if (DeviceNumber > 0) { + InfoSize = sizeof (VTD_RMRR_INFO) - sizeof (VTD_SOURCE_ID) + sizeof (VTD_SOURCE_ID) * DeviceNumber; + RmrrInfo = (VTD_RMRR_INFO *) AllocateZeroPages (EFI_SIZE_TO_PAGES (InfoSize)); + if (RmrrInfo == NULL) { + DEBUG ((DEBUG_ERROR, "GetVtdRmrrInfo - OUT_OF_RESOURCE\n")); + ASSERT (FALSE); + return NULL; + } + + RmrrInfo->DeviceNumber = (UINT16) DeviceNumber; + ParseRmrrDmarAcpiTable (AcpiDmarTable, RmrrInfo); + } + return RmrrInfo; +} diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index 63397a1a..91694797 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -79,7 +79,7 @@ PerpareCacheInvalidationInterface ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT16 QueueSize; + UINT16 QiDescLength; UINT64 Reg64; UINT32 Reg32; VTD_ECAP_REG ECapReg; @@ -109,12 +109,6 @@ PerpareCacheInvalidationInterface ( Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) != 0); MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, 0); - - if (VTdUnitInfo->QiDesc != NULL) { - FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength)); - VTdUnitInfo->QiDesc = NULL; - VTdUnitInfo->QiDescLength = 0; - } } // @@ -125,19 +119,19 @@ PerpareCacheInvalidationInterface ( // // Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register // - QueueSize = 0; - VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8); - VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength)); - if (VTdUnitInfo->QiDesc == NULL) { - VTdUnitInfo->QiDescLength = 0; - DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); - return EFI_OUT_OF_RESOURCES; + VTdUnitInfo->QueueSize = 0; + QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); + VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength)); + if (VTdUnitInfo->QiDesc == NULL) { + DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); + return EFI_OUT_OF_RESOURCES; + } } - DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiDescLength)); + DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", QiDescLength)); Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc; - Reg64 |= QueueSize; + Reg64 |= VTdUnitInfo->QueueSize; MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, Reg64); // @@ -167,7 +161,8 @@ DisableQueuedInvalidationInterface ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT32 Reg32; + UINT32 Reg32; + UINT16 QiDescLength; if (VTdUnitInfo->EnableQueuedInvalidation != 0) { Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); @@ -179,9 +174,10 @@ DisableQueuedInvalidationInterface ( } while ((Reg32 & B_GSTS_REG_QIES) != 0); if (VTdUnitInfo->QiDesc != NULL) { - FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength)); + QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); + FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength)); VTdUnitInfo->QiDesc = NULL; - VTdUnitInfo->QiDescLength = 0; + VTdUnitInfo->QueueSize = 0; } VTdUnitInfo->EnableQueuedInvalidation = 0; @@ -204,24 +200,9 @@ QueuedInvalidationCheckFault ( UINT32 FaultReg; FaultReg = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG); - - if (FaultReg & B_FSTS_REG_IQE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", FaultReg)); - FaultReg |= B_FSTS_REG_IQE; - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); - return RETURN_DEVICE_ERROR; - } - - if (FaultReg & B_FSTS_REG_ITE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", FaultReg)); - FaultReg |= B_FSTS_REG_ITE; - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); - return RETURN_DEVICE_ERROR; - } - - if (FaultReg & B_FSTS_REG_ICE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", FaultReg)); - FaultReg |= B_FSTS_REG_ICE; + if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) { + DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg)); + FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE); MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); return RETURN_DEVICE_ERROR; } @@ -256,7 +237,7 @@ SubmitQueuedInvalidationDescriptor ( return EFI_INVALID_PARAMETER; } - QiDescLength = VTdUnitInfo->QiDescLength; + QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); BaseDesc = VTdUnitInfo->QiDesc; DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%08x, 0x%08x]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High)); @@ -391,15 +372,15 @@ InvalidateIOTLB ( **/ EFI_STATUS EnableDmarPreMem ( - IN UINTN VtdUnitBaseAddress, - IN UINTN RtaddrRegValue + IN UINT32 VtdUnitBaseAddress, + IN UINT64 RtaddrRegValue ) { UINT32 Reg32; DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUnitBaseAddress)); - DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%x \n", RtaddrRegValue)); + DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue)); MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RtaddrRegValue); Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); @@ -566,139 +547,52 @@ DisableDmar ( } /** - Dump VTd version registers. - - @param[in] VerReg The version register. -**/ -VOID -DumpVtdVerRegs ( - IN VTD_VER_REG *VerReg - ) -{ - DEBUG ((DEBUG_INFO, " VerReg:\n", VerReg->Uint32)); - DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major)); - DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor)); -} + Enable VTd translation table protection for block DMA -/** - Dump VTd capability registers. + @param[in] VtdUnitBaseAddress The base address of the VTd engine. - @param[in] CapReg The capability register. + @retval EFI_SUCCESS DMAR translation is enabled. + @retval EFI_DEVICE_ERROR DMAR translation is not enabled. **/ -VOID -DumpVtdCapRegs ( - IN VTD_CAP_REG *CapReg - ) -{ - DEBUG ((DEBUG_INFO, " CapReg:\n", CapReg->Uint64)); - DEBUG ((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND)); - DEBUG ((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL)); - DEBUG ((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF)); - DEBUG ((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR)); - DEBUG ((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR)); - DEBUG ((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM)); - DEBUG ((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW)); - DEBUG ((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW)); - DEBUG ((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR)); - DEBUG ((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO)); - DEBUG ((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS)); - DEBUG ((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI)); - DEBUG ((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR)); - DEBUG ((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV)); - DEBUG ((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD)); - DEBUG ((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD)); - DEBUG ((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP)); - DEBUG ((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI)); -} - -/** - Dump VTd extended capability registers. - - @param[in] ECapReg The extended capability register. -**/ -VOID -DumpVtdECapRegs ( - IN VTD_ECAP_REG *ECapReg - ) -{ - DEBUG ((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64)); - DEBUG ((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C)); - DEBUG ((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI)); - DEBUG ((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT)); - DEBUG ((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR)); - DEBUG ((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM)); - DEBUG ((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT)); - DEBUG ((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC)); - DEBUG ((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO)); - DEBUG ((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV)); - DEBUG ((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS)); - DEBUG ((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST)); - DEBUG ((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID)); - DEBUG ((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS)); - DEBUG ((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS)); - DEBUG ((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS)); - DEBUG ((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS)); - DEBUG ((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS)); - DEBUG ((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS)); - DEBUG ((DEBUG_INFO, " ADMS - 0x%x\n", ECapReg->Bits.ADMS)); -} - - -/** - Enable VTd translation table protection for all. - - @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. -**/ -VOID -EnableVTdTranslationProtectionAll ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask +EFI_STATUS +EnableVTdTranslationProtectionBlockDma ( + IN UINT32 VtdUnitBaseAddress ) { - EFI_STATUS Status; - EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI *RootEntryTable; - UINTN Index; + EFI_STATUS Status; + VTD_ECAP_REG ECapReg; + EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI *RootEntryTable; - DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionAll - 0x%lx\n", EngineMask)); + DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n", VtdUnitBaseAddress)); - for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - if ((EngineMask & LShiftU64(1, Index)) == 0) { - continue; - } + ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); + DEBUG ((DEBUG_INFO, "ECapReg : 0%016lx\n", ECapReg.Uint64)); - VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG); - DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg); - VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG); - DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg); - VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG); - DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg); - - if (VTdInfo->VtdUnitInfo[Index].ECapReg.Bits.ADMS == 1) { - // - // Use Abort DMA Mode - // - Status = EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM); - } else { - // - // Use Null Root Entry Table - // - Status = PeiServicesLocatePpi ( - &gEdkiiVTdNullRootEntryTableGuid, - 0, - NULL, - (VOID **)&RootEntryTable - ); - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status)); - ASSERT (FALSE); - return; - } - EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable); + if (ECapReg.Bits.ADMS == 1) { + // + // Use Abort DMA Mode + // + DEBUG ((DEBUG_INFO, "Enable abort DMA mode.\n")); + Status = EnableDmarPreMem (VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM); + } else { + // + // Use Null Root Entry Table + // + Status = PeiServicesLocatePpi ( + &gEdkiiVTdNullRootEntryTableGuid, + 0, + NULL, + (VOID **)&RootEntryTable + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status)); + ASSERT (FALSE); + return EFI_DEVICE_ERROR; } + Status = EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) *RootEntryTable); } - return; + return Status; } /** @@ -715,18 +609,25 @@ EnableVTdTranslationProtection ( ) { EFI_STATUS Status; - UINTN VtdIndex; + UINTN Index; + VTD_UNIT_INFO *VtdUnitInfo; + + for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { + VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index)); + continue; + } - for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) { - if (VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable != 0) { - DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable)); - Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex], VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable); + if (VtdUnitInfo->ExtRootEntryTable != 0) { + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", Index, VtdUnitInfo->ExtRootEntryTable)); + Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable); } else { - DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable)); - Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex], VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable); + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", Index, VtdUnitInfo->RootEntryTable)); + Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->RootEntryTable); } if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", VtdIndex)); + DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", Index)); return Status; } } @@ -737,22 +638,21 @@ EnableVTdTranslationProtection ( Disable VTd translation table protection. @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. **/ VOID DisableVTdTranslationProtection ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask + IN VTD_INFO *VTdInfo ) { UINTN Index; - DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask)); + if (VTdInfo == NULL) { + return; + } + + DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - %d Vtd Engine\n", VTdInfo->VTdEngineCount)); for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - if ((EngineMask & LShiftU64(1, Index)) == 0) { - continue; - } DisableDmar ((UINTN) VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress); DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]); @@ -786,6 +686,36 @@ PrepareVtdCacheInvalidationConfig ( return EFI_SUCCESS; } +/** + +**/ +EFI_STATUS +VtdCheckUsing5LevelPaging ( + IN UINT8 HostAddressWidth, + IN VTD_UNIT_INFO *VtdUnitInfo, + OUT BOOLEAN *Is5LevelPaging + ) +{ + DEBUG((DEBUG_INFO, " CapReg SAGAW bits : 0x%02x\n", VtdUnitInfo->CapReg.Bits.SAGAW)); + + *Is5LevelPaging = FALSE; + if ((VtdUnitInfo->CapReg.Bits.SAGAW & BIT3) != 0) { + *Is5LevelPaging = TRUE; + if ((HostAddressWidth <= 48) && + ((VtdUnitInfo->CapReg.Bits.SAGAW & BIT2) != 0)) { + *Is5LevelPaging = FALSE; + } else { + return EFI_UNSUPPORTED; + } + } + if ((VtdUnitInfo->CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) { + return EFI_UNSUPPORTED; + } + DEBUG((DEBUG_INFO, " Using %d Level Paging\n", *Is5LevelPaging ? 5 : 4)); + return EFI_SUCCESS; +} + + /** Prepare VTD configuration. @@ -798,43 +728,35 @@ PrepareVtdConfig ( IN VTD_INFO *VTdInfo ) { + EFI_STATUS Status; UINTN Index; - UINTN DomainNumber; + VTD_UNIT_INFO *VtdUnitInfo; for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - DEBUG ((DEBUG_ERROR, "Dump VTd Capability (%d)\n", Index)); - VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG); - DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg); - VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG); - DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg); - VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG); - DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg); - - VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = FALSE; - if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT2) != 0) { - DEBUG ((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index)); - } - if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT3) != 0) { - DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index)); - VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = TRUE; - - if ((VTdInfo->HostAddressWidth <= 48) && - ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT2) != 0)) { - DEBUG ((DEBUG_INFO, "Rollback to 4-level page-table on VTD %d\n", Index)); - VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = FALSE; - } + VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + continue; } - if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) { - DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on VTD %d !!!!\n", Index, VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW)); - return EFI_UNSUPPORTED; + DEBUG((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitInfo->VtdUnitBaseAddress)); + + VtdUnitInfo->VerReg.Uint32 = MmioRead32 (VtdUnitInfo->VtdUnitBaseAddress + R_VER_REG); + VtdUnitInfo->CapReg.Uint64 = MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CAP_REG); + VtdUnitInfo->ECapReg.Uint64 = MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); + DEBUG((DEBUG_INFO, " VerReg : 0x%08X\n", VtdUnitInfo->VerReg.Uint32)); + DEBUG((DEBUG_INFO, " CapReg : 0x%016lX\n", VtdUnitInfo->CapReg.Uint64)); + DEBUG((DEBUG_INFO, " ECapReg : 0x%016lX\n", VtdUnitInfo->ECapReg.Uint64)); + + Status = VtdCheckUsing5LevelPaging (VTdInfo->HostAddressWidth, VtdUnitInfo, &(VtdUnitInfo->Is5LevelPaging)); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported!!!!\n", VtdUnitInfo->CapReg.Bits.SAGAW)); + return Status; } - DomainNumber = (UINTN)1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[Index].CapReg.Bits.ND * 2 + 4); - if (VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber >= DomainNumber) { - DEBUG ((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber, DomainNumber)); - return EFI_UNSUPPORTED; + Status = PerpareCacheInvalidationInterface(VtdUnitInfo); + if (EFI_ERROR (Status)) { + return Status; } } + return EFI_SUCCESS; } - diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c index a8f7bfee..fd2f4dd3 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -50,20 +50,20 @@ typedef struct { the device driver need use SetAttribute() to update the IOMMU attribute to request DMA access (read and/or write). - @param[in] This The PPI instance pointer. - @param[in] DeviceHandle The device who initiates the DMA access request. - @param[in] Mapping The mapping value returned from Map(). - @param[in] IoMmuAccess The IOMMU access. - - @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. - @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). - @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. - @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. - @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. - @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @param[in] This The PPI instance pointer. + @param[in] DeviceHandle The device who initiates the DMA access request. + @param[in] Mapping The mapping value returned from Map(). + @param[in] IoMmuAccess The IOMMU access. + + @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. + @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -93,22 +93,22 @@ PeiIoMmuSetAttribute ( Provides the controller-specific addresses required to access system memory from a DMA bus master. - @param This The PPI instance pointer. - @param Operation Indicates if the bus master is going to read or write to system memory. - @param HostAddress The system memory address to map to the PCI controller. - @param NumberOfBytes On input the number of bytes to map. On output the number of bytes - that were mapped. - @param DeviceAddress The resulting map address for the bus master PCI controller to use to - access the hosts HostAddress. - @param Mapping A resulting value to pass to Unmap(). - - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @param [in] This The PPI instance pointer. + @param [in] Operation Indicates if the bus master is going to read or write to system memory. + @param [in] HostAddress The system memory address to map to the PCI controller. + @param [in] [out] NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param [out] DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param [out] Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -184,14 +184,14 @@ PeiIoMmuMap ( /** Completes the Map() operation and releases any corresponding resources. - @param This The PPI instance pointer. - @param Mapping The mapping value returned from Map(). + @param [in] This The PPI instance pointer. + @param [in] Mapping The mapping value returned from Map(). - @retval EFI_SUCCESS The range was unmapped. - @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -250,21 +250,21 @@ PeiIoMmuUnmap ( Allocates pages that are suitable for an OperationBusMasterCommonBuffer or OperationBusMasterCommonBuffer64 mapping. - @param This The PPI instance pointer. - @param MemoryType The type of memory to allocate, EfiBootServicesData or - EfiRuntimeServicesData. - @param Pages The number of pages to allocate. - @param HostAddress A pointer to store the base system memory address of the - allocated range. - @param Attributes The requested bit mask of attributes for the allocated range. - - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are - MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @param [in] This The PPI instance pointer. + @param [in] MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param [in] Pages The number of pages to allocate. + @param [in] [out] HostAddress A pointer to store the base system memory address of the + allocated range. + @param [in] Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -307,15 +307,15 @@ PeiIoMmuAllocateBuffer ( /** Frees memory that was allocated with AllocateBuffer(). - @param This The PPI instance pointer. - @param Pages The number of pages to free. - @param HostAddress The base system memory address of the allocated range. + @param [in] This The PPI instance pointer. + @param [in] Pages The number of pages to free. + @param [in] HostAddress The base system memory address of the allocated range. - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages - was not allocated with AllocateBuffer(). - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -364,52 +364,147 @@ CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = { }; /** - Release the momery in the Intel VTd Info + Get ACPI DMAT Table from EdkiiVTdInfo PPI - @param[in] VTdInfo The VTd engine context information. + @retval Address ACPI DMAT Table address + @retval NULL Failed to get ACPI DMAT Table **/ -VOID -ReleaseVTdInfo ( - IN VTD_INFO *VTdInfo +EFI_ACPI_DMAR_HEADER * GetAcpiDmarTable ( + VOID ) { - UINTN Index; + EFI_STATUS Status; + EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - DEBUG ((DEBUG_INFO, "Release momery in VTdInfo[%d]\n", Index)); + // + // Get the DMAR table + // + Status = PeiServicesLocatePpi ( + &gEdkiiVTdInfoPpiGuid, + 0, + NULL, + (VOID **)&AcpiDmarTable + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to get ACPI DMAR Table : %r\n", Status)); + AcpiDmarTable = NULL; + } else { + DumpAcpiDMAR (AcpiDmarTable); + } - if (VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry, 1); - VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry = 0; - } + return AcpiDmarTable; +} - if (VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry, 1); - VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry = 0; - } +/** + Get the VTd engine context information hob. - if (VTdInfo->VtdUnitInfo[Index].RootEntryTable) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].RootEntryTable, VTdInfo->VtdUnitInfo[Index].RootEntryTablePageSize); - VTdInfo->VtdUnitInfo[Index].RootEntryTable = 0; - } + @retval The VTd engine context information. - if (VTdInfo->VtdUnitInfo[Index].ExtRootEntryTable) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].ExtRootEntryTable, VTdInfo->VtdUnitInfo[Index].ExtRootEntryTablePageSize); - VTdInfo->VtdUnitInfo[Index].RootEntryTable = 0; +**/ +VTD_INFO * +GetVTdInfoHob ( + VOID + ) +{ + VOID *Hob; + VTD_INFO *VTdInfo; + + Hob = GetFirstGuidHob (&mVTdInfoGuid); + if (Hob == NULL) { + VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO)); + if (VTdInfo != NULL) { + ZeroMem (VTdInfo, sizeof (VTD_INFO)); } + } else { + VTdInfo = GET_GUID_HOB_DATA(Hob); + } + return VTdInfo; +} + +/** + Callback function of parse DMAR DRHD table in pre-memory phase. - if (VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData, VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataPageSize); - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataPageSize = 0; - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData = 0; - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber = 0; - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataMaxNumber = 0; + @param [in] [out] Context Callback function context. + @param [in] VTdIndex The VTd engine index. + @param [in] DmarDrhd The DRHD table. + +**/ +VOID +ProcessDhrdPreMemory ( + IN OUT VOID *Context, + IN UINT32 VTdIndex, + IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd + ) +{ + DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, DmarDrhd->RegisterBaseAddress)); + + EnableVTdTranslationProtectionBlockDma ((UINT32) DmarDrhd->RegisterBaseAddress); +} + + +/** + Compare 2 RMRR contexts are same or not. + + @param[in] Destin Destiny RMRR Info + @param[in] Source Source RMRR Info + + @retval Same or not same + +**/ +BOOLEAN +CompareVTdRmrrInfo ( + IN VTD_RMRR_INFO *Destin, + IN VTD_RMRR_INFO *Source + ) +{ + UINT16 InfoSize; + + if ((Destin == NULL) && (Source == NULL)) { + return TRUE; + } + + if ((Destin != NULL) && (Source != NULL)) { + if (Destin->DeviceNumber == Source->DeviceNumber) { + InfoSize = sizeof (VTD_RMRR_INFO) - sizeof (VTD_SOURCE_ID) + sizeof (VTD_SOURCE_ID) * Destin->DeviceNumber; + if (CompareMem (Destin, Source, InfoSize) == 0) { + return TRUE; + } } } + return FALSE; +} + +/** + Callback function of parse DMAR DRHD table in post memory phase. + + @param [in] [out] Context Callback function context. + @param [in] VTdIndex The VTd engine index. + @param [in] DmarDrhd The DRHD table. + +**/ +VOID +ProcessDrhdPostMemory ( + IN OUT VOID *Context, + IN UINT32 VTdIndex, + IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd + ) +{ + VTD_UNIT_INFO *VtdUnitInfo; + + VtdUnitInfo = (VTD_UNIT_INFO *) Context; + VtdUnitInfo += VTdIndex; + + VtdUnitInfo->Done = FALSE; + VtdUnitInfo->VtdUnitBaseAddress = (UINT32) DmarDrhd->RegisterBaseAddress; + VtdUnitInfo->Segment = DmarDrhd->SegmentNumber; + VtdUnitInfo->Flags = DmarDrhd->Flags; + + DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, DmarDrhd->RegisterBaseAddress)); + DEBUG ((DEBUG_INFO," Segment - %d, Flags - 0x%x\n", DmarDrhd->SegmentNumber, DmarDrhd->Flags)); } /** - Initializes the Intel VTd Info. + Initializes the Intel VTd Info in post memory phase. @retval EFI_SUCCESS Usb bot driver is successfully initialized. @retval EFI_OUT_OF_RESOURCES Can't initialize the driver. @@ -419,89 +514,96 @@ InitVTdInfo ( VOID ) { - EFI_STATUS Status; EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - VOID *Hob; + VTD_RMRR_INFO *RmrrInfo; + BOOLEAN RmrrInfoEqual; VTD_INFO *VTdInfo; - UINT64 EngineMask; - - Status = PeiServicesLocatePpi ( - &gEdkiiVTdInfoPpiGuid, - 0, - NULL, - (VOID **)&AcpiDmarTable - ); - ASSERT_EFI_ERROR (Status); + VTD_UNIT_INFO *VtdUnitInfo; + UINTN VtdUnitNumber; + EFI_STATUS Status; + UINTN i; + UINTN j; - DumpAcpiDMAR (AcpiDmarTable); + VTdInfo = GetVTdInfoHob (); + ASSERT (VTdInfo != NULL); - // - // Clear old VTdInfo Hob. - // - Hob = GetFirstGuidHob (&mVTdInfoGuid); - if (Hob != NULL) { - DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob)); + AcpiDmarTable = GetAcpiDmarTable (); + ASSERT (AcpiDmarTable != NULL); - VTdInfo = GET_GUID_HOB_DATA(Hob); - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; - EnableVTdTranslationProtectionAll (VTdInfo, EngineMask); - - ReleaseVTdInfo (VTdInfo); - VTdInfo->VTdEngineCount = 0; + VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable); + if (VtdUnitNumber == 0) { + return EFI_UNSUPPORTED; + } + RmrrInfo = GetVtdRmrrInfo (AcpiDmarTable); + RmrrInfoEqual = CompareVTdRmrrInfo (VTdInfo->VtdRmrrInfo, RmrrInfo); - ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID)); + VtdUnitInfo = AllocateZeroPages (EFI_SIZE_TO_PAGES (sizeof (VTD_UNIT_INFO) * VtdUnitNumber)); + if (VtdUnitInfo == NULL) { + DEBUG ((DEBUG_ERROR, "InitVTdInfo - OUT_OF_RESOURCE\n")); + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; } - // - // Get DMAR information to local VTdInfo - // - Status = ParseDmarAcpiTableDrhd (AcpiDmarTable); - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR, " ParseDmarAcpiTableDrhd : %r\n", Status)); + Status = ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDrhdPostMemory, VtdUnitInfo); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); return Status; } // - // NOTE: Do not parse RMRR here, because RMRR may cause DMAR programming. + // Check Host Address Width // + if ((AcpiDmarTable->HostAddressWidth == VTdInfo->HostAddressWidth) && RmrrInfoEqual) { + for (i = 0; i < VtdUnitNumber; i++) { + // + // Scan each new Vtd Unit + // + for (j = 0; j < VTdInfo->VTdEngineCount; j++) { + // + // Compare the new Vtd Unit with each exist VTd Unit + // + if (VtdUnitInfo[i].VtdUnitBaseAddress == VTdInfo->VtdUnitInfo[j].VtdUnitBaseAddress) { + DEBUG ((DEBUG_INFO,"Find VTD [0x%08lx] Exist\n", VtdUnitInfo[i].VtdUnitBaseAddress)); + CopyMem (&VtdUnitInfo[i], &VTdInfo->VtdUnitInfo[j], sizeof (VTD_UNIT_INFO)); + VtdUnitInfo[i].Done = TRUE; + + break; + } + } + } + } + VTdInfo->AcpiDmarTable = (UINT32) AcpiDmarTable; + VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth; + VTdInfo->VTdEngineCount = VtdUnitNumber; + VTdInfo->VtdUnitInfo = VtdUnitInfo; + VTdInfo->VtdRmrrInfo = RmrrInfo; return EFI_SUCCESS; } /** - Initializes the Intel VTd DMAR for all memory. + Initializes the Intel VTd DMAR for block all DMA. @retval EFI_SUCCESS Driver is successfully initialized. @retval RETURN_NOT_READY Fail to get VTdInfo Hob . **/ EFI_STATUS -InitVTdDmarForAll ( +InitVTdDmarBlockAll ( VOID ) { - VOID *Hob; - VTD_INFO *VTdInfo; - UINT64 EngineMask; - EFI_STATUS Status; - - Hob = GetFirstGuidHob (&mVTdInfoGuid); - if (Hob == NULL) { - DEBUG ((DEBUG_ERROR, "Fail to get VTdInfo Hob.\n")); - return RETURN_NOT_READY; - } - VTdInfo = GET_GUID_HOB_DATA (Hob); - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; - - DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); - Status = PrepareVtdConfig (VTdInfo); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } + EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - EnableVTdTranslationProtectionAll (VTdInfo, EngineMask); + // + // Get the DMAR table + // + AcpiDmarTable = GetAcpiDmarTable (); + ASSERT (AcpiDmarTable != NULL); - return EFI_SUCCESS; + // + // Parse the DMAR table and block all DMA + // + return ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDhrdPreMemory, NULL); } /** @@ -524,8 +626,8 @@ InitDmaBuffer( DEBUG ((DEBUG_INFO, "InitDmaBuffer :\n")); Hob = GetFirstGuidHob (&mDmaBufferInfoGuid); + ASSERT(Hob != NULL); DmaBufferInfo = GET_GUID_HOB_DATA (Hob); - VtdPmrHobPtr = GetFirstGuidHob (&gVtdPmrInfoDataHobGuid); /** When gVtdPmrInfoDataHobGuid exists, it means: @@ -535,7 +637,7 @@ InitDmaBuffer( 4. Protection regions will be conveyed through VTD_PMR_INFO_HOB When gVtdPmrInfoDataHobGuid dosen't exist, it means: - 1. IntelVTdDmar driver will calcuate the PMR memory alignment + 1. IntelVTdDmarPei driver will calcuate the protected memory alignment 2. Dma buffer is reserved by AllocateAlignedPages() **/ @@ -545,31 +647,38 @@ InitDmaBuffer( return EFI_INVALID_PARAMETER; } - if (VtdPmrHobPtr == NULL) { - // - // Allocate memory for DMA buffer - // - DmaBufferInfo->DmaBufferBase = (UINT64) (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) DmaBufferInfo->DmaBufferSize), 0); - if (DmaBufferInfo->DmaBufferBase == 0) { - DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n")); - return EFI_OUT_OF_RESOURCES; + if (DmaBufferInfo->DmaBufferBase == 0) { + VtdPmrHobPtr = GetFirstGuidHob (&gVtdPmrInfoDataHobGuid); + if (VtdPmrHobPtr != NULL) { + // + // Get the protected memory ranges information from the VTd PMR hob + // + VtdPmrHob = GET_GUID_HOB_DATA (VtdPmrHobPtr); + + if ((VtdPmrHob->ProtectedHighBase - VtdPmrHob->ProtectedLowLimit) < DmaBufferInfo->DmaBufferSize) { + DEBUG ((DEBUG_ERROR, " DmaBufferSize not enough\n")); + return EFI_INVALID_PARAMETER; + } + DmaBufferInfo->DmaBufferBase = VtdPmrHob->ProtectedLowLimit; + } else { + // + // Allocate memory for DMA buffer + // + DmaBufferInfo->DmaBufferBase = (UINT64) (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) DmaBufferInfo->DmaBufferSize), 0); + if (DmaBufferInfo->DmaBufferBase == 0) { + DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n")); + return EFI_OUT_OF_RESOURCES; + } + DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n")); } - DmaBufferInfo->DmaBufferLimit = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; - DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n")); - } else { - // - // Get the PMR ranges information for the VTd PMR hob - // - VtdPmrHob = GET_GUID_HOB_DATA (VtdPmrHobPtr); - DmaBufferInfo->DmaBufferBase = VtdPmrHob->ProtectedLowLimit; - DmaBufferInfo->DmaBufferLimit = VtdPmrHob->ProtectedHighBase; + + DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; + DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase; + + DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%lx\n", DmaBufferInfo->DmaBufferSize)); + DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%lx\n", DmaBufferInfo->DmaBufferBase)); } - DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; - DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase; - DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%lx\n", DmaBufferInfo->DmaBufferSize)); - DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%lx\n", DmaBufferInfo->DmaBufferBase)); - DEBUG ((DEBUG_INFO, " DmaBufferLimit : 0x%lx\n", DmaBufferInfo->DmaBufferLimit)); DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%lx\n", DmaBufferInfo->DmaBufferCurrentTop)); DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%lx\n", DmaBufferInfo->DmaBufferCurrentBottom)); @@ -588,14 +697,14 @@ InitVTdDmarForDma ( VOID ) { - VOID *Hob; VTD_INFO *VTdInfo; + EFI_STATUS Status; EFI_PEI_PPI_DESCRIPTOR *OldDescriptor; EDKII_IOMMU_PPI *OldIoMmuPpi; - Hob = GetFirstGuidHob (&mVTdInfoGuid); - VTdInfo = GET_GUID_HOB_DATA (Hob); + VTdInfo = GetVTdInfoHob (); + ASSERT (VTdInfo != NULL); DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); Status = PrepareVtdConfig (VTdInfo); @@ -604,13 +713,6 @@ InitVTdDmarForDma ( return Status; } - DEBUG ((DEBUG_INFO, "PrepareVtdCacheInvalidationConfig\n")); - Status = PrepareVtdCacheInvalidationConfig (VTdInfo); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - // create root entry table DEBUG ((DEBUG_INFO, "SetupTranslationTable\n")); Status = SetupTranslationTable (VTdInfo); @@ -620,8 +722,11 @@ InitVTdDmarForDma ( } // If there is RMRR memory, parse it here. - DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n")); - ParseDmarAcpiTableRmrr (VTdInfo); + Status = SetupRmrr (VTdInfo); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } DEBUG ((DEBUG_INFO, "EnableVtdDmar\n")); Status = EnableVTdTranslationProtection(VTdInfo); @@ -668,21 +773,10 @@ S3EndOfPeiNotify( IN VOID *Ppi ) { - VOID *Hob; - VTD_INFO *VTdInfo; - UINT64 EngineMask; - DEBUG((DEBUG_INFO, "VTd DMAR PEI S3EndOfPeiNotify\n")); if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) { - Hob = GetFirstGuidHob (&mVTdInfoGuid); - if (Hob == NULL) { - return EFI_SUCCESS; - } - VTdInfo = GET_GUID_HOB_DATA(Hob); - - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; - DisableVTdTranslationProtection (VTdInfo, EngineMask); + DisableVTdTranslationProtection (GetVTdInfoHob ()); } return EFI_SUCCESS; } @@ -733,18 +827,13 @@ VTdInfoNotify ( DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized)); - // - // NOTE: We need reinit VTdInfo because previous information might be overriden. - // - InitVTdInfo (); - if (!MemoryInitialized) { // // If the memory is not initialized, // Protect all system memory // - InitVTdDmarForAll (); + InitVTdDmarBlockAll (); // // Install PPI. @@ -758,9 +847,16 @@ VTdInfoNotify ( // Status = InitDmaBuffer (); - ASSERT_EFI_ERROR(Status); + ASSERT_EFI_ERROR (Status); - InitVTdDmarForDma (); + // + // NOTE: We need reinit VTdInfo because previous information might be overriden. + // + Status = InitVTdInfo (); + ASSERT_EFI_ERROR (Status); + + Status = InitVTdDmarForDma (); + ASSERT_EFI_ERROR (Status); } return EFI_SUCCESS; @@ -826,4 +922,3 @@ IntelVTdDmarInitialize ( return EFI_SUCCESS; } - diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h index e23a6c8e..74667277 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h @@ -9,68 +9,71 @@ #ifndef __DMA_ACCESS_LIB_H__ #define __DMA_ACCESS_LIB_H__ -#define MAX_VTD_PCI_DATA_NUMBER 0x100 - #define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32)) typedef struct { - UINT8 DeviceType; - VTD_SOURCE_ID PciSourceId; -} PEI_PCI_DEVICE_DATA; - -typedef struct { - BOOLEAN IncludeAllFlag; - UINT32 PciDeviceDataNumber; - UINT32 PciDeviceDataMaxNumber; - UINT32 PciDeviceDataPageSize; - UINT32 PciDeviceData; -} PEI_PCI_DEVICE_INFORMATION; + UINT16 SegmentNumber; + UINT64 ReservedMemoryRegionBaseAddress; + UINT64 ReservedMemoryRegionLimitAddress; + UINT16 DeviceNumber; + VTD_SOURCE_ID SourceId[1]; +} VTD_RMRR_INFO; typedef struct { + BOOLEAN Done; UINT32 VtdUnitBaseAddress; UINT16 Segment; + UINT8 Flags; VTD_VER_REG VerReg; VTD_CAP_REG CapReg; VTD_ECAP_REG ECapReg; BOOLEAN Is5LevelPaging; + UINT8 EnableQueuedInvalidation; + UINT16 QueueSize; + QI_DESC *QiDesc; + UINT16 QiFreeHead; UINT32 FixedSecondLevelPagingEntry; - UINT32 RmrrSecondLevelPagingEntry; UINT32 RootEntryTable; UINT32 ExtRootEntryTable; UINT16 RootEntryTablePageSize; UINT16 ExtRootEntryTablePageSize; - PEI_PCI_DEVICE_INFORMATION PciDeviceInfo; - UINT8 EnableQueuedInvalidation; - UINT16 QiDescLength; - QI_DESC *QiDesc; - UINT16 QiFreeHead; + UINT32 RmrrSecondLevelPagingEntry; } VTD_UNIT_INFO; typedef struct { UINT32 AcpiDmarTable; UINT8 HostAddressWidth; UINT32 VTdEngineCount; - VTD_UNIT_INFO VtdUnitInfo[1]; + VTD_UNIT_INFO *VtdUnitInfo; + VTD_RMRR_INFO *VtdRmrrInfo; } VTD_INFO; typedef struct { UINT64 DmaBufferBase; UINT64 DmaBufferSize; - UINT64 DmaBufferLimit; UINT64 DmaBufferCurrentTop; UINT64 DmaBufferCurrentBottom; } DMA_BUFFER_INFO; +typedef +VOID +(EFIAPI *PROCESS_DRHD_CALLBACK_FUNC) ( + IN OUT VOID *Context, + IN UINT32 VTdIndex, + IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd + ); + /** - Enable VTd translation table protection. + Enable VTd translation table protection for block DMA - @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. + @param[in] VtdUnitBaseAddress The base address of the VTd engine. + + @retval EFI_SUCCESS DMAR translation is enabled. + @retval EFI_DEVICE_ERROR DMAR translation is not enabled. **/ -VOID -EnableVTdTranslationProtectionAll ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask +EFI_STATUS +EnableVTdTranslationProtectionBlockDma ( + IN UINT32 VtdUnitBaseAddress ); /** @@ -90,34 +93,39 @@ EnableVTdTranslationProtection ( Disable VTd translation table protection. @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. **/ VOID DisableVTdTranslationProtection ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask + IN VTD_INFO *VTdInfo ); /** Parse DMAR DRHD table. @param[in] AcpiDmarTable DMAR ACPI table + @param[in] Callback Callback function for handle DRHD + @param[in] Context Callback function Context + + @return EFI_SUCCESS The DMAR DRHD table is parsed. - @return EFI_SUCCESS The DMAR DRHD table is parsed. **/ EFI_STATUS ParseDmarAcpiTableDrhd ( - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable, + IN PROCESS_DRHD_CALLBACK_FUNC Callback, + IN VOID *Context ); /** - Parse DMAR DRHD table. + Get RMRR Info from ACPI DMAR Table. - @param[in] VTdInfo The VTd engine context information. + @param[in] AcpiDmarTable DMAR ACPI table + + @return the VTd engine number. **/ -VOID -ParseDmarAcpiTableRmrr ( - IN VTD_INFO *VTdInfo +VTD_RMRR_INFO * +GetVtdRmrrInfo ( + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable ); /** @@ -167,6 +175,30 @@ SetupTranslationTable ( IN VTD_INFO *VTdInfo ); +/** + Get VTd engine number. + + @param[in] AcpiDmarTable DMAR ACPI table + + @return the VTd engine number. +**/ +UINTN +GetVtdEngineNumber ( + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable + ); + +/** + Setup VTd RMRR in translation table. + + @param[in] VTdInfo The VTd engine context information. + + @return the VTd engine number. +**/ +EFI_STATUS +SetupRmrr ( + IN VTD_INFO *VTdInfo + ); + /** Flush VTD page table and context table memory. @@ -240,4 +272,3 @@ extern EFI_GUID mVTdInfoGuid; extern EFI_GUID mDmaBufferInfoGuid; #endif - diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c index a309d566..405ea630 100644 --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c @@ -1,6 +1,7 @@ /** @file Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -276,6 +277,10 @@ CreateContextEntry ( VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry; UINT64 Pt; + if (VTdUnitInfo->RootEntryTable != 0) { + return EFI_SUCCESS; + } + RootPages = EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTRY_NUMBER); ContextPages = EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CONTEXT_ENTRY_NUMBER); EntryTablePages = RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER); @@ -359,6 +364,10 @@ CreateExtContextEntry ( VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry; UINT64 Pt; + if (VTdUnitInfo->ExtRootEntryTable != 0) { + return EFI_SUCCESS; + } + RootPages = EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_ENTRY_NUMBER); ContextPages = EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD_CONTEXT_ENTRY_NUMBER); EntryTablePages = RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER); @@ -837,6 +846,10 @@ CreateFixedSecondLevelPagingEntry ( VOID *Hob; DMA_BUFFER_INFO *DmaBufferInfo; + if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) { + return EFI_SUCCESS; + } + VTdUnitInfo->FixedSecondLevelPagingEntry = (UINT32) (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0); if (VTdUnitInfo->FixedSecondLevelPagingEntry == 0) { DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n")); @@ -846,7 +859,7 @@ CreateFixedSecondLevelPagingEntry ( Hob = GetFirstGuidHob (&mDmaBufferInfoGuid); DmaBufferInfo = GET_GUID_HOB_DATA (Hob); BaseAddress = DmaBufferInfo->DmaBufferBase; - Length = DmaBufferInfo->DmaBufferLimit - DmaBufferInfo->DmaBufferBase; + Length = DmaBufferInfo->DmaBufferSize; IoMmuAccess = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; DEBUG ((DEBUG_INFO, " BaseAddress = 0x%lx\n", BaseAddress)); @@ -877,6 +890,9 @@ SetupTranslationTable ( for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + continue; + } Status = CreateFixedSecondLevelPagingEntry (VtdUnitInfo); if (EFI_ERROR (Status)) { @@ -912,83 +928,45 @@ SetupTranslationTable ( } /** - Find the VTd index by the Segment and SourceId. + Setup VTd RMRR in translation table. @param[in] VTdInfo The VTd engine context information. - @param[in] Segment The segment of the source. - @param[in] SourceId The SourceId of the source. - @param[out] ExtContextEntry The ExtContextEntry of the source. - @param[out] ContextEntry The ContextEntry of the source. - @return The index of the VTd engine. - @retval (UINTN)-1 The VTd engine is not found. + @return the VTd engine number. **/ -UINTN -FindVtdIndexBySegmentSourceId ( - IN VTD_INFO *VTdInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId, - OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry, - OUT VTD_CONTEXT_ENTRY **ContextEntry +EFI_STATUS +SetupRmrr ( + IN VTD_INFO *VTdInfo ) { - UINTN VtdIndex; - VTD_ROOT_ENTRY *RootEntryBase; - VTD_ROOT_ENTRY *RootEntry; - VTD_CONTEXT_ENTRY *ContextEntryTable; - VTD_CONTEXT_ENTRY *ThisContextEntry; - VTD_EXT_ROOT_ENTRY *ExtRootEntryBase; - VTD_EXT_ROOT_ENTRY *ExtRootEntry; - VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable; - VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry; + EFI_STATUS Status; + UINTN Index; - for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) { - if (GetPciDataIndex (&VTdInfo->VtdUnitInfo[VtdIndex], Segment, SourceId) != (UINTN)-1) { - DEBUG ((DEBUG_INFO, "Find VtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - break; - } + if (VTdInfo->VtdRmrrInfo == NULL) { + return EFI_SUCCESS; } - if (VtdIndex >= VTdInfo->VTdEngineCount) { - for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) { - if (Segment != VTdInfo->VtdUnitInfo[VtdIndex].Segment) { - continue; - } - if (VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.IncludeAllFlag) { - DEBUG ((DEBUG_INFO, "Find IncludeAllFlag VtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - break; - } - } + + if (VTdInfo->VtdRmrrInfo->DeviceNumber == 0) { + return EFI_SUCCESS; } - if (VtdIndex < VTdInfo->VTdEngineCount) { - ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable; - if (ExtRootEntryBase != 0) { - ExtRootEntry = &ExtRootEntryBase[SourceId.Index.RootIndex]; - ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ; - ThisExtContextEntry = &ExtContextEntryTable[SourceId.Index.ContextIndex]; - if (ThisExtContextEntry->Bits.AddressWidth == 0) { - DEBUG ((DEBUG_INFO, "ExtContextEntry AddressWidth : 0x%x\n", ThisExtContextEntry->Bits.AddressWidth)); - return (UINTN)-1; - } - *ExtContextEntry = ThisExtContextEntry; - *ContextEntry = NULL; - } else { - RootEntryBase = (VTD_ROOT_ENTRY*) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable; - RootEntry = &RootEntryBase[SourceId.Index.RootIndex]; - ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ; - ThisContextEntry = &ContextEntryTable[SourceId.Index.ContextIndex]; - if (ThisContextEntry->Bits.AddressWidth == 0) { - DEBUG ((DEBUG_INFO, "ContextEntry AddressWidth : 0x%x\n", ThisContextEntry->Bits.AddressWidth)); - return (UINTN)-1; - } - *ExtContextEntry = NULL; - *ContextEntry = ThisContextEntry; + DEBUG ((DEBUG_INFO, "Setup Rmrr Info\n")); + + for (Index = 0; Index < VTdInfo->VtdRmrrInfo->DeviceNumber; Index++) { + Status = EnableRmrrPageAttribute ( + VTdInfo, + VTdInfo->VtdRmrrInfo->SegmentNumber, + VTdInfo->VtdRmrrInfo->SourceId[Index], + VTdInfo->VtdRmrrInfo->ReservedMemoryRegionBaseAddress, + VTdInfo->VtdRmrrInfo->ReservedMemoryRegionLimitAddress, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EnableRmrrPageAttribute : %r\n", Status)); } - - return VtdIndex; } - return (UINTN)-1; + return EFI_SUCCESS; } /** @@ -1013,8 +991,9 @@ EnableRmrrPageAttribute ( IN UINT64 IoMmuAccess ) { - EFI_STATUS Status; - UINTN VtdIndex; + UINTN Index; + VTD_UNIT_INFO *VtdUnitInfo; + EFI_STATUS Status; VTD_EXT_CONTEXT_ENTRY *ExtContextEntry; VTD_CONTEXT_ENTRY *ContextEntry; VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry; @@ -1022,39 +1001,41 @@ EnableRmrrPageAttribute ( DEBUG ((DEBUG_INFO, "EnableRmrrPageAttribute (S%04x B%02x D%02x F%02x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - VtdIndex = FindVtdIndexBySegmentSourceId (VTdInfo, Segment, SourceId, &ExtContextEntry, &ContextEntry); - if (VtdIndex == (UINTN)-1) { - DEBUG ((DEBUG_ERROR, "EnableRmrrPageAttribute - Can not locate Pci device (S%04x B%02x D%02x F%02x) !\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - return EFI_DEVICE_ERROR; - } - - if (VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry == 0) { - DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex)); - VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry = (UINT32)(UINTN)CreateSecondLevelPagingEntryTable (&VTdInfo->VtdUnitInfo[VtdIndex], NULL, 0, SIZE_4GB, 0); - if (VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry == 0) { - return EFI_OUT_OF_RESOURCES; + for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { + VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + continue; } - Status =SetSecondLevelPagingAttribute (&VTdInfo->VtdUnitInfo[VtdIndex], (VTD_SECOND_LEVEL_PAGING_ENTRY*)(UINTN)VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry, MemoryBase, MemoryLimit + 1 - MemoryBase, IoMmuAccess); - if (EFI_ERROR (Status)) { - return Status; - } - } + if (VtdUnitInfo->RmrrSecondLevelPagingEntry == 0) { + DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", Index)); + VtdUnitInfo->RmrrSecondLevelPagingEntry = (UINT32)(UINTN)CreateSecondLevelPagingEntryTable (VtdUnitInfo, NULL, 0, SIZE_4GB, 0); + if (VtdUnitInfo->RmrrSecondLevelPagingEntry == 0) { + return EFI_OUT_OF_RESOURCES; + } - SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry; - Pt = (UINT64) RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12); - if (ExtContextEntry != NULL) { - ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; - ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20); - ExtContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1); - ExtContextEntry->Bits.Present = 1; - FlushPageTableMemory (&VTdInfo->VtdUnitInfo[VtdIndex], (UINTN) ExtContextEntry, sizeof(*ExtContextEntry)); - } else if (ContextEntry != NULL) { - ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; - ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64 (Pt, 20); - ContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1); - ContextEntry->Bits.Present = 1; - FlushPageTableMemory (&VTdInfo->VtdUnitInfo[VtdIndex], (UINTN) ContextEntry, sizeof (*ContextEntry)); + Status = SetSecondLevelPagingAttribute (VtdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*)(UINTN)VtdUnitInfo->RmrrSecondLevelPagingEntry, MemoryBase, MemoryLimit + 1 - MemoryBase, IoMmuAccess); + if (EFI_ERROR (Status)) { + return Status; + } + } + SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VtdUnitInfo->RmrrSecondLevelPagingEntry; + ExtContextEntry = (VTD_EXT_CONTEXT_ENTRY *) VtdUnitInfo->ExtRootEntryTable; + ContextEntry = (VTD_CONTEXT_ENTRY *) VtdUnitInfo->RootEntryTable; + Pt = (UINT64) RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12); + if (ExtContextEntry != NULL) { + ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; + ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20); + ExtContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VtdUnitInfo->CapReg.Bits.ND * 2 + 4)) - 1); + ExtContextEntry->Bits.Present = 1; + FlushPageTableMemory (VtdUnitInfo, (UINTN) ExtContextEntry, sizeof(*ExtContextEntry)); + } else if (ContextEntry != NULL) { + ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; + ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64 (Pt, 20); + ContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VtdUnitInfo->CapReg.Bits.ND * 2 + 4)) - 1); + ContextEntry->Bits.Present = 1; + FlushPageTableMemory (VtdUnitInfo, (UINTN) ContextEntry, sizeof (*ContextEntry)); + } } return EFI_SUCCESS; -- 2.16.2.windows.1