diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2023-07-19 18:31:29 +0200 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2023-07-19 17:36:31 +0000 |
commit | a52044a9e602bc168cdf5d73a48952bfc9edb521 (patch) | |
tree | 7c29b6914c18396d847da6f86c0e9e85195c2511 | |
parent | 08aacbf0560d98929d402af029ac010d35abb3d6 (diff) | |
download | edk2-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.c | 7 |
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;
|