summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/efi/nii.c
diff options
context:
space:
mode:
authorMichael Brown2021-11-22 15:53:33 +0100
committerMichael Brown2021-11-23 16:55:01 +0100
commit562c74e1ea52a399f7a6c416e35d98f4b37888cf (patch)
tree87e9f39ee8e0d61bca0af997dfc3a8a1fea739be /src/drivers/net/efi/nii.c
parent[build] Include EFI system partition table entry in isohybrid images (diff)
downloadipxe-562c74e1ea52a399f7a6c416e35d98f4b37888cf.tar.gz
ipxe-562c74e1ea52a399f7a6c416e35d98f4b37888cf.tar.xz
ipxe-562c74e1ea52a399f7a6c416e35d98f4b37888cf.zip
[efi] Run ExitBootServices shutdown hook at TPL_NOTIFY
On some systems (observed with the Thunderbolt ports on a ThinkPad X1 Extreme Gen3 and a ThinkPad P53), if the IOMMU is enabled then the system firmware will install an ExitBootServices notification event that disables bus mastering on the Thunderbolt xHCI controller and all PCI bridges, and destroys any extant IOMMU mappings. This leaves the xHCI controller unable to perform any DMA operations. As described in commit 236299b ("[xhci] Avoid DMA during shutdown if firmware has disabled bus mastering"), any subsequent DMA operation attempted by the xHCI controller will end up completing after the operating system kernel has reenabled bus mastering, resulting in a DMA operation to an area of memory that the hardware is no longer permitted to access and, on Windows with the Driver Verifier enabled, a STOP 0xE6 (DRIVER_VERIFIER_DMA_VIOLATION). That commit avoids triggering any DMA attempts during the shutdown of the xHCI controller itself. However, this is not a complete solution since any attached and opened USB device (e.g. a USB NIC) may asynchronously trigger DMA attempts that happen to occur after bus mastering has been disabled but before we reset the xHCI controller. Avoid this problem by installing our own ExitBootServices notification event at TPL_NOTIFY, thereby causing it to be invoked before the firmware's own ExitBootServices notification event that disables bus mastering. This unsurprisingly causes the shutdown hook itself to be invoked at TPL_NOTIFY, which causes a fatal error when later code attempts to raise the TPL to TPL_CALLBACK (which is a lower TPL). Work around this problem by redefining the "internal" iPXE TPL to be variable, and set this internal TPL to TPL_NOTIFY when the shutdown hook is invoked. Avoid calling into an underlying SNP protocol instance from within our shutdown hook at TPL_NOTIFY, since the underlying SNP driver may attempt to raise the TPL to TPL_CALLBACK (which would cause a fatal error). Failing to shut down the underlying SNP device is safe to do since the underlying device must, in any case, have installed its own ExitBootServices hook if any shutdown actions are required. Reported-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Tested-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/efi/nii.c')
-rw-r--r--src/drivers/net/efi/nii.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
index b9f34650..833462e7 100644
--- a/src/drivers/net/efi/nii.c
+++ b/src/drivers/net/efi/nii.c
@@ -576,7 +576,7 @@ static int nii_issue_cpb_db ( struct nii_nic *nii, unsigned int op, void *cpb,
cdb.IFnum = nii->nii->IfNum;
/* Raise task priority level */
- tpl = bs->RaiseTPL ( TPL_CALLBACK );
+ tpl = bs->RaiseTPL ( efi_internal_tpl );
/* Issue command */
DBGC2 ( nii, "NII %s issuing %02x:%04x ifnum %d%s%s\n",