* [PATCH 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.
2021-12-07 1:55 [PATCH 0/4] There are 4 patches for VTd drivers Sheng Wei
` (2 preceding siblings ...)
2021-12-07 1:55 ` [PATCH 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode Sheng Wei
@ 2021-12-07 1:55 ` Sheng Wei
3 siblings, 0 replies; 5+ messages in thread
From: Sheng Wei @ 2021-12-07 1:55 UTC (permalink / raw)
To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski
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 <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
Cc: Robert Kowalewski <robert.kowalewski@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
.../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.<BR>
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+
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.<BR>
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
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.<BR>
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
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.<BR>
+
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
^ permalink raw reply related [flat|nested] 5+ messages in thread