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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
.../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 545 +--------------------
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 433 +++++++---------
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 474 ++++++++++--------
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 119 ++---
.../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 196 ++------
5 files changed, 533 insertions(+), 1234 deletions(-)
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index e9c99d0a..acfbc4a8 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
**/
@@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry (
return;
}
-/**
- Dump DMAR RMRR table.
-
- @param[in] Rmrr DMAR RMRR table
-**/
-VOID
-DumpDmarRmrr (
- IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
- INTN RmrrLen;
-
- if (Rmrr == NULL) {
- return;
- }
-
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- " * Reserved Memory Region Reporting Structure *\n"
- ));
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- (sizeof (UINTN) == sizeof (UINT64)) ?
- " RMRR address ........................................... 0x%016lx\n" :
- " RMRR address ........................................... 0x%08x\n",
- Rmrr
- ));
- DEBUG ((DEBUG_INFO,
- " Type ................................................. 0x%04x\n",
- Rmrr->Header.Type
- ));
- DEBUG ((DEBUG_INFO,
- " Length ............................................... 0x%04x\n",
- Rmrr->Header.Length
- ));
- DEBUG ((DEBUG_INFO,
- " Segment Number ....................................... 0x%04x\n",
- Rmrr->SegmentNumber
- ));
- DEBUG ((DEBUG_INFO,
- " Reserved Memory Region Base Address .................. 0x%016lx\n",
- Rmrr->ReservedMemoryRegionBaseAddress
- ));
- DEBUG ((DEBUG_INFO,
- " Reserved Memory Region Limit Address ................. 0x%016lx\n",
- Rmrr->ReservedMemoryRegionLimitAddress
- ));
-
- RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1);
- while (RmrrLen > 0) {
- DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
- RmrrLen -= DmarDeviceScopeEntry->Length;
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
- }
-
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n\n"
- ));
-
- return;
-}
-
/**
Dump DMAR DRHD table.
@@ -312,9 +245,6 @@ DumpAcpiDMAR (
case EFI_ACPI_DMAR_TYPE_DRHD:
DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
break;
- case EFI_ACPI_DMAR_TYPE_RMRR:
- DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
- break;
default:
break;
}
@@ -329,492 +259,43 @@ DumpAcpiDMAR (
return;
}
-/**
- Get VTd engine number.
-
- @param[in] AcpiDmarTable DMAR ACPI table
-
- @return the VTd engine number.
-**/
-UINTN
-GetVtdEngineNumber (
- IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdIndex;
-
- 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:
- VtdIndex++;
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
- }
- return VtdIndex ;
-}
-
-/**
- Get PCI device information from DMAR DevScopeEntry.
-
- @param[in] Segment The segment number.
- @param[in] DmarDevScopeEntry DMAR DevScopeEntry
- @param[out] Bus The bus number.
- @param[out] Device The device number.
- @param[out] Function The function number.
-
- @retval EFI_SUCCESS The PCI device information is returned.
-**/
-EFI_STATUS
-GetPciBusDeviceFunction (
- IN UINT16 Segment,
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,
- OUT UINT8 *Bus,
- OUT UINT8 *Device,
- OUT UINT8 *Function
- )
-{
- EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;
- UINT8 MyBus;
- UINT8 MyDevice;
- UINT8 MyFunction;
-
- DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN) (DmarDevScopeEntry + 1));
- MyBus = DmarDevScopeEntry->StartBusNumber;
- MyDevice = DmarPciPath->Device;
- MyFunction = DmarPciPath->Function;
-
- switch (DmarDevScopeEntry->Type) {
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
- while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) < (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) {
- MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
- DmarPciPath ++;
- MyDevice = DmarPciPath->Device;
- MyFunction = DmarPciPath->Function;
- }
- break;
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
- break;
- }
-
- *Bus = MyBus;
- *Device = MyDevice;
- *Function = MyFunction;
-
- return EFI_SUCCESS;
-}
-
-/**
- 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.
-
- @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.
-
- @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.
-
-**/
-EFI_STATUS
-RegisterPciDevice (
- IN VTD_UNIT_INFO *VTdUnitInfo,
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT8 DeviceType,
- IN BOOLEAN CheckExist
- )
-{
- 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"));
-
- 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;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Process DMAR DRHD table.
-
- @param[in] VTdUnitInfo The VTd engine unit information.
- @param[in] DmarDrhd The DRHD table.
-
-**/
-VOID
-ProcessDrhd (
- IN VTD_UNIT_INFO *VTdUnitInfo,
- IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
- UINT8 Bus;
- 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"));
- }
-
- VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
- VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
- VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
- VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
-
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1));
- while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) {
-
- Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- 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;
- }
- 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);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
- }
-
- 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
- ));
-
- PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
-
- 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
- ));
- }
-}
-
/**
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.
**/
EFI_STATUS
ParseDmarAcpiTableDrhd (
- IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,
+ IN VOID *Context
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdUnitNumber;
- UINTN VtdIndex;
- VTD_INFO *VTdInfo;
-
- VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
- if (VtdUnitNumber == 0) {
- return EFI_UNSUPPORTED;
- }
-
- 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;
+ UINT32 VtdIndex;
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);
+ if (Callback != NULL) {
+ Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+ }
VtdIndex++;
-
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;
-}
-
-
-/**
- Process DMAR RMRR table.
-
- @param[in] VTdInfo The VTd engine context information.
- @param[in] DmarRmrr The RMRR table.
-
-**/
-VOID
-ProcessRmrr (
- IN VTD_INFO *VTdInfo,
- IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
- UINT8 Bus;
- UINT8 Device;
- UINT8 Function;
- EFI_STATUS Status;
- VTD_SOURCE_ID SourceId;
-
- DEBUG ((DEBUG_INFO," PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
-
- if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
- (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
- return ;
- }
-
- 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;
- }
-
- Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- 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));
- }
-
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
- }
-}
-
-/**
- Parse DMAR DRHD table.
-
- @param[in] VTdInfo The VTd engine context information.
-
-**/
-VOID
-ParseDmarAcpiTableRmrr (
- IN VTD_INFO *VTdInfo
- )
-{
- 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);
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
- }
+ return VtdIndex;
}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 63397a1a..0ed216bb 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,77 +79,73 @@ PerpareCacheInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT16 QueueSize;
+ UINT16 QiDescLength;
UINT64 Reg64;
UINT32 Reg32;
VTD_ECAP_REG ECapReg;
+ UINTN VtdUnitBaseAddress;
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
- if (VTdUnitInfo->VerReg.Bits.Major <= 6) {
+ if (VTdUnitInfo->VerReg.Bits.Major <= 5) {
VTdUnitInfo->EnableQueuedInvalidation = 0;
- DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress));
return EFI_SUCCESS;
}
- ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
if (ECapReg.Bits.QI == 0) {
- DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VtdUnitBaseAddress));
return EFI_UNSUPPORTED;
}
VTdUnitInfo->EnableQueuedInvalidation = 1;
- DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress));
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
if ((Reg32 & B_GSTS_REG_QIES) != 0) {
DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));
Reg32 &= (~B_GSTS_REG_QIES);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (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;
- }
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0);
}
//
// Initialize the Invalidation Queue Tail Register to zero.
//
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, 0);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);
//
// 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));
- Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc;
- Reg64 |= QueueSize;
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", QiDescLength));
+ Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
+ Reg64 |= VTdUnitInfo->QueueSize;
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64);
//
// Enable the queued invalidation interface through the Global Command Register.
// When enabled, hardware sets the QIES field in the Global Status Register.
//
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
Reg32 |= B_GMCD_REG_QIE;
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) == 0);
VTdUnitInfo->QiFreeHead = 0;
@@ -167,21 +163,23 @@ DisableQueuedInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT32 Reg32;
+ UINT32 Reg32;
+ UINT16 QiDescLength;
if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
Reg32 &= (~B_GMCD_REG_QIE);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
} 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;
@@ -203,26 +201,11 @@ 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;
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
+ FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG);
+ if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
+ DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg));
+ FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);
+ MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
return RETURN_DEVICE_ERROR;
}
@@ -256,7 +239,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));
@@ -268,12 +251,12 @@ SubmitQueuedInvalidationDescriptor (
DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead));
VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength;
- Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
+ Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
//
// Update the HW tail register indicating the presence of new descriptors.
//
Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+ MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
Status = EFI_SUCCESS;
do {
@@ -283,7 +266,7 @@ SubmitQueuedInvalidationDescriptor (
break;
}
- Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
+ Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
} while (Reg64Iqt != Reg64Iqh);
DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
@@ -307,18 +290,18 @@ InvalidateContextCache (
//
// Register-based Invalidation
//
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
if ((Reg64 & B_CCMD_REG_ICC) != 0) {
- DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress));
return EFI_DEVICE_ERROR;
}
Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);
+ MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);
do {
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
} while ((Reg64 & B_CCMD_REG_ICC) != 0);
} else {
//
@@ -351,26 +334,26 @@ InvalidateIOTLB (
//
// Register-based Invalidation
//
- ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
- DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress));
return EFI_DEVICE_ERROR;
}
Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
+ MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
do {
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
} while ((Reg64 & B_IOTLB_REG_IVT) != 0);
} else {
//
// Queued Invalidation
//
- ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(ECapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
@@ -392,14 +375,14 @@ InvalidateIOTLB (
EFI_STATUS
EnableDmarPreMem (
IN UINTN VtdUnitBaseAddress,
- IN UINTN RtaddrRegValue
+ 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);
@@ -452,30 +435,33 @@ EnableDmar (
)
{
UINT32 Reg32;
+ UINTN VtdUnitBaseAddress;
- DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VTdUnitInfo->VtdUnitBaseAddress));
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));
//
// Init DMAr Fault Event and Data registers
//
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FEDATA_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
//
// Write Buffer Flush before invalidation
//
- FlushWriteBuffer ((UINTN)VTdUnitInfo->VtdUnitBaseAddress);
+ FlushWriteBuffer (VtdUnitBaseAddress);
//
// Invalidate the context cache
@@ -490,11 +476,11 @@ EnableDmar (
//
// Enable VTd
//
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_TE) == 0);
DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
@@ -566,139 +552,52 @@ DisableDmar (
}
/**
- Dump VTd version registers.
+ Enable VTd translation table protection for block DMA
- @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));
-}
-
-/**
- Dump VTd capability registers.
-
- @param[in] CapReg The capability register.
-**/
-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));
-}
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.
-/**
- Dump VTd extended capability registers.
-
- @param[in] ECapReg The extended capability register.
+ @retval EFI_SUCCESS DMAR translation is enabled.
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
**/
-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 UINTN 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 +614,25 @@ EnableVTdTranslationProtection (
)
{
EFI_STATUS Status;
- UINTN VtdIndex;
+ UINTN Index;
+ VTD_UNIT_INFO *VtdUnitInfo;
- 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);
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+ if (VtdUnitInfo->Done) {
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index));
+ continue;
+ }
+
+ 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,23 +643,22 @@ 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);
+ DisableDmar (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress);
DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]);
}
@@ -786,6 +691,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 +733,37 @@ PrepareVtdConfig (
IN VTD_INFO *VTdInfo
)
{
+ EFI_STATUS Status;
UINTN Index;
- UINTN DomainNumber;
+ VTD_UNIT_INFO *VtdUnitInfo;
+ UINTN VtdUnitBaseAddress;
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;
+ VtdUnitBaseAddress = VtdUnitInfo->VtdUnitBaseAddress;
+ DEBUG((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress));
+
+ VtdUnitInfo->VerReg.Uint32 = MmioRead32 (VtdUnitBaseAddress + R_VER_REG);
+ VtdUnitInfo->CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+ VtdUnitInfo->ECapReg.Uint64 = MmioRead64 (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..ac91eac3 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
@@ -140,7 +140,7 @@ PeiIoMmuMap (
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
- *DeviceAddress = (UINTN)HostAddress;
+ *DeviceAddress = (UINTN) HostAddress;
*Mapping = NULL;
return EFI_SUCCESS;
}
@@ -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,114 @@ 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;
- 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;
+ 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.
+
+ @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 ((UINTN) DmarDrhd->RegisterBaseAddress);
}
/**
- Initializes the Intel VTd Info.
+ 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 = (UINTN) 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 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 +481,103 @@ InitVTdInfo (
VOID
)
{
- EFI_STATUS Status;
- EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
- VOID *Hob;
VTD_INFO *VTdInfo;
- UINT64 EngineMask;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ UINTN VtdUnitNumber;
+ VTD_UNIT_INFO *VtdUnitInfo;
+ EFI_STATUS Status;
+ UINTN NewUnitIndex;
+ UINTN PreviousUnitIndex;
- Status = PeiServicesLocatePpi (
- &gEdkiiVTdInfoPpiGuid,
- 0,
- NULL,
- (VOID **)&AcpiDmarTable
- );
- ASSERT_EFI_ERROR (Status);
+ VTdInfo = GetVTdInfoHob ();
+ ASSERT (VTdInfo != NULL);
- DumpAcpiDMAR (AcpiDmarTable);
+ AcpiDmarTable = GetAcpiDmarTable ();
+ ASSERT (AcpiDmarTable != NULL);
//
- // Clear old VTdInfo Hob.
+ // Get VTd Unit Number
//
- Hob = GetFirstGuidHob (&mVTdInfoGuid);
- if (Hob != NULL) {
- DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
-
- VTdInfo = GET_GUID_HOB_DATA(Hob);
- EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
- EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
-
- ReleaseVTdInfo (VTdInfo);
- VTdInfo->VTdEngineCount = 0;
+ VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, NULL, NULL);
+ if (VtdUnitNumber == 0) {
+ return EFI_UNSUPPORTED;
+ }
- ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
+ //
+ // Genrate a new Vtd Unit Info Table
+ //
+ 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
+ // Parse the DMAR ACPI Table to the new Vtd Unit Info Table
//
- 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) {
+ //
+ // New Vtd Unit Info Table Loop
+ //
+ for (NewUnitIndex = 0; NewUnitIndex < VtdUnitNumber; NewUnitIndex++) {
+ //
+ // Previous Vtd Unit Info Table Loop
+ //
+ for (PreviousUnitIndex = 0; PreviousUnitIndex < VTdInfo->VTdEngineCount; PreviousUnitIndex++) {
+ //
+ // Compare the new Vtd Unit with the previous VTd Unit
+ //
+ if (VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress == VTdInfo->VtdUnitInfo[PreviousUnitIndex].VtdUnitBaseAddress) {
+ DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n", VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress));
+ CopyMem (&VtdUnitInfo[NewUnitIndex], &VTdInfo->VtdUnitInfo[PreviousUnitIndex], sizeof (VTD_UNIT_INFO));
+ VtdUnitInfo[NewUnitIndex].Done = TRUE;
+
+ break;
+ }
+ }
+ }
+ }
+ VTdInfo->AcpiDmarTable = AcpiDmarTable;
+ VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
+ VTdInfo->VTdEngineCount = VtdUnitNumber;
+ VTdInfo->VtdUnitInfo = VtdUnitInfo;
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;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
- 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;
- }
-
- 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 +600,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 +611,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,33 +621,40 @@ 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 = (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES (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%x\n", DmaBufferInfo->DmaBufferSize));
+ DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\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));
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n", DmaBufferInfo->DmaBufferCurrentBottom));
return EFI_SUCCESS;
}
@@ -588,14 +671,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 +687,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);
@@ -619,10 +695,6 @@ InitVTdDmarForDma (
return Status;
}
- // If there is RMRR memory, parse it here.
- DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
- ParseDmarAcpiTableRmrr (VTdInfo);
-
DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
Status = EnableVTdTranslationProtection(VTdInfo);
if (EFI_ERROR (Status)) {
@@ -668,21 +740,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 +794,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 +814,16 @@ VTdInfoNotify (
//
Status = InitDmaBuffer ();
- ASSERT_EFI_ERROR(Status);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // NOTE: We need reinit VTdInfo because previous information might be overriden.
+ //
+ Status = InitVTdInfo ();
+ ASSERT_EFI_ERROR (Status);
- InitVTdDmarForDma ();
+ Status = InitVTdDmarForDma ();
+ ASSERT_EFI_ERROR (Status);
}
return EFI_SUCCESS;
@@ -826,4 +889,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..351a7810 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -9,68 +9,61 @@
#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;
-
-typedef struct {
- UINT32 VtdUnitBaseAddress;
+ BOOLEAN Done;
+ UINTN VtdUnitBaseAddress;
UINT16 Segment;
+ UINT8 Flags;
VTD_VER_REG VerReg;
VTD_CAP_REG CapReg;
VTD_ECAP_REG ECapReg;
BOOLEAN Is5LevelPaging;
- UINT32 FixedSecondLevelPagingEntry;
- UINT32 RmrrSecondLevelPagingEntry;
- UINT32 RootEntryTable;
- UINT32 ExtRootEntryTable;
- UINT16 RootEntryTablePageSize;
- UINT16 ExtRootEntryTablePageSize;
- PEI_PCI_DEVICE_INFORMATION PciDeviceInfo;
UINT8 EnableQueuedInvalidation;
- UINT16 QiDescLength;
+ UINT16 QueueSize;
QI_DESC *QiDesc;
UINT16 QiFreeHead;
+ UINTN FixedSecondLevelPagingEntry;
+ UINTN RootEntryTable;
+ UINTN ExtRootEntryTable;
+ UINTN RootEntryTablePageSize;
+ UINTN ExtRootEntryTablePageSize;
} VTD_UNIT_INFO;
typedef struct {
- UINT32 AcpiDmarTable;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
UINT8 HostAddressWidth;
- UINT32 VTdEngineCount;
- VTD_UNIT_INFO VtdUnitInfo[1];
+ UINTN VTdEngineCount;
+ VTD_UNIT_INFO *VtdUnitInfo;
} VTD_INFO;
typedef struct {
- UINT64 DmaBufferBase;
- UINT64 DmaBufferSize;
- UINT64 DmaBufferLimit;
- UINT64 DmaBufferCurrentTop;
- UINT64 DmaBufferCurrentBottom;
+ UINTN DmaBufferBase;
+ UINTN DmaBufferSize;
+ UINTN DmaBufferCurrentTop;
+ UINTN DmaBufferCurrentBottom;
} DMA_BUFFER_INFO;
+typedef
+VOID
+(*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 UINTN VtdUnitBaseAddress
);
/**
@@ -90,34 +83,27 @@ 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.
-**/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
- IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
- );
-
-/**
- Parse DMAR DRHD table.
+ @return the VTd engine number.
- @param[in] VTdInfo The VTd engine context information.
**/
-VOID
-ParseDmarAcpiTableRmrr (
- IN VTD_INFO *VTdInfo
+UINTN
+ParseDmarAcpiTableDrhd (
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,
+ IN VOID *Context
);
/**
@@ -214,30 +200,7 @@ GetPciDataIndex (
IN VTD_SOURCE_ID SourceId
);
-/**
- Always enable the VTd page attribute for the device.
-
- @param[in] VTdInfo The VTd engine context 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.
- @param[in] MemoryBase The base of the memory.
- @param[in] MemoryLimit The limit of the memory.
- @param[in] IoMmuAccess The IOMMU access.
-
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
- IN VTD_INFO *VTdInfo,
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT64 MemoryBase,
- IN UINT64 MemoryLimit,
- IN UINT64 IoMmuAccess
- );
-
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..c94f4a85 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
**/
@@ -129,12 +130,12 @@ CreateSecondLevelPagingEntryTable (
FlushPageTableMemory (VTdUnitInfo, (UINTN) SecondLevelPagingEntry, EFI_PAGES_TO_SIZE (1));
}
- DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", SecondLevelPagingEntry));
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry));
//
// If no access is needed, just create not present entry.
//
if (IoMmuAccess == 0) {
- DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN) SecondLevelPagingEntry));
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n", (UINT64) (UINTN) SecondLevelPagingEntry));
return SecondLevelPagingEntry;
}
@@ -244,7 +245,7 @@ CreateSecondLevelPagingEntryTable (
}
FlushPageTableMemory (VTdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start], (UINTN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]);
- DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN)SecondLevelPagingEntry));
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry));
return SecondLevelPagingEntry;
}
@@ -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);
@@ -286,8 +291,8 @@ CreateContextEntry (
}
DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer));
- VTdUnitInfo->RootEntryTable = (UINT32) (UINTN) Buffer;
- VTdUnitInfo->RootEntryTablePageSize = (UINT16) EntryTablePages;
+ VTdUnitInfo->RootEntryTable = (UINTN) Buffer;
+ VTdUnitInfo->RootEntryTablePageSize = EntryTablePages;
RootEntryBase = (VTD_ROOT_ENTRY *) Buffer;
Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
@@ -304,7 +309,7 @@ CreateContextEntry (
RootEntry->Bits.ContextTablePointerHi = (UINT32) RShiftU64 ((UINT64) (UINTN) Buffer, 32);
RootEntry->Bits.Present = 1;
Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
- ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ;
+ ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi);
for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -317,7 +322,7 @@ CreateContextEntry (
ContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2;
if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
- SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
+ SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry;
Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);
@@ -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);
@@ -369,8 +378,8 @@ CreateExtContextEntry (
}
DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer));
- VTdUnitInfo->ExtRootEntryTable = (UINT32) (UINTN) Buffer;
- VTdUnitInfo->ExtRootEntryTablePageSize = (UINT16) EntryTablePages;
+ VTdUnitInfo->ExtRootEntryTable = (UINTN) Buffer;
+ VTdUnitInfo->ExtRootEntryTablePageSize = EntryTablePages;
ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) Buffer;
Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
@@ -390,7 +399,7 @@ CreateExtContextEntry (
ExtRootEntry->Bits.UpperContextTablePointerHi = (UINT32) RShiftU64 (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);
ExtRootEntry->Bits.UpperPresent = 1;
Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);
- ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ;
+ ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi);
for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -403,7 +412,7 @@ CreateExtContextEntry (
ExtContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2;
if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
- SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
+ SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry;
Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
@@ -791,9 +800,6 @@ SetSecondLevelPagingAttribute (
SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute);
if (SplitAttribute == PageNone) {
ConvertSecondLevelPageEntryAttribute (VTdUnitInfo, PageEntry, IoMmuAccess, &IsEntryModified);
- if (IsEntryModified) {
- //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
- }
//
// Convert success, move to next
//
@@ -805,7 +811,6 @@ SetSecondLevelPagingAttribute (
DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));
return RETURN_UNSUPPORTED;
}
- //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
//
// Just split current page
// Convert success in next around
@@ -837,7 +842,11 @@ CreateFixedSecondLevelPagingEntry (
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
- VTdUnitInfo->FixedSecondLevelPagingEntry = (UINT32) (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
+ if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
+ return EFI_SUCCESS;
+ }
+
+ VTdUnitInfo->FixedSecondLevelPagingEntry = (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
if (VTdUnitInfo->FixedSecondLevelPagingEntry == 0) {
DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));
return EFI_OUT_OF_RESOURCES;
@@ -846,14 +855,14 @@ 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));
DEBUG ((DEBUG_INFO, " Length = 0x%lx\n", Length));
DEBUG ((DEBUG_INFO, " IoMmuAccess = 0x%lx\n", IoMmuAccess));
- Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
+ Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
return Status;
}
@@ -877,6 +886,9 @@ SetupTranslationTable (
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+ if (VtdUnitInfo->Done) {
+ continue;
+ }
Status = CreateFixedSecondLevelPagingEntry (VtdUnitInfo);
if (EFI_ERROR (Status)) {
@@ -911,151 +923,3 @@ SetupTranslationTable (
return EFI_SUCCESS;
}
-/**
- Find the VTd index by the Segment and SourceId.
-
- @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.
-**/
-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
- )
-{
- 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;
-
- 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 (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 (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;
- }
-
- return VtdIndex;
- }
-
- return (UINTN)-1;
-}
-
-/**
- Always enable the VTd page attribute for the device.
-
- @param[in] VTdInfo The VTd engine context 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.
- @param[in] MemoryBase The base of the memory.
- @param[in] MemoryLimit The limit of the memory.
- @param[in] IoMmuAccess The IOMMU access.
-
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
- IN VTD_INFO *VTdInfo,
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT64 MemoryBase,
- IN UINT64 MemoryLimit,
- IN UINT64 IoMmuAccess
- )
-{
- EFI_STATUS Status;
- UINTN VtdIndex;
- VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;
- VTD_CONTEXT_ENTRY *ContextEntry;
- VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
- UINT64 Pt;
-
- 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;
- }
-
- 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;
- }
- }
-
- 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));
- }
-
- return EFI_SUCCESS;
-}
--
2.16.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#85777): https://edk2.groups.io/g/devel/message/85777
Mute This Topic: https://groups.io/mt/88505121/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
-----Original Message-----
From: Sheng, W <w.sheng@intel.com>
Sent: Tuesday, January 18, 2022 4:15 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.
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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
.../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 545 +--------------------
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 433 +++++++---------
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 474 ++++++++++--------
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 119 ++---
.../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 196 ++------
5 files changed, 533 insertions(+), 1234 deletions(-)
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index e9c99d0a..acfbc4a8 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
**/
@@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry (
return;
}
-/**
- Dump DMAR RMRR table.
-
- @param[in] Rmrr DMAR RMRR table
-**/
-VOID
-DumpDmarRmrr (
- IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
- INTN RmrrLen;
-
- if (Rmrr == NULL) {
- return;
- }
-
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- " * Reserved Memory Region Reporting Structure *\n"
- ));
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- (sizeof (UINTN) == sizeof (UINT64)) ?
- " RMRR address ........................................... 0x%016lx\n" :
- " RMRR address ........................................... 0x%08x\n",
- Rmrr
- ));
- DEBUG ((DEBUG_INFO,
- " Type ................................................. 0x%04x\n",
- Rmrr->Header.Type
- ));
- DEBUG ((DEBUG_INFO,
- " Length ............................................... 0x%04x\n",
- Rmrr->Header.Length
- ));
- DEBUG ((DEBUG_INFO,
- " Segment Number ....................................... 0x%04x\n",
- Rmrr->SegmentNumber
- ));
- DEBUG ((DEBUG_INFO,
- " Reserved Memory Region Base Address .................. 0x%016lx\n",
- Rmrr->ReservedMemoryRegionBaseAddress
- ));
- DEBUG ((DEBUG_INFO,
- " Reserved Memory Region Limit Address ................. 0x%016lx\n",
- Rmrr->ReservedMemoryRegionLimitAddress
- ));
-
- RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1);
- while (RmrrLen > 0) {
- DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
- RmrrLen -= DmarDeviceScopeEntry->Length;
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
- }
-
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n\n"
- ));
-
- return;
-}
-
/**
Dump DMAR DRHD table.
@@ -312,9 +245,6 @@ DumpAcpiDMAR (
case EFI_ACPI_DMAR_TYPE_DRHD:
DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
break;
- case EFI_ACPI_DMAR_TYPE_RMRR:
- DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
- break;
default:
break;
}
@@ -329,492 +259,43 @@ DumpAcpiDMAR (
return;
}
-/**
- Get VTd engine number.
-
- @param[in] AcpiDmarTable DMAR ACPI table
-
- @return the VTd engine number.
-**/
-UINTN
-GetVtdEngineNumber (
- IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdIndex;
-
- 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:
- VtdIndex++;
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
- }
- return VtdIndex ;
-}
-
-/**
- Get PCI device information from DMAR DevScopeEntry.
-
- @param[in] Segment The segment number.
- @param[in] DmarDevScopeEntry DMAR DevScopeEntry
- @param[out] Bus The bus number.
- @param[out] Device The device number.
- @param[out] Function The function number.
-
- @retval EFI_SUCCESS The PCI device information is returned.
-**/
-EFI_STATUS
-GetPciBusDeviceFunction (
- IN UINT16 Segment,
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,
- OUT UINT8 *Bus,
- OUT UINT8 *Device,
- OUT UINT8 *Function
- )
-{
- EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;
- UINT8 MyBus;
- UINT8 MyDevice;
- UINT8 MyFunction;
-
- DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN) (DmarDevScopeEntry + 1));
- MyBus = DmarDevScopeEntry->StartBusNumber;
- MyDevice = DmarPciPath->Device;
- MyFunction = DmarPciPath->Function;
-
- switch (DmarDevScopeEntry->Type) {
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
- while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) < (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) {
- MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
- DmarPciPath ++;
- MyDevice = DmarPciPath->Device;
- MyFunction = DmarPciPath->Function;
- }
- break;
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
- break;
- }
-
- *Bus = MyBus;
- *Device = MyDevice;
- *Function = MyFunction;
-
- return EFI_SUCCESS;
-}
-
-/**
- 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.
-
- @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.
-
- @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.
-
-**/
-EFI_STATUS
-RegisterPciDevice (
- IN VTD_UNIT_INFO *VTdUnitInfo,
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT8 DeviceType,
- IN BOOLEAN CheckExist
- )
-{
- 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"));
-
- 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;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Process DMAR DRHD table.
-
- @param[in] VTdUnitInfo The VTd engine unit information.
- @param[in] DmarDrhd The DRHD table.
-
-**/
-VOID
-ProcessDrhd (
- IN VTD_UNIT_INFO *VTdUnitInfo,
- IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
- UINT8 Bus;
- 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"));
- }
-
- VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
- VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
- VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
- VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
-
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1));
- while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) {
-
- Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- 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;
- }
- 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);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
- }
-
- 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
- ));
-
- PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
-
- 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
- ));
- }
-}
-
/**
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.
**/
EFI_STATUS
ParseDmarAcpiTableDrhd (
- IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,
+ IN VOID *Context
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdUnitNumber;
- UINTN VtdIndex;
- VTD_INFO *VTdInfo;
-
- VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
- if (VtdUnitNumber == 0) {
- return EFI_UNSUPPORTED;
- }
-
- 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;
+ UINT32 VtdIndex;
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);
+ if (Callback != NULL) {
+ Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+ }
VtdIndex++;
-
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;
-}
-
-
-/**
- Process DMAR RMRR table.
-
- @param[in] VTdInfo The VTd engine context information.
- @param[in] DmarRmrr The RMRR table.
-
-**/
-VOID
-ProcessRmrr (
- IN VTD_INFO *VTdInfo,
- IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
- UINT8 Bus;
- UINT8 Device;
- UINT8 Function;
- EFI_STATUS Status;
- VTD_SOURCE_ID SourceId;
-
- DEBUG ((DEBUG_INFO," PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
-
- if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
- (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
- return ;
- }
-
- 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;
- }
-
- Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- 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));
- }
-
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
- }
-}
-
-/**
- Parse DMAR DRHD table.
-
- @param[in] VTdInfo The VTd engine context information.
-
-**/
-VOID
-ParseDmarAcpiTableRmrr (
- IN VTD_INFO *VTdInfo
- )
-{
- 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);
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
- }
+ return VtdIndex;
}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 63397a1a..0ed216bb 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,77 +79,73 @@ PerpareCacheInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT16 QueueSize;
+ UINT16 QiDescLength;
UINT64 Reg64;
UINT32 Reg32;
VTD_ECAP_REG ECapReg;
+ UINTN VtdUnitBaseAddress;
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
- if (VTdUnitInfo->VerReg.Bits.Major <= 6) {
+ if (VTdUnitInfo->VerReg.Bits.Major <= 5) {
VTdUnitInfo->EnableQueuedInvalidation = 0;
- DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress));
return EFI_SUCCESS;
}
- ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
if (ECapReg.Bits.QI == 0) {
- DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VtdUnitBaseAddress));
return EFI_UNSUPPORTED;
}
VTdUnitInfo->EnableQueuedInvalidation = 1;
- DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress));
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
if ((Reg32 & B_GSTS_REG_QIES) != 0) {
DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));
Reg32 &= (~B_GSTS_REG_QIES);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (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;
- }
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0);
}
//
// Initialize the Invalidation Queue Tail Register to zero.
//
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, 0);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);
//
// 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));
- Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc;
- Reg64 |= QueueSize;
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", QiDescLength));
+ Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
+ Reg64 |= VTdUnitInfo->QueueSize;
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64);
//
// Enable the queued invalidation interface through the Global Command Register.
// When enabled, hardware sets the QIES field in the Global Status Register.
//
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
Reg32 |= B_GMCD_REG_QIE;
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) == 0);
VTdUnitInfo->QiFreeHead = 0;
@@ -167,21 +163,23 @@ DisableQueuedInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT32 Reg32;
+ UINT32 Reg32;
+ UINT16 QiDescLength;
if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
Reg32 &= (~B_GMCD_REG_QIE);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
} 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;
@@ -203,26 +201,11 @@ 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;
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
+ FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG);
+ if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
+ DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg));
+ FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);
+ MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
return RETURN_DEVICE_ERROR;
}
@@ -256,7 +239,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));
@@ -268,12 +251,12 @@ SubmitQueuedInvalidationDescriptor (
DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead));
VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength;
- Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
+ Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
//
// Update the HW tail register indicating the presence of new descriptors.
//
Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+ MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
Status = EFI_SUCCESS;
do {
@@ -283,7 +266,7 @@ SubmitQueuedInvalidationDescriptor (
break;
}
- Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
+ Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
} while (Reg64Iqt != Reg64Iqh);
DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
@@ -307,18 +290,18 @@ InvalidateContextCache (
//
// Register-based Invalidation
//
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
if ((Reg64 & B_CCMD_REG_ICC) != 0) {
- DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress));
return EFI_DEVICE_ERROR;
}
Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);
+ MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);
do {
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
} while ((Reg64 & B_CCMD_REG_ICC) != 0);
} else {
//
@@ -351,26 +334,26 @@ InvalidateIOTLB (
//
// Register-based Invalidation
//
- ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
- DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+ DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress));
return EFI_DEVICE_ERROR;
}
Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
+ MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
do {
- Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
} while ((Reg64 & B_IOTLB_REG_IVT) != 0);
} else {
//
// Queued Invalidation
//
- ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(ECapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
@@ -392,14 +375,14 @@ InvalidateIOTLB (
EFI_STATUS
EnableDmarPreMem (
IN UINTN VtdUnitBaseAddress,
- IN UINTN RtaddrRegValue
+ 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);
@@ -452,30 +435,33 @@ EnableDmar (
)
{
UINT32 Reg32;
+ UINTN VtdUnitBaseAddress;
- DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VTdUnitInfo->VtdUnitBaseAddress));
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));
//
// Init DMAr Fault Event and Data registers
//
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FEDATA_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
//
// Write Buffer Flush before invalidation
//
- FlushWriteBuffer ((UINTN)VTdUnitInfo->VtdUnitBaseAddress);
+ FlushWriteBuffer (VtdUnitBaseAddress);
//
// Invalidate the context cache
@@ -490,11 +476,11 @@ EnableDmar (
//
// Enable VTd
//
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
- MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
do {
- Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_TE) == 0);
DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
@@ -566,139 +552,52 @@ DisableDmar (
}
/**
- Dump VTd version registers.
+ Enable VTd translation table protection for block DMA
- @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));
-}
-
-/**
- Dump VTd capability registers.
-
- @param[in] CapReg The capability register.
-**/
-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));
-}
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.
-/**
- Dump VTd extended capability registers.
-
- @param[in] ECapReg The extended capability register.
+ @retval EFI_SUCCESS DMAR translation is enabled.
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
**/
-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 UINTN 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 +614,25 @@ EnableVTdTranslationProtection (
)
{
EFI_STATUS Status;
- UINTN VtdIndex;
+ UINTN Index;
+ VTD_UNIT_INFO *VtdUnitInfo;
- 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);
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+ if (VtdUnitInfo->Done) {
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index));
+ continue;
+ }
+
+ 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,23 +643,22 @@ 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);
+ DisableDmar (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress);
DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]);
}
@@ -786,6 +691,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 +733,37 @@ PrepareVtdConfig (
IN VTD_INFO *VTdInfo
)
{
+ EFI_STATUS Status;
UINTN Index;
- UINTN DomainNumber;
+ VTD_UNIT_INFO *VtdUnitInfo;
+ UINTN VtdUnitBaseAddress;
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;
+ VtdUnitBaseAddress = VtdUnitInfo->VtdUnitBaseAddress;
+ DEBUG((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress));
+
+ VtdUnitInfo->VerReg.Uint32 = MmioRead32 (VtdUnitBaseAddress + R_VER_REG);
+ VtdUnitInfo->CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+ VtdUnitInfo->ECapReg.Uint64 = MmioRead64 (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..ac91eac3 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
@@ -140,7 +140,7 @@ PeiIoMmuMap (
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
- *DeviceAddress = (UINTN)HostAddress;
+ *DeviceAddress = (UINTN) HostAddress;
*Mapping = NULL;
return EFI_SUCCESS;
}
@@ -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,114 @@ 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;
- 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;
+ 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.
+
+ @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 ((UINTN) DmarDrhd->RegisterBaseAddress);
}
/**
- Initializes the Intel VTd Info.
+ 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 = (UINTN) 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 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 +481,103 @@ InitVTdInfo (
VOID
)
{
- EFI_STATUS Status;
- EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
- VOID *Hob;
VTD_INFO *VTdInfo;
- UINT64 EngineMask;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ UINTN VtdUnitNumber;
+ VTD_UNIT_INFO *VtdUnitInfo;
+ EFI_STATUS Status;
+ UINTN NewUnitIndex;
+ UINTN PreviousUnitIndex;
- Status = PeiServicesLocatePpi (
- &gEdkiiVTdInfoPpiGuid,
- 0,
- NULL,
- (VOID **)&AcpiDmarTable
- );
- ASSERT_EFI_ERROR (Status);
+ VTdInfo = GetVTdInfoHob ();
+ ASSERT (VTdInfo != NULL);
- DumpAcpiDMAR (AcpiDmarTable);
+ AcpiDmarTable = GetAcpiDmarTable ();
+ ASSERT (AcpiDmarTable != NULL);
//
- // Clear old VTdInfo Hob.
+ // Get VTd Unit Number
//
- Hob = GetFirstGuidHob (&mVTdInfoGuid);
- if (Hob != NULL) {
- DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
-
- VTdInfo = GET_GUID_HOB_DATA(Hob);
- EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
- EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
-
- ReleaseVTdInfo (VTdInfo);
- VTdInfo->VTdEngineCount = 0;
+ VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, NULL, NULL);
+ if (VtdUnitNumber == 0) {
+ return EFI_UNSUPPORTED;
+ }
- ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
+ //
+ // Genrate a new Vtd Unit Info Table
+ //
+ 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
+ // Parse the DMAR ACPI Table to the new Vtd Unit Info Table
//
- 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) {
+ //
+ // New Vtd Unit Info Table Loop
+ //
+ for (NewUnitIndex = 0; NewUnitIndex < VtdUnitNumber; NewUnitIndex++) {
+ //
+ // Previous Vtd Unit Info Table Loop
+ //
+ for (PreviousUnitIndex = 0; PreviousUnitIndex < VTdInfo->VTdEngineCount; PreviousUnitIndex++) {
+ //
+ // Compare the new Vtd Unit with the previous VTd Unit
+ //
+ if (VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress == VTdInfo->VtdUnitInfo[PreviousUnitIndex].VtdUnitBaseAddress) {
+ DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n", VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress));
+ CopyMem (&VtdUnitInfo[NewUnitIndex], &VTdInfo->VtdUnitInfo[PreviousUnitIndex], sizeof (VTD_UNIT_INFO));
+ VtdUnitInfo[NewUnitIndex].Done = TRUE;
+
+ break;
+ }
+ }
+ }
+ }
+ VTdInfo->AcpiDmarTable = AcpiDmarTable;
+ VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
+ VTdInfo->VTdEngineCount = VtdUnitNumber;
+ VTdInfo->VtdUnitInfo = VtdUnitInfo;
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;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
- 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;
- }
-
- 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 +600,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 +611,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,33 +621,40 @@ 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 = (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES (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%x\n", DmaBufferInfo->DmaBufferSize));
+ DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\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));
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n", DmaBufferInfo->DmaBufferCurrentBottom));
return EFI_SUCCESS;
}
@@ -588,14 +671,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 +687,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);
@@ -619,10 +695,6 @@ InitVTdDmarForDma (
return Status;
}
- // If there is RMRR memory, parse it here.
- DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
- ParseDmarAcpiTableRmrr (VTdInfo);
-
DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
Status = EnableVTdTranslationProtection(VTdInfo);
if (EFI_ERROR (Status)) {
@@ -668,21 +740,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 +794,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 +814,16 @@ VTdInfoNotify (
//
Status = InitDmaBuffer ();
- ASSERT_EFI_ERROR(Status);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // NOTE: We need reinit VTdInfo because previous information might be overriden.
+ //
+ Status = InitVTdInfo ();
+ ASSERT_EFI_ERROR (Status);
- InitVTdDmarForDma ();
+ Status = InitVTdDmarForDma ();
+ ASSERT_EFI_ERROR (Status);
}
return EFI_SUCCESS;
@@ -826,4 +889,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..351a7810 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -9,68 +9,61 @@
#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;
-
-typedef struct {
- UINT32 VtdUnitBaseAddress;
+ BOOLEAN Done;
+ UINTN VtdUnitBaseAddress;
UINT16 Segment;
+ UINT8 Flags;
VTD_VER_REG VerReg;
VTD_CAP_REG CapReg;
VTD_ECAP_REG ECapReg;
BOOLEAN Is5LevelPaging;
- UINT32 FixedSecondLevelPagingEntry;
- UINT32 RmrrSecondLevelPagingEntry;
- UINT32 RootEntryTable;
- UINT32 ExtRootEntryTable;
- UINT16 RootEntryTablePageSize;
- UINT16 ExtRootEntryTablePageSize;
- PEI_PCI_DEVICE_INFORMATION PciDeviceInfo;
UINT8 EnableQueuedInvalidation;
- UINT16 QiDescLength;
+ UINT16 QueueSize;
QI_DESC *QiDesc;
UINT16 QiFreeHead;
+ UINTN FixedSecondLevelPagingEntry;
+ UINTN RootEntryTable;
+ UINTN ExtRootEntryTable;
+ UINTN RootEntryTablePageSize;
+ UINTN ExtRootEntryTablePageSize;
} VTD_UNIT_INFO;
typedef struct {
- UINT32 AcpiDmarTable;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
UINT8 HostAddressWidth;
- UINT32 VTdEngineCount;
- VTD_UNIT_INFO VtdUnitInfo[1];
+ UINTN VTdEngineCount;
+ VTD_UNIT_INFO *VtdUnitInfo;
} VTD_INFO;
typedef struct {
- UINT64 DmaBufferBase;
- UINT64 DmaBufferSize;
- UINT64 DmaBufferLimit;
- UINT64 DmaBufferCurrentTop;
- UINT64 DmaBufferCurrentBottom;
+ UINTN DmaBufferBase;
+ UINTN DmaBufferSize;
+ UINTN DmaBufferCurrentTop;
+ UINTN DmaBufferCurrentBottom;
} DMA_BUFFER_INFO;
+typedef
+VOID
+(*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 UINTN VtdUnitBaseAddress
);
/**
@@ -90,34 +83,27 @@ 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.
-**/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
- IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
- );
-
-/**
- Parse DMAR DRHD table.
+ @return the VTd engine number.
- @param[in] VTdInfo The VTd engine context information.
**/
-VOID
-ParseDmarAcpiTableRmrr (
- IN VTD_INFO *VTdInfo
+UINTN
+ParseDmarAcpiTableDrhd (
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,
+ IN VOID *Context
);
/**
@@ -214,30 +200,7 @@ GetPciDataIndex (
IN VTD_SOURCE_ID SourceId
);
-/**
- Always enable the VTd page attribute for the device.
-
- @param[in] VTdInfo The VTd engine context 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.
- @param[in] MemoryBase The base of the memory.
- @param[in] MemoryLimit The limit of the memory.
- @param[in] IoMmuAccess The IOMMU access.
-
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
- IN VTD_INFO *VTdInfo,
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT64 MemoryBase,
- IN UINT64 MemoryLimit,
- IN UINT64 IoMmuAccess
- );
-
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..c94f4a85 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
**/
@@ -129,12 +130,12 @@ CreateSecondLevelPagingEntryTable (
FlushPageTableMemory (VTdUnitInfo, (UINTN) SecondLevelPagingEntry, EFI_PAGES_TO_SIZE (1));
}
- DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", SecondLevelPagingEntry));
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry));
//
// If no access is needed, just create not present entry.
//
if (IoMmuAccess == 0) {
- DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN) SecondLevelPagingEntry));
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n", (UINT64) (UINTN) SecondLevelPagingEntry));
return SecondLevelPagingEntry;
}
@@ -244,7 +245,7 @@ CreateSecondLevelPagingEntryTable (
}
FlushPageTableMemory (VTdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start], (UINTN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]);
- DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN)SecondLevelPagingEntry));
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry));
return SecondLevelPagingEntry;
}
@@ -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);
@@ -286,8 +291,8 @@ CreateContextEntry (
}
DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer));
- VTdUnitInfo->RootEntryTable = (UINT32) (UINTN) Buffer;
- VTdUnitInfo->RootEntryTablePageSize = (UINT16) EntryTablePages;
+ VTdUnitInfo->RootEntryTable = (UINTN) Buffer;
+ VTdUnitInfo->RootEntryTablePageSize = EntryTablePages;
RootEntryBase = (VTD_ROOT_ENTRY *) Buffer;
Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
@@ -304,7 +309,7 @@ CreateContextEntry (
RootEntry->Bits.ContextTablePointerHi = (UINT32) RShiftU64 ((UINT64) (UINTN) Buffer, 32);
RootEntry->Bits.Present = 1;
Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
- ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ;
+ ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi);
for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -317,7 +322,7 @@ CreateContextEntry (
ContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2;
if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
- SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
+ SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry;
Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);
@@ -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);
@@ -369,8 +378,8 @@ CreateExtContextEntry (
}
DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer));
- VTdUnitInfo->ExtRootEntryTable = (UINT32) (UINTN) Buffer;
- VTdUnitInfo->ExtRootEntryTablePageSize = (UINT16) EntryTablePages;
+ VTdUnitInfo->ExtRootEntryTable = (UINTN) Buffer;
+ VTdUnitInfo->ExtRootEntryTablePageSize = EntryTablePages;
ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) Buffer;
Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
@@ -390,7 +399,7 @@ CreateExtContextEntry (
ExtRootEntry->Bits.UpperContextTablePointerHi = (UINT32) RShiftU64 (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);
ExtRootEntry->Bits.UpperPresent = 1;
Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);
- ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ;
+ ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi);
for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -403,7 +412,7 @@ CreateExtContextEntry (
ExtContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2;
if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
- SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
+ SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry;
Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
@@ -791,9 +800,6 @@ SetSecondLevelPagingAttribute (
SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute);
if (SplitAttribute == PageNone) {
ConvertSecondLevelPageEntryAttribute (VTdUnitInfo, PageEntry, IoMmuAccess, &IsEntryModified);
- if (IsEntryModified) {
- //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
- }
//
// Convert success, move to next
//
@@ -805,7 +811,6 @@ SetSecondLevelPagingAttribute (
DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));
return RETURN_UNSUPPORTED;
}
- //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
//
// Just split current page
// Convert success in next around
@@ -837,7 +842,11 @@ CreateFixedSecondLevelPagingEntry (
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
- VTdUnitInfo->FixedSecondLevelPagingEntry = (UINT32) (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
+ if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
+ return EFI_SUCCESS;
+ }
+
+ VTdUnitInfo->FixedSecondLevelPagingEntry = (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
if (VTdUnitInfo->FixedSecondLevelPagingEntry == 0) {
DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));
return EFI_OUT_OF_RESOURCES;
@@ -846,14 +855,14 @@ 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));
DEBUG ((DEBUG_INFO, " Length = 0x%lx\n", Length));
DEBUG ((DEBUG_INFO, " IoMmuAccess = 0x%lx\n", IoMmuAccess));
- Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
+ Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
return Status;
}
@@ -877,6 +886,9 @@ SetupTranslationTable (
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+ if (VtdUnitInfo->Done) {
+ continue;
+ }
Status = CreateFixedSecondLevelPagingEntry (VtdUnitInfo);
if (EFI_ERROR (Status)) {
@@ -911,151 +923,3 @@ SetupTranslationTable (
return EFI_SUCCESS;
}
-/**
- Find the VTd index by the Segment and SourceId.
-
- @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.
-**/
-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
- )
-{
- 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;
-
- 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 (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 (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;
- }
-
- return VtdIndex;
- }
-
- return (UINTN)-1;
-}
-
-/**
- Always enable the VTd page attribute for the device.
-
- @param[in] VTdInfo The VTd engine context 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.
- @param[in] MemoryBase The base of the memory.
- @param[in] MemoryLimit The limit of the memory.
- @param[in] IoMmuAccess The IOMMU access.
-
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
- IN VTD_INFO *VTdInfo,
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT64 MemoryBase,
- IN UINT64 MemoryLimit,
- IN UINT64 IoMmuAccess
- )
-{
- EFI_STATUS Status;
- UINTN VtdIndex;
- VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;
- VTD_CONTEXT_ENTRY *ContextEntry;
- VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
- UINT64 Pt;
-
- 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;
- }
-
- 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;
- }
- }
-
- 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));
- }
-
- return EFI_SUCCESS;
-}
--
2.16.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#85899): https://edk2.groups.io/g/devel/message/85899
Mute This Topic: https://groups.io/mt/88505121/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
As the review comment form Ray, I will use a fixed MAX VTdUnit number in function VTdInfoNotify().
After that, it will no need to allocate memory at every function call of VTdInfoNotify().
I set the MAX VTd unit number to 42. The total memory usage will just smaller than 4k (1 page). And this number is enough for client and server projects.
I update to patch V6
@Ni, Ray Could you help review and merge the patch ?
Thank you
BR
Sheng Wei
> -----Original Message-----
> From: Huang, Jenny <jenny.huang@intel.com>
> Sent: 2022年1月21日 16:36
> To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Kowalewski, Robert
> <robert.kowalewski@intel.com>
> Subject: RE: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA
> buffer once.
>
> Reviewed-by: Jenny Huang <jenny.huang@intel.com>
>
> -----Original Message-----
> From: Sheng, W <w.sheng@intel.com>
> Sent: Tuesday, January 18, 2022 4:15 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>;
> Kowalewski, Robert <robert.kowalewski@intel.com>
> Subject: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer
> once.
>
> 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>
> Reviewed-by: Jenny Huang <jenny.huang@intel.com>
> Signed-off-by: Sheng Wei <w.sheng@intel.com>
> ---
> .../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 545 +--------------------
> .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 433 +++++++---------
> .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 474 ++++++++++----
> ----
> .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 119 ++---
> .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 196 ++------
> 5 files changed, 533 insertions(+), 1234 deletions(-)
>
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
> index e9c99d0a..acfbc4a8 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
>
> **/
> @@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry (
> return;
> }
>
> -/**
> - Dump DMAR RMRR table.
> -
> - @param[in] Rmrr DMAR RMRR table
> -**/
> -VOID
> -DumpDmarRmrr (
> - IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
> - )
> -{
> - EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDeviceScopeEntry;
> - INTN RmrrLen;
> -
> - if (Rmrr == NULL) {
> - return;
> - }
> -
> - DEBUG ((DEBUG_INFO,
> - "
> **********************************************************
> *****************\n"
> - ));
> - DEBUG ((DEBUG_INFO,
> - " * Reserved Memory Region Reporting Structure *\n"
> - ));
> - DEBUG ((DEBUG_INFO,
> - "
> **********************************************************
> *****************\n"
> - ));
> - DEBUG ((DEBUG_INFO,
> - (sizeof (UINTN) == sizeof (UINT64)) ?
> - " RMRR address ........................................... 0x%016lx\n" :
> - " RMRR address ........................................... 0x%08x\n",
> - Rmrr
> - ));
> - DEBUG ((DEBUG_INFO,
> - " Type ................................................. 0x%04x\n",
> - Rmrr->Header.Type
> - ));
> - DEBUG ((DEBUG_INFO,
> - " Length ............................................... 0x%04x\n",
> - Rmrr->Header.Length
> - ));
> - DEBUG ((DEBUG_INFO,
> - " Segment Number ....................................... 0x%04x\n",
> - Rmrr->SegmentNumber
> - ));
> - DEBUG ((DEBUG_INFO,
> - " Reserved Memory Region Base Address .................. 0x%016lx\n",
> - Rmrr->ReservedMemoryRegionBaseAddress
> - ));
> - DEBUG ((DEBUG_INFO,
> - " Reserved Memory Region Limit Address ................. 0x%016lx\n",
> - Rmrr->ReservedMemoryRegionLimitAddress
> - ));
> -
> - RmrrLen = Rmrr->Header.Length -
> sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
> - DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1);
> - while (RmrrLen > 0) {
> - DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
> - RmrrLen -= DmarDeviceScopeEntry->Length;
> - DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
> - }
> -
> - DEBUG ((DEBUG_INFO,
> - "
> **********************************************************
> *****************\n\n"
> - ));
> -
> - return;
> -}
> -
> /**
> Dump DMAR DRHD table.
>
> @@ -312,9 +245,6 @@ DumpAcpiDMAR (
> case EFI_ACPI_DMAR_TYPE_DRHD:
> DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
> break;
> - case EFI_ACPI_DMAR_TYPE_RMRR:
> - DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
> - break;
> default:
> break;
> }
> @@ -329,492 +259,43 @@ DumpAcpiDMAR (
> return;
> }
>
> -/**
> - Get VTd engine number.
> -
> - @param[in] AcpiDmarTable DMAR ACPI table
> -
> - @return the VTd engine number.
> -**/
> -UINTN
> -GetVtdEngineNumber (
> - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
> - )
> -{
> - EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
> - UINTN VtdIndex;
> -
> - 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:
> - VtdIndex++;
> - break;
> - default:
> - break;
> - }
> - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN)
> DmarHeader + DmarHeader->Length);
> - }
> - return VtdIndex ;
> -}
> -
> -/**
> - Get PCI device information from DMAR DevScopeEntry.
> -
> - @param[in] Segment The segment number.
> - @param[in] DmarDevScopeEntry DMAR DevScopeEntry
> - @param[out] Bus The bus number.
> - @param[out] Device The device number.
> - @param[out] Function The function number.
> -
> - @retval EFI_SUCCESS The PCI device information is returned.
> -**/
> -EFI_STATUS
> -GetPciBusDeviceFunction (
> - IN UINT16 Segment,
> - IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry,
> - OUT UINT8 *Bus,
> - OUT UINT8 *Device,
> - OUT UINT8 *Function
> - )
> -{
> - EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;
> - UINT8 MyBus;
> - UINT8 MyDevice;
> - UINT8 MyFunction;
> -
> - DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN)
> (DmarDevScopeEntry + 1));
> - MyBus = DmarDevScopeEntry->StartBusNumber;
> - MyDevice = DmarPciPath->Device;
> - MyFunction = DmarPciPath->Function;
> -
> - switch (DmarDevScopeEntry->Type) {
> - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
> - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
> - while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) <
> (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) {
> - MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment,
> MyBus, MyDevice, MyFunction,
> PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
> - DmarPciPath ++;
> - MyDevice = DmarPciPath->Device;
> - MyFunction = DmarPciPath->Function;
> - }
> - break;
> - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
> - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
> - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
> - break;
> - }
> -
> - *Bus = MyBus;
> - *Device = MyDevice;
> - *Function = MyFunction;
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - 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.
> -
> - @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.
> -
> - @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.
> -
> -**/
> -EFI_STATUS
> -RegisterPciDevice (
> - IN VTD_UNIT_INFO *VTdUnitInfo,
> - IN UINT16 Segment,
> - IN VTD_SOURCE_ID SourceId,
> - IN UINT8 DeviceType,
> - IN BOOLEAN CheckExist
> - )
> -{
> - 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"));
> -
> - 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;
> - }
> - }
> -
> - return EFI_SUCCESS;
> -}
> -
> -/**
> - Process DMAR DRHD table.
> -
> - @param[in] VTdUnitInfo The VTd engine unit information.
> - @param[in] DmarDrhd The DRHD table.
> -
> -**/
> -VOID
> -ProcessDrhd (
> - IN VTD_UNIT_INFO *VTdUnitInfo,
> - IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
> - )
> -{
> - EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry;
> - UINT8 Bus;
> - 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"));
> - }
> -
> - VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
> - VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
> - VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
> - VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
> -
> - DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> (DmarDrhd + 1));
> - while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd-
> >Header.Length) {
> -
> - Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber,
> DmarDevScopeEntry, &Bus, &Device, &Function);
> - if (EFI_ERROR (Status)) {
> - return;
> - }
> -
> - 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;
> - }
> - 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);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
> - }
> -
> - 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
> - ));
> -
> - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo-
> >VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
> -
> - 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
> - ));
> - }
> -}
> -
> /**
> 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.
>
> **/
> EFI_STATUS
> ParseDmarAcpiTableDrhd (
> - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
> + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
> + IN PROCESS_DRHD_CALLBACK_FUNC Callback,
> + IN VOID *Context
> )
> {
> EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
> - UINTN VtdUnitNumber;
> - UINTN VtdIndex;
> - VTD_INFO *VTdInfo;
> -
> - VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
> - if (VtdUnitNumber == 0) {
> - return EFI_UNSUPPORTED;
> - }
> -
> - 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;
> + UINT32 VtdIndex;
>
> 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);
> + if (Callback != NULL) {
> + Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)
> DmarHeader);
> + }
> VtdIndex++;
> -
> 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;
> -}
> -
> -
> -/**
> - Process DMAR RMRR table.
> -
> - @param[in] VTdInfo The VTd engine context information.
> - @param[in] DmarRmrr The RMRR table.
> -
> -**/
> -VOID
> -ProcessRmrr (
> - IN VTD_INFO *VTdInfo,
> - IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
> - )
> -{
> - EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry;
> - UINT8 Bus;
> - UINT8 Device;
> - UINT8 Function;
> - EFI_STATUS Status;
> - VTD_SOURCE_ID SourceId;
> -
> - DEBUG ((DEBUG_INFO," PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n",
> DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr-
> >ReservedMemoryRegionLimitAddress));
> -
> - if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
> - (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
> - return ;
> - }
> -
> - 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;
> - }
> -
> - Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber,
> DmarDevScopeEntry, &Bus, &Device, &Function);
> - if (EFI_ERROR (Status)) {
> - continue;
> - }
> -
> - 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));
> - }
> -
> - DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> DmarDevScopeEntry + DmarDevScopeEntry->Length);
> - }
> -}
> -
> -/**
> - Parse DMAR DRHD table.
> -
> - @param[in] VTdInfo The VTd engine context information.
> -
> -**/
> -VOID
> -ParseDmarAcpiTableRmrr (
> - IN VTD_INFO *VTdInfo
> - )
> -{
> - 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);
> - break;
> - default:
> - break;
> - }
> - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN)
> DmarHeader + DmarHeader->Length);
> - }
> + return VtdIndex;
> }
>
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> index 63397a1a..0ed216bb 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,77 +79,73 @@ PerpareCacheInvalidationInterface (
> IN VTD_UNIT_INFO *VTdUnitInfo
> )
> {
> - UINT16 QueueSize;
> + UINT16 QiDescLength;
> UINT64 Reg64;
> UINT32 Reg32;
> VTD_ECAP_REG ECapReg;
> + UINTN VtdUnitBaseAddress;
>
> + VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
>
> - if (VTdUnitInfo->VerReg.Bits.Major <= 6) {
> + if (VTdUnitInfo->VerReg.Bits.Major <= 5) {
> VTdUnitInfo->EnableQueuedInvalidation = 0;
> - DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for
> engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
> + DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for
> engine [0x%x]\n", VtdUnitBaseAddress));
> return EFI_SUCCESS;
> }
>
> - ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo-
> >VtdUnitBaseAddress + R_ECAP_REG);
> + ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
> if (ECapReg.Bits.QI == 0) {
> - DEBUG ((DEBUG_ERROR, "Hardware does not support queued
> invalidations interface for engine [0x%x]\n", VTdUnitInfo-
> >VtdUnitBaseAddress));
> + DEBUG ((DEBUG_ERROR, "Hardware does not support queued
> invalidations interface for engine [0x%x]\n", VtdUnitBaseAddress));
> return EFI_UNSUPPORTED;
> }
>
> VTdUnitInfo->EnableQueuedInvalidation = 1;
> - DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine
> [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
> + DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine
> [0x%x]\n", VtdUnitBaseAddress));
>
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> if ((Reg32 & B_GSTS_REG_QIES) != 0) {
> DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));
> Reg32 &= (~B_GSTS_REG_QIES);
> - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GCMD_REG, Reg32);
> + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
> do {
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (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;
> - }
> + MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0);
> }
>
> //
> // Initialize the Invalidation Queue Tail Register to zero.
> //
> - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG,
> 0);
> + MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);
>
> //
> // 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));
> - Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc;
> - Reg64 |= QueueSize;
> - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG,
> Reg64);
> + DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n",
> QiDescLength));
> + Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
> + Reg64 |= VTdUnitInfo->QueueSize;
> + MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64);
>
> //
> // Enable the queued invalidation interface through the Global Command
> Register.
> // When enabled, hardware sets the QIES field in the Global Status Register.
> //
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> Reg32 |= B_GMCD_REG_QIE;
> - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GCMD_REG, Reg32);
> + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
> DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG
> = 0x%x\n", Reg32));
> do {
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> } while ((Reg32 & B_GSTS_REG_QIES) == 0);
>
> VTdUnitInfo->QiFreeHead = 0;
> @@ -167,21 +163,23 @@ DisableQueuedInvalidationInterface (
> IN VTD_UNIT_INFO *VTdUnitInfo
> )
> {
> - UINT32 Reg32;
> + UINT32 Reg32;
> + UINT16 QiDescLength;
>
> if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> Reg32 &= (~B_GMCD_REG_QIE);
> - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GCMD_REG, Reg32);
> + MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG,
> Reg32);
> DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface.
> GCMD_REG = 0x%x\n", Reg32));
> do {
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> } 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;
> @@ -203,26 +201,11 @@ 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;
> - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG,
> FaultReg);
> + FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress +
> R_FSTS_REG);
> + if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
> + DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n",
> FaultReg));
> + FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);
> + MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG,
> FaultReg);
> return RETURN_DEVICE_ERROR;
> }
>
> @@ -256,7 +239,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));
> @@ -268,12 +251,12 @@ SubmitQueuedInvalidationDescriptor (
> DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo-
> >QiFreeHead));
> VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) %
> QiDescLength;
>
> - Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_IQH_REG);
> + Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> R_IQH_REG);
> //
> // Update the HW tail register indicating the presence of new descriptors.
> //
> Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
> - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG,
> Reg64Iqt);
> + MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG,
> Reg64Iqt);
>
> Status = EFI_SUCCESS;
> do {
> @@ -283,7 +266,7 @@ SubmitQueuedInvalidationDescriptor (
> break;
> }
>
> - Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_IQH_REG);
> + Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> R_IQH_REG);
> } while (Reg64Iqt != Reg64Iqh);
>
> DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
> @@ -307,18 +290,18 @@ InvalidateContextCache (
> //
> // Register-based Invalidation
> //
> - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_CCMD_REG);
> + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> R_CCMD_REG);
> if ((Reg64 & B_CCMD_REG_ICC) != 0) {
> - DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache:
> B_CCMD_REG_ICC is set for VTD(%x)\n", (UINTN)VTdUnitInfo-
> >VtdUnitBaseAddress));
> + DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache:
> B_CCMD_REG_ICC is set for VTD(%x)\n", VTdUnitInfo-
> >VtdUnitBaseAddress));
> return EFI_DEVICE_ERROR;
> }
>
> Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
> Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
> - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_CCMD_REG, Reg64);
> + MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG,
> Reg64);
>
> do {
> - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_CCMD_REG);
> + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> R_CCMD_REG);
> } while ((Reg64 & B_CCMD_REG_ICC) != 0);
> } else {
> //
> @@ -351,26 +334,26 @@ InvalidateIOTLB (
> //
> // Register-based Invalidation
> //
> - ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo-
> >VtdUnitBaseAddress + R_ECAP_REG);
> + ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> R_ECAP_REG);
>
> - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
> - DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is
> set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
> + DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is
> set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress));
> return EFI_DEVICE_ERROR;
> }
>
> Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
> Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
> - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
> + MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO *
> 16) + R_IOTLB_REG, Reg64);
>
> do {
> - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
> } else {
> //
> // Queued Invalidation
> //
> - ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo-
> >VtdUnitBaseAddress + R_ECAP_REG);
> + ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress +
> R_ECAP_REG);
> QiDesc.Low = QI_IOTLB_DID(0) |
> QI_IOTLB_DR(CAP_READ_DRAIN(ECapReg.Uint64)) |
> QI_IOTLB_DW(CAP_WRITE_DRAIN(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) |
> QI_IOTLB_TYPE;
> QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
>
> @@ -392,14 +375,14 @@ InvalidateIOTLB (
> EFI_STATUS
> EnableDmarPreMem (
> IN UINTN VtdUnitBaseAddress,
> - IN UINTN RtaddrRegValue
> + 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);
> @@ -452,30 +435,33 @@ EnableDmar (
> )
> {
> UINT32 Reg32;
> + UINTN VtdUnitBaseAddress;
>
> - DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n",
> VTdUnitInfo->VtdUnitBaseAddress));
> + VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
> +
> + DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n",
> VtdUnitBaseAddress));
>
> DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
> - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
> + MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)
> RootEntryTable);
>
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
> B_GMCD_REG_SRTP);
>
> DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
> do {
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));
>
> //
> // Init DMAr Fault Event and Data registers
> //
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_FEDATA_REG);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
>
> //
> // Write Buffer Flush before invalidation
> //
> - FlushWriteBuffer ((UINTN)VTdUnitInfo->VtdUnitBaseAddress);
> + FlushWriteBuffer (VtdUnitBaseAddress);
>
> //
> // Invalidate the context cache
> @@ -490,11 +476,11 @@ EnableDmar (
> //
> // Enable VTd
> //
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
> B_GMCD_REG_TE);
> DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
> do {
> - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
> R_GSTS_REG);
> + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> } while ((Reg32 & B_GSTS_REG_TE) == 0);
>
> DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
> @@ -566,139 +552,52 @@ DisableDmar (
> }
>
> /**
> - Dump VTd version registers.
> + Enable VTd translation table protection for block DMA
>
> - @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));
> -}
> -
> -/**
> - Dump VTd capability registers.
> -
> - @param[in] CapReg The capability register.
> -**/
> -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));
> -}
> + @param[in] VtdUnitBaseAddress The base address of the VTd engine.
>
> -/**
> - Dump VTd extended capability registers.
> -
> - @param[in] ECapReg The extended capability register.
> + @retval EFI_SUCCESS DMAR translation is enabled.
> + @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
> **/
> -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 UINTN 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 +614,25 @@ EnableVTdTranslationProtection (
> )
> {
> EFI_STATUS Status;
> - UINTN VtdIndex;
> + UINTN Index;
> + VTD_UNIT_INFO *VtdUnitInfo;
>
> - 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);
> + for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
> + VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
> + if (VtdUnitInfo->Done) {
> + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index));
> + continue;
> + }
> +
> + 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,23 +643,22 @@ 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);
> + DisableDmar (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress);
>
> DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]);
> }
> @@ -786,6 +691,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 +733,37 @@ PrepareVtdConfig (
> IN VTD_INFO *VTdInfo
> )
> {
> + EFI_STATUS Status;
> UINTN Index;
> - UINTN DomainNumber;
> + VTD_UNIT_INFO *VtdUnitInfo;
> + UINTN VtdUnitBaseAddress;
>
> 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;
> + VtdUnitBaseAddress = VtdUnitInfo->VtdUnitBaseAddress;
> + DEBUG((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress));
> +
> + VtdUnitInfo->VerReg.Uint32 = MmioRead32 (VtdUnitBaseAddress +
> R_VER_REG);
> + VtdUnitInfo->CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress +
> R_CAP_REG);
> + VtdUnitInfo->ECapReg.Uint64 = MmioRead64 (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/IntelVTdDmar
> Pei.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.c
> index a8f7bfee..ac91eac3 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.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
> @@ -140,7 +140,7 @@ PeiIoMmuMap (
>
> if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
> Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
> - *DeviceAddress = (UINTN)HostAddress;
> + *DeviceAddress = (UINTN) HostAddress;
> *Mapping = NULL;
> return EFI_SUCCESS;
> }
> @@ -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,114 @@ 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;
>
> - 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;
> + 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.
> +
> + @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 ((UINTN) DmarDrhd-
> >RegisterBaseAddress);
> }
>
> /**
> - Initializes the Intel VTd Info.
> + 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 = (UINTN) 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 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 +481,103 @@ InitVTdInfo (
> VOID
> )
> {
> - EFI_STATUS Status;
> - EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
> - VOID *Hob;
> VTD_INFO *VTdInfo;
> - UINT64 EngineMask;
> + EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
> + UINTN VtdUnitNumber;
> + VTD_UNIT_INFO *VtdUnitInfo;
> + EFI_STATUS Status;
> + UINTN NewUnitIndex;
> + UINTN PreviousUnitIndex;
>
> - Status = PeiServicesLocatePpi (
> - &gEdkiiVTdInfoPpiGuid,
> - 0,
> - NULL,
> - (VOID **)&AcpiDmarTable
> - );
> - ASSERT_EFI_ERROR (Status);
> + VTdInfo = GetVTdInfoHob ();
> + ASSERT (VTdInfo != NULL);
>
> - DumpAcpiDMAR (AcpiDmarTable);
> + AcpiDmarTable = GetAcpiDmarTable ();
> + ASSERT (AcpiDmarTable != NULL);
>
> //
> - // Clear old VTdInfo Hob.
> + // Get VTd Unit Number
> //
> - Hob = GetFirstGuidHob (&mVTdInfoGuid);
> - if (Hob != NULL) {
> - DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
> -
> - VTdInfo = GET_GUID_HOB_DATA(Hob);
> - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
> - EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
> -
> - ReleaseVTdInfo (VTdInfo);
> - VTdInfo->VTdEngineCount = 0;
> + VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, NULL, NULL);
> + if (VtdUnitNumber == 0) {
> + return EFI_UNSUPPORTED;
> + }
>
> - ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
> + //
> + // Genrate a new Vtd Unit Info Table
> + //
> + 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
> + // Parse the DMAR ACPI Table to the new Vtd Unit Info Table
> //
> - 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) {
> + //
> + // New Vtd Unit Info Table Loop
> + //
> + for (NewUnitIndex = 0; NewUnitIndex < VtdUnitNumber;
> NewUnitIndex++) {
> + //
> + // Previous Vtd Unit Info Table Loop
> + //
> + for (PreviousUnitIndex = 0; PreviousUnitIndex < VTdInfo-
> >VTdEngineCount; PreviousUnitIndex++) {
> + //
> + // Compare the new Vtd Unit with the previous VTd Unit
> + //
> + if (VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress == VTdInfo-
> >VtdUnitInfo[PreviousUnitIndex].VtdUnitBaseAddress) {
> + DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n",
> VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress));
> + CopyMem (&VtdUnitInfo[NewUnitIndex], &VTdInfo-
> >VtdUnitInfo[PreviousUnitIndex], sizeof (VTD_UNIT_INFO));
> + VtdUnitInfo[NewUnitIndex].Done = TRUE;
> +
> + break;
> + }
> + }
> + }
> + }
> + VTdInfo->AcpiDmarTable = AcpiDmarTable;
> + VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
> + VTdInfo->VTdEngineCount = VtdUnitNumber;
> + VTdInfo->VtdUnitInfo = VtdUnitInfo;
>
> 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;
> + EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
>
> - 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;
> - }
> -
> - 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 +600,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 +611,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,33 +621,40 @@ 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 = (UINTN) AllocateAlignedPages
> (EFI_SIZE_TO_PAGES (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%x\n", DmaBufferInfo-
> >DmaBufferSize));
> + DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\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));
> + DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%x\n",
> DmaBufferInfo->DmaBufferCurrentTop));
> + DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n",
> DmaBufferInfo->DmaBufferCurrentBottom));
>
> return EFI_SUCCESS;
> }
> @@ -588,14 +671,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 +687,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);
> @@ -619,10 +695,6 @@ InitVTdDmarForDma (
> return Status;
> }
>
> - // If there is RMRR memory, parse it here.
> - DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
> - ParseDmarAcpiTableRmrr (VTdInfo);
> -
> DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
> Status = EnableVTdTranslationProtection(VTdInfo);
> if (EFI_ERROR (Status)) {
> @@ -668,21 +740,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 +794,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 +814,16 @@ VTdInfoNotify (
> //
>
> Status = InitDmaBuffer ();
> - ASSERT_EFI_ERROR(Status);
> + ASSERT_EFI_ERROR (Status);
> +
> + //
> + // NOTE: We need reinit VTdInfo because previous information might be
> overriden.
> + //
> + Status = InitVTdInfo ();
> + ASSERT_EFI_ERROR (Status);
>
> - InitVTdDmarForDma ();
> + Status = InitVTdDmarForDma ();
> + ASSERT_EFI_ERROR (Status);
> }
>
> return EFI_SUCCESS;
> @@ -826,4 +889,3 @@ IntelVTdDmarInitialize (
>
> return EFI_SUCCESS;
> }
> -
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> index e23a6c8e..351a7810 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> @@ -9,68 +9,61 @@
> #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;
> -
> -typedef struct {
> - UINT32 VtdUnitBaseAddress;
> + BOOLEAN Done;
> + UINTN VtdUnitBaseAddress;
> UINT16 Segment;
> + UINT8 Flags;
> VTD_VER_REG VerReg;
> VTD_CAP_REG CapReg;
> VTD_ECAP_REG ECapReg;
> BOOLEAN Is5LevelPaging;
> - UINT32 FixedSecondLevelPagingEntry;
> - UINT32 RmrrSecondLevelPagingEntry;
> - UINT32 RootEntryTable;
> - UINT32 ExtRootEntryTable;
> - UINT16 RootEntryTablePageSize;
> - UINT16 ExtRootEntryTablePageSize;
> - PEI_PCI_DEVICE_INFORMATION PciDeviceInfo;
> UINT8 EnableQueuedInvalidation;
> - UINT16 QiDescLength;
> + UINT16 QueueSize;
> QI_DESC *QiDesc;
> UINT16 QiFreeHead;
> + UINTN FixedSecondLevelPagingEntry;
> + UINTN RootEntryTable;
> + UINTN ExtRootEntryTable;
> + UINTN RootEntryTablePageSize;
> + UINTN ExtRootEntryTablePageSize;
> } VTD_UNIT_INFO;
>
> typedef struct {
> - UINT32 AcpiDmarTable;
> + EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
> UINT8 HostAddressWidth;
> - UINT32 VTdEngineCount;
> - VTD_UNIT_INFO VtdUnitInfo[1];
> + UINTN VTdEngineCount;
> + VTD_UNIT_INFO *VtdUnitInfo;
> } VTD_INFO;
>
> typedef struct {
> - UINT64 DmaBufferBase;
> - UINT64 DmaBufferSize;
> - UINT64 DmaBufferLimit;
> - UINT64 DmaBufferCurrentTop;
> - UINT64 DmaBufferCurrentBottom;
> + UINTN DmaBufferBase;
> + UINTN DmaBufferSize;
> + UINTN DmaBufferCurrentTop;
> + UINTN DmaBufferCurrentBottom;
> } DMA_BUFFER_INFO;
>
> +typedef
> +VOID
> +(*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 UINTN VtdUnitBaseAddress
> );
>
> /**
> @@ -90,34 +83,27 @@ 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.
> -**/
> -EFI_STATUS
> -ParseDmarAcpiTableDrhd (
> - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
> - );
> -
> -/**
> - Parse DMAR DRHD table.
> + @return the VTd engine number.
>
> - @param[in] VTdInfo The VTd engine context information.
> **/
> -VOID
> -ParseDmarAcpiTableRmrr (
> - IN VTD_INFO *VTdInfo
> +UINTN
> +ParseDmarAcpiTableDrhd (
> + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
> + IN PROCESS_DRHD_CALLBACK_FUNC Callback,
> + IN VOID *Context
> );
>
> /**
> @@ -214,30 +200,7 @@ GetPciDataIndex (
> IN VTD_SOURCE_ID SourceId
> );
>
> -/**
> - Always enable the VTd page attribute for the device.
> -
> - @param[in] VTdInfo The VTd engine context 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.
> - @param[in] MemoryBase The base of the memory.
> - @param[in] MemoryLimit The limit of the memory.
> - @param[in] IoMmuAccess The IOMMU access.
> -
> - @retval EFI_SUCCESS The VTd entry is updated to always enable all
> DMA access for the specific device.
> -**/
> -EFI_STATUS
> -EnableRmrrPageAttribute (
> - IN VTD_INFO *VTdInfo,
> - IN UINT16 Segment,
> - IN VTD_SOURCE_ID SourceId,
> - IN UINT64 MemoryBase,
> - IN UINT64 MemoryLimit,
> - IN UINT64 IoMmuAccess
> - );
> -
> extern EFI_GUID mVTdInfoGuid;
> extern EFI_GUID mDmaBufferInfoGuid;
>
> #endif
> -
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> index a309d566..c94f4a85 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> @@ -1,6 +1,7 @@
> /** @file
>
> Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
> +
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> **/
> @@ -129,12 +130,12 @@ CreateSecondLevelPagingEntryTable (
> FlushPageTableMemory (VTdUnitInfo, (UINTN) SecondLevelPagingEntry,
> EFI_PAGES_TO_SIZE (1));
> }
>
> - DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n",
> SecondLevelPagingEntry));
> + DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64)
> (UINTN) SecondLevelPagingEntry));
> //
> // If no access is needed, just create not present entry.
> //
> if (IoMmuAccess == 0) {
> - DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN)
> SecondLevelPagingEntry));
> + DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n",
> (UINT64) (UINTN) SecondLevelPagingEntry));
> return SecondLevelPagingEntry;
> }
>
> @@ -244,7 +245,7 @@ CreateSecondLevelPagingEntryTable (
> }
> FlushPageTableMemory (VTdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start],
> (UINTN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]);
>
> - DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n",
> (UINTN)SecondLevelPagingEntry));
> + DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64)
> (UINTN) SecondLevelPagingEntry));
> return SecondLevelPagingEntry;
> }
>
> @@ -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);
> @@ -286,8 +291,8 @@ CreateContextEntry (
> }
>
> DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer));
> - VTdUnitInfo->RootEntryTable = (UINT32) (UINTN) Buffer;
> - VTdUnitInfo->RootEntryTablePageSize = (UINT16) EntryTablePages;
> + VTdUnitInfo->RootEntryTable = (UINTN) Buffer;
> + VTdUnitInfo->RootEntryTablePageSize = EntryTablePages;
> RootEntryBase = (VTD_ROOT_ENTRY *) Buffer;
> Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
>
> @@ -304,7 +309,7 @@ CreateContextEntry (
> RootEntry->Bits.ContextTablePointerHi = (UINT32) RShiftU64 ((UINT64)
> (UINTN) Buffer, 32);
> RootEntry->Bits.Present = 1;
> Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
> - ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry-
> >Bits.ContextTablePointerHi) ;
> + ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry-
> >Bits.ContextTablePointerHi);
>
> for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER;
> ContextIndex++) {
> SourceId.Index.ContextIndex = (UINT8) ContextIndex;
> @@ -317,7 +322,7 @@ CreateContextEntry (
> ContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 :
> 0x2;
>
> if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
> - SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)
> (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
> + SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)
> VTdUnitInfo->FixedSecondLevelPagingEntry;
> Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
> ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
> ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32)
> RShiftU64(Pt, 20);
> @@ -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);
> @@ -369,8 +378,8 @@ CreateExtContextEntry (
> }
>
> DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer));
> - VTdUnitInfo->ExtRootEntryTable = (UINT32) (UINTN) Buffer;
> - VTdUnitInfo->ExtRootEntryTablePageSize = (UINT16) EntryTablePages;
> + VTdUnitInfo->ExtRootEntryTable = (UINTN) Buffer;
> + VTdUnitInfo->ExtRootEntryTablePageSize = EntryTablePages;
> ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) Buffer;
> Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
>
> @@ -390,7 +399,7 @@ CreateExtContextEntry (
> ExtRootEntry->Bits.UpperContextTablePointerHi = (UINT32) RShiftU64
> (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);
> ExtRootEntry->Bits.UpperPresent = 1;
> Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);
> - ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo,
> ExtRootEntry->Bits.LowerContextTablePointerHi) ;
> + ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo,
> ExtRootEntry->Bits.LowerContextTablePointerHi);
>
> for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER;
> ContextIndex++) {
> SourceId.Index.ContextIndex = (UINT8) ContextIndex;
> @@ -403,7 +412,7 @@ CreateExtContextEntry (
> ExtContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ?
> 0x3 : 0x2;
>
> if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
> - SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)
> (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
> + SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)
> VTdUnitInfo->FixedSecondLevelPagingEntry;
> Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
>
> ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32)
> Pt;
> @@ -791,9 +800,6 @@ SetSecondLevelPagingAttribute (
> SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute);
> if (SplitAttribute == PageNone) {
> ConvertSecondLevelPageEntryAttribute (VTdUnitInfo, PageEntry,
> IoMmuAccess, &IsEntryModified);
> - if (IsEntryModified) {
> - //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
> - }
> //
> // Convert success, move to next
> //
> @@ -805,7 +811,6 @@ SetSecondLevelPagingAttribute (
> DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));
> return RETURN_UNSUPPORTED;
> }
> - //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
> //
> // Just split current page
> // Convert success in next around
> @@ -837,7 +842,11 @@ CreateFixedSecondLevelPagingEntry (
> VOID *Hob;
> DMA_BUFFER_INFO *DmaBufferInfo;
>
> - VTdUnitInfo->FixedSecondLevelPagingEntry = (UINT32) (UINTN)
> CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
> + if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
> + return EFI_SUCCESS;
> + }
> +
> + VTdUnitInfo->FixedSecondLevelPagingEntry = (UINTN)
> CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
> if (VTdUnitInfo->FixedSecondLevelPagingEntry == 0) {
> DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));
> return EFI_OUT_OF_RESOURCES;
> @@ -846,14 +855,14 @@ 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));
> DEBUG ((DEBUG_INFO, " Length = 0x%lx\n", Length));
> DEBUG ((DEBUG_INFO, " IoMmuAccess = 0x%lx\n", IoMmuAccess));
>
> - Status = SetSecondLevelPagingAttribute (VTdUnitInfo,
> (VTD_SECOND_LEVEL_PAGING_ENTRY*) (UINTN) VTdUnitInfo-
> >FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
> + Status = SetSecondLevelPagingAttribute (VTdUnitInfo,
> (VTD_SECOND_LEVEL_PAGING_ENTRY*) VTdUnitInfo-
> >FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
>
> return Status;
> }
> @@ -877,6 +886,9 @@ SetupTranslationTable (
>
> for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
> VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
> + if (VtdUnitInfo->Done) {
> + continue;
> + }
>
> Status = CreateFixedSecondLevelPagingEntry (VtdUnitInfo);
> if (EFI_ERROR (Status)) {
> @@ -911,151 +923,3 @@ SetupTranslationTable (
> return EFI_SUCCESS;
> }
>
> -/**
> - Find the VTd index by the Segment and SourceId.
> -
> - @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.
> -**/
> -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
> - )
> -{
> - 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;
> -
> - 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 (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 (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;
> - }
> -
> - return VtdIndex;
> - }
> -
> - return (UINTN)-1;
> -}
> -
> -/**
> - Always enable the VTd page attribute for the device.
> -
> - @param[in] VTdInfo The VTd engine context 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.
> - @param[in] MemoryBase The base of the memory.
> - @param[in] MemoryLimit The limit of the memory.
> - @param[in] IoMmuAccess The IOMMU access.
> -
> - @retval EFI_SUCCESS The VTd entry is updated to always enable all
> DMA access for the specific device.
> -**/
> -EFI_STATUS
> -EnableRmrrPageAttribute (
> - IN VTD_INFO *VTdInfo,
> - IN UINT16 Segment,
> - IN VTD_SOURCE_ID SourceId,
> - IN UINT64 MemoryBase,
> - IN UINT64 MemoryLimit,
> - IN UINT64 IoMmuAccess
> - )
> -{
> - EFI_STATUS Status;
> - UINTN VtdIndex;
> - VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;
> - VTD_CONTEXT_ENTRY *ContextEntry;
> - VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> - UINT64 Pt;
> -
> - 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;
> - }
> -
> - 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;
> - }
> - }
> -
> - 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));
> - }
> -
> - return EFI_SUCCESS;
> -}
> --
> 2.16.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#86011): https://edk2.groups.io/g/devel/message/86011
Mute This Topic: https://groups.io/mt/88505121/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.