IntelSiliconPkg/IntelVTd: update PlatformVtdPolicy

1. Handle flexible exception list format.
1.1 Handle DeviceScope based device info.
1.2 Handle PciDeviceId based device info.
2. Reorg the PCI_DEVICE_INFORMATION
2.1 Merge data pointer reduce allocation times
2.2 Add PCI device id to PCI_DEVICE_INFORMATION
2.3 Rename PciDescriptor to avoid confusing.
3. Fix the debug message too long issue.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
This commit is contained in:
Jiewen Yao
2017-08-25 14:46:07 +08:00
parent 71872f7cda
commit f77d35c7f0
7 changed files with 423 additions and 161 deletions

View File

@@ -151,6 +151,132 @@ ReturnUefiMemoryMap (
return ;
}
/**
The scan bus callback function to always enable page attribute.
@param[in] Context The context of the callback.
@param[in] Segment The segment of the source.
@param[in] Bus The bus of the source.
@param[in] Device The device of the source.
@param[in] Function The function of the source.
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
**/
EFI_STATUS
EFIAPI
ScanBusCallbackAlwaysEnablePageAttribute (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function
)
{
VTD_SOURCE_ID SourceId;
EFI_STATUS Status;
SourceId.Bits.Bus = Bus;
SourceId.Bits.Device = Device;
SourceId.Bits.Function = Function;
Status = AlwaysEnablePageAttribute (Segment, SourceId);
return Status;
}
/**
Always enable the VTd page attribute for the device in the DeviceScope.
@param[in] DeviceScope the input device scope data structure
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device in the device scope.
**/
EFI_STATUS
AlwaysEnablePageAttributeDeviceScope (
IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope
)
{
UINT8 Bus;
UINT8 Device;
UINT8 Function;
VTD_SOURCE_ID SourceId;
UINT8 SecondaryBusNumber;
EFI_STATUS Status;
Status = GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceScope->DeviceScope, &Bus, &Device, &Function);
if (DeviceScope->DeviceScope.Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE) {
//
// Need scan the bridge and add all devices.
//
SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DeviceScope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
Status = ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusNumber, ScanBusCallbackAlwaysEnablePageAttribute);
return Status;
} else {
SourceId.Bits.Bus = Bus;
SourceId.Bits.Device = Device;
SourceId.Bits.Function = Function;
Status = AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, SourceId);
return Status;
}
}
/**
Always enable the VTd page attribute for the device matching DeviceId.
@param[in] PciDeviceId the input PCI device ID
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device matching DeviceId.
**/
EFI_STATUS
AlwaysEnablePageAttributePciDeviceId (
IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId
)
{
UINTN VtdIndex;
UINTN PciIndex;
PCI_DEVICE_DATA *PciDeviceData;
EFI_STATUS Status;
for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
for (PciIndex = 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; PciIndex++) {
PciDeviceData = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[PciIndex];
if (((PciDeviceId->VendorId == 0xFFFF) || (PciDeviceId->VendorId == PciDeviceData->PciDeviceId.VendorId)) &&
((PciDeviceId->DeviceId == 0xFFFF) || (PciDeviceId->DeviceId == PciDeviceData->PciDeviceId.DeviceId)) &&
((PciDeviceId->RevisionId == 0xFF) || (PciDeviceId->RevisionId == PciDeviceData->PciDeviceId.RevisionId)) &&
((PciDeviceId->SubsystemVendorId == 0xFFFF) || (PciDeviceId->SubsystemVendorId == PciDeviceData->PciDeviceId.SubsystemVendorId)) &&
((PciDeviceId->SubsystemDeviceId == 0xFFFF) || (PciDeviceId->SubsystemDeviceId == PciDeviceData->PciDeviceId.SubsystemDeviceId)) ) {
Status = AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex].Segment, PciDeviceData->PciSourceId);
if (EFI_ERROR(Status)) {
continue;
}
}
}
}
return EFI_SUCCESS;
}
/**
Always enable the VTd page attribute for the device.
@param[in] DeviceInfo the exception device information
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device in the device info.
**/
EFI_STATUS
AlwaysEnablePageAttributeExceptionDeviceInfo (
IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo
)
{
switch (DeviceInfo->Type) {
case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:
return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1));
case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:
return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1));
default:
return EFI_UNSUPPORTED;
}
}
/**
Initialize platform VTd policy.
**/
@@ -159,10 +285,11 @@ InitializePlatformVTdPolicy (
VOID
)
{
EFI_STATUS Status;
UINTN DeviceInfoCount;
EDKII_PLATFORM_VTD_DEVICE_INFO *DeviceInfo;
UINTN Index;
EFI_STATUS Status;
UINTN DeviceInfoCount;
VOID *DeviceInfo;
EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;
UINTN Index;
//
// It is optional.
@@ -173,10 +300,16 @@ InitializePlatformVTdPolicy (
(VOID **)&mPlatformVTdPolicy
);
if (!EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));
Status = mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPolicy, &DeviceInfoCount, &DeviceInfo);
if (!EFI_ERROR(Status)) {
ThisDeviceInfo = DeviceInfo;
for (Index = 0; Index < DeviceInfoCount; Index++) {
AlwaysEnablePageAttribute (DeviceInfo[Index].Segment, DeviceInfo[Index].SourceId);
if (ThisDeviceInfo->Type == EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_END) {
break;
}
AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);
ThisDeviceInfo = (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo->Length);
}
FreePool (DeviceInfo);
}