mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-26 07:04:28 +02:00
IntelSiliconPkg IntelVTdDxe: Support early SetAttributes()
Support early SetAttributes() before DMAR table is installed. Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
parent
3a71670618
commit
0bc94c748b
@ -18,6 +18,151 @@ UINT64 mAbove4GMemoryLimit;
|
|||||||
|
|
||||||
EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;
|
EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;
|
||||||
|
|
||||||
|
VTD_ACCESS_REQUEST *mAccessRequest = NULL;
|
||||||
|
UINTN mAccessRequestCount = 0;
|
||||||
|
UINTN mAccessRequestMaxCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Append VTd Access Request to global.
|
||||||
|
|
||||||
|
@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] BaseAddress The base of device memory address to be used as the DMA memory.
|
||||||
|
@param[in] Length The length of device memory address to be used as the DMA memory.
|
||||||
|
@param[in] IoMmuAccess The IOMMU access.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
|
||||||
|
@retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
|
||||||
|
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
|
||||||
|
@retval EFI_INVALID_PARAMETER Length is 0.
|
||||||
|
@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 BaseAddress and Length.
|
||||||
|
@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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
RequestAccessAttribute (
|
||||||
|
IN UINT16 Segment,
|
||||||
|
IN VTD_SOURCE_ID SourceId,
|
||||||
|
IN UINT64 BaseAddress,
|
||||||
|
IN UINT64 Length,
|
||||||
|
IN UINT64 IoMmuAccess
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VTD_ACCESS_REQUEST *NewAccessRequest;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Optimization for memory.
|
||||||
|
//
|
||||||
|
// If the last record is to IoMmuAccess=0,
|
||||||
|
// Check previous records and remove the matched entry.
|
||||||
|
//
|
||||||
|
if (IoMmuAccess == 0) {
|
||||||
|
for (Index = 0; Index < mAccessRequestCount; Index++) {
|
||||||
|
if ((mAccessRequest[Index].Segment == Segment) &&
|
||||||
|
(mAccessRequest[Index].SourceId.Uint16 == SourceId.Uint16) &&
|
||||||
|
(mAccessRequest[Index].BaseAddress == BaseAddress) &&
|
||||||
|
(mAccessRequest[Index].Length == Length) &&
|
||||||
|
(mAccessRequest[Index].IoMmuAccess != 0)) {
|
||||||
|
//
|
||||||
|
// Remove this record [Index].
|
||||||
|
// No need to add the new record.
|
||||||
|
//
|
||||||
|
if (Index != mAccessRequestCount - 1) {
|
||||||
|
CopyMem (
|
||||||
|
&mAccessRequest[Index],
|
||||||
|
&mAccessRequest[Index + 1],
|
||||||
|
sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCESS_REQUEST));
|
||||||
|
mAccessRequestCount--;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAccessRequestCount >= mAccessRequestMaxCount) {
|
||||||
|
NewAccessRequest = AllocateZeroPool (sizeof(*NewAccessRequest) * (mAccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));
|
||||||
|
if (NewAccessRequest == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
mAccessRequestMaxCount += MAX_VTD_ACCESS_REQUEST;
|
||||||
|
if (mAccessRequest != NULL) {
|
||||||
|
CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest) * mAccessRequestCount);
|
||||||
|
FreePool (mAccessRequest);
|
||||||
|
}
|
||||||
|
mAccessRequest = NewAccessRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (mAccessRequestCount < mAccessRequestMaxCount);
|
||||||
|
|
||||||
|
mAccessRequest[mAccessRequestCount].Segment = Segment;
|
||||||
|
mAccessRequest[mAccessRequestCount].SourceId = SourceId;
|
||||||
|
mAccessRequest[mAccessRequestCount].BaseAddress = BaseAddress;
|
||||||
|
mAccessRequest[mAccessRequestCount].Length = Length;
|
||||||
|
mAccessRequest[mAccessRequestCount].IoMmuAccess = IoMmuAccess;
|
||||||
|
|
||||||
|
mAccessRequestCount++;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Process Access Requests from before DMAR table is installed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ProcessRequestedAccessAttribute (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));
|
||||||
|
|
||||||
|
for (Index = 0; Index < mAccessRequestCount; Index++) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"PCI(S%x.B%x.D%x.F%x) ",
|
||||||
|
mAccessRequest[Index].Segment,
|
||||||
|
mAccessRequest[Index].SourceId.Bits.Bus,
|
||||||
|
mAccessRequest[Index].SourceId.Bits.Device,
|
||||||
|
mAccessRequest[Index].SourceId.Bits.Function
|
||||||
|
));
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"(0x%lx~0x%lx) - %lx\n",
|
||||||
|
mAccessRequest[Index].BaseAddress,
|
||||||
|
mAccessRequest[Index].Length,
|
||||||
|
mAccessRequest[Index].IoMmuAccess
|
||||||
|
));
|
||||||
|
Status = SetAccessAttribute (
|
||||||
|
mAccessRequest[Index].Segment,
|
||||||
|
mAccessRequest[Index].SourceId,
|
||||||
|
mAccessRequest[Index].BaseAddress,
|
||||||
|
mAccessRequest[Index].Length,
|
||||||
|
mAccessRequest[Index].IoMmuAccess
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAccessRequest != NULL) {
|
||||||
|
FreePool (mAccessRequest);
|
||||||
|
}
|
||||||
|
mAccessRequest = NULL;
|
||||||
|
mAccessRequestCount = 0;
|
||||||
|
mAccessRequestMaxCount = 0;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
return the UEFI memory information.
|
return the UEFI memory information.
|
||||||
|
|
||||||
@ -370,6 +515,8 @@ SetupVtd (
|
|||||||
|
|
||||||
ParseDmarAcpiTableRmrr ();
|
ParseDmarAcpiTableRmrr ();
|
||||||
|
|
||||||
|
ProcessRequestedAccessAttribute ();
|
||||||
|
|
||||||
for (Index = 0; Index < mVtdUnitNumber; Index++) {
|
for (Index = 0; Index < mVtdUnitNumber; Index++) {
|
||||||
DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));
|
DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));
|
||||||
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
|
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -84,6 +84,21 @@ typedef struct {
|
|||||||
PCI_DEVICE_INFORMATION PciDeviceInfo;
|
PCI_DEVICE_INFORMATION PciDeviceInfo;
|
||||||
} VTD_UNIT_INFORMATION;
|
} VTD_UNIT_INFORMATION;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the initial max ACCESS request.
|
||||||
|
// The number may be enlarged later.
|
||||||
|
//
|
||||||
|
#define MAX_VTD_ACCESS_REQUEST 0x100
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Segment;
|
||||||
|
VTD_SOURCE_ID SourceId;
|
||||||
|
UINT64 BaseAddress;
|
||||||
|
UINT64 Length;
|
||||||
|
UINT64 IoMmuAccess;
|
||||||
|
} VTD_ACCESS_REQUEST;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The scan bus callback function.
|
The scan bus callback function.
|
||||||
|
|
||||||
@ -561,4 +576,33 @@ GetPciBusDeviceFunction (
|
|||||||
OUT UINT8 *Function
|
OUT UINT8 *Function
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Append VTd Access Request to global.
|
||||||
|
|
||||||
|
@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] BaseAddress The base of device memory address to be used as the DMA memory.
|
||||||
|
@param[in] Length The length of device memory address to be used as the DMA memory.
|
||||||
|
@param[in] IoMmuAccess The IOMMU access.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
|
||||||
|
@retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
|
||||||
|
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
|
||||||
|
@retval EFI_INVALID_PARAMETER Length is 0.
|
||||||
|
@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 BaseAddress and Length.
|
||||||
|
@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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
RequestAccessAttribute (
|
||||||
|
IN UINT16 Segment,
|
||||||
|
IN VTD_SOURCE_ID SourceId,
|
||||||
|
IN UINT64 BaseAddress,
|
||||||
|
IN UINT64 Length,
|
||||||
|
IN UINT64 IoMmuAccess
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,7 +27,7 @@ typedef struct {
|
|||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
|
EFI_ACPI_DMAR_HEADER *mAcpiDmarTable = NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Dump DMAR DeviceScopeEntry.
|
Dump DMAR DeviceScopeEntry.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
Intel VTd driver.
|
Intel VTd driver.
|
||||||
|
|
||||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -231,6 +231,14 @@ VTdSetAttribute (
|
|||||||
DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
|
DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
|
||||||
DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, IoMmuAccess));
|
DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, IoMmuAccess));
|
||||||
|
|
||||||
|
if (mAcpiDmarTable == NULL) {
|
||||||
|
//
|
||||||
|
// Record the entry to driver global variable.
|
||||||
|
// As such once VTd is activated, the setting can be adopted.
|
||||||
|
//
|
||||||
|
return RequestAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
|
||||||
|
}
|
||||||
|
|
||||||
PERF_CODE (
|
PERF_CODE (
|
||||||
AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);
|
AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);
|
||||||
Identifier = (Segment << 16) | SourceId.Uint16;
|
Identifier = (Segment << 16) | SourceId.Uint16;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user