mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/PciBus: Disable BME of all devices when entering RT
The patch ensures all DMA transactions are blocked after ExitBootService. If a platform enables IOMMU before and needs disable IOMMU after ExitBootService, the IOMMU should be disabled after PCI bus driver disables BME. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael Turner <michael.turner@microsoft.com> Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Cc: Jeff Fan <vanjeff_919@hotmail.com>
This commit is contained in:
parent
3d34e92fab
commit
050763db07
|
@ -18,6 +18,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
#include <PiDxe.h>
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <Guid/EventGroup.h>
|
||||||
|
|
||||||
#include <Protocol/LoadedImage.h>
|
#include <Protocol/LoadedImage.h>
|
||||||
#include <Protocol/PciHostBridgeResourceAllocation.h>
|
#include <Protocol/PciHostBridgeResourceAllocation.h>
|
||||||
#include <Protocol/PciIo.h>
|
#include <Protocol/PciIo.h>
|
||||||
|
|
|
@ -80,6 +80,9 @@
|
||||||
DebugLib
|
DebugLib
|
||||||
PeCoffLib
|
PeCoffLib
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiEventExitBootServicesGuid ## SOMETIMES_CONSUMES ## Event
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiPciHotPlugRequestProtocolGuid ## SOMETIMES_PRODUCES
|
gEfiPciHotPlugRequestProtocolGuid ## SOMETIMES_PRODUCES
|
||||||
gEfiPciIoProtocolGuid ## BY_START
|
gEfiPciIoProtocolGuid ## BY_START
|
||||||
|
|
|
@ -20,6 +20,72 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
//
|
//
|
||||||
LIST_ENTRY mPciDevicePool;
|
LIST_ENTRY mPciDevicePool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disable Bus Master Enable bit in all devices in the list.
|
||||||
|
|
||||||
|
@param Devices A device list.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DisableBmeOnTree (
|
||||||
|
IN LIST_ENTRY *Devices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
PCI_IO_DEVICE *PciIoDevice;
|
||||||
|
UINT16 Command;
|
||||||
|
|
||||||
|
for ( Link = GetFirstNode (Devices)
|
||||||
|
; !IsNull (Devices, Link)
|
||||||
|
; Link = GetNextNode (Devices, Link)
|
||||||
|
) {
|
||||||
|
PciIoDevice = PCI_IO_DEVICE_FROM_LINK (Link);
|
||||||
|
//
|
||||||
|
// Turn off all children's Bus Master, if any
|
||||||
|
//
|
||||||
|
DisableBmeOnTree (&PciIoDevice->ChildList);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If this is a device that supports BME, disable BME on this device.
|
||||||
|
//
|
||||||
|
if ((PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {
|
||||||
|
PCI_READ_COMMAND_REGISTER(PciIoDevice, &Command);
|
||||||
|
if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
|
||||||
|
Command &= ~EFI_PCI_COMMAND_BUS_MASTER;
|
||||||
|
PCI_SET_COMMAND_REGISTER (PciIoDevice, Command);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO," %02x %02x %02x %04x\n",
|
||||||
|
PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber,
|
||||||
|
Command
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Exit Boot Services Event notification handler.
|
||||||
|
|
||||||
|
Disable Bus Master on any that were enabled during BDS.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
OnExitBootServices (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"PciBus: Disable Bus Master of all devices...\n"
|
||||||
|
" Bus# Device# Function# NewCommand\n"
|
||||||
|
));
|
||||||
|
DisableBmeOnTree(&mPciDevicePool);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the PCI devices pool.
|
Initialize the PCI devices pool.
|
||||||
|
|
||||||
|
@ -29,7 +95,27 @@ InitializePciDevicePool (
|
||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
EFI_EVENT ExitBootServicesEvent;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
InitializeListHead (&mPciDevicePool);
|
InitializeListHead (&mPciDevicePool);
|
||||||
|
|
||||||
|
//
|
||||||
|
// DisableBME on ExitBootServices should be synchonized with any IOMMU ExitBootServices routine.
|
||||||
|
// DisableBME should be run before the IOMMU protections are disabled.
|
||||||
|
// One way to do this is to ensure that the IOMMU ExitBootServices callback runs at TPL_CALLBACK.
|
||||||
|
//
|
||||||
|
Status = gBS->CreateEventEx (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_NOTIFY,
|
||||||
|
OnExitBootServices,
|
||||||
|
NULL,
|
||||||
|
&gEfiEventExitBootServicesGuid,
|
||||||
|
&ExitBootServicesEvent
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "PciBus: Unable to hook ExitBootServices event - %r\n", Status));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue