summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2023-07-19 18:31:29 +0200
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-07-19 17:36:31 +0000
commita52044a9e602bc168cdf5d73a48952bfc9edb521 (patch)
tree7c29b6914c18396d847da6f86c0e9e85195c2511
parent08aacbf0560d98929d402af029ac010d35abb3d6 (diff)
downloadedk2-a52044a9e602bc168cdf5d73a48952bfc9edb521.tar.gz
edk2-a52044a9e602bc168cdf5d73a48952bfc9edb521.tar.bz2
edk2-a52044a9e602bc168cdf5d73a48952bfc9edb521.zip
OvmfPkg/IoMmuDxe: add locking to IoMmuAllocateBounceBuffer
Searching for an unused bounce buffer in mReservedMemBitmap and reserving the buffer by flipping the bit is a critical section which must not be interrupted. Raise the TPL level to ensure that. Without this fix it can happen that IoMmuDxe hands out the same bounce buffer twice, causing trouble down the road. Seen happening in practice with VirtioNetDxe setting up the network interface (and calling into IoMmuDxe from a polling timer callback) in parallel with Boot Manager doing some disk I/O. An ASSERT() in VirtioNet caught the buffer inconsistency. Full story with lots of details and discussions is available here: https://bugzilla.redhat.com/show_bug.cgi?id=2211060 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--OvmfPkg/IoMmuDxe/IoMmuBuffer.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/OvmfPkg/IoMmuDxe/IoMmuBuffer.c b/OvmfPkg/IoMmuDxe/IoMmuBuffer.c
index c8f6cf4818..103003cae3 100644
--- a/OvmfPkg/IoMmuDxe/IoMmuBuffer.c
+++ b/OvmfPkg/IoMmuDxe/IoMmuBuffer.c
@@ -367,7 +367,9 @@ IoMmuAllocateBounceBuffer (
{
EFI_STATUS Status;
UINT32 ReservedMemBitmap;
+ EFI_TPL OldTpl;
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
ReservedMemBitmap = 0;
Status = InternalAllocateBuffer (
Type,
@@ -378,6 +380,7 @@ IoMmuAllocateBounceBuffer (
);
MapInfo->ReservedMemBitmap = ReservedMemBitmap;
mReservedMemBitmap |= ReservedMemBitmap;
+ gBS->RestoreTPL (OldTpl);
ASSERT (Status == EFI_SUCCESS);
@@ -395,6 +398,8 @@ IoMmuFreeBounceBuffer (
IN OUT MAP_INFO *MapInfo
)
{
+ EFI_TPL OldTpl;
+
if (MapInfo->ReservedMemBitmap == 0) {
gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);
} else {
@@ -407,9 +412,11 @@ IoMmuFreeBounceBuffer (
mReservedMemBitmap,
mReservedMemBitmap & ((UINT32)(~MapInfo->ReservedMemBitmap))
));
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
MapInfo->PlainTextAddress = 0;
mReservedMemBitmap &= (UINT32)(~MapInfo->ReservedMemBitmap);
MapInfo->ReservedMemBitmap = 0;
+ gBS->RestoreTPL (OldTpl);
}
return EFI_SUCCESS;