[10/11] OvmfPkg/XenPvBlkDxe: Use XenBusIo->RegisterExitCallback
diff mbox series

Message ID 20190913145100.303433-11-anthony.perard@citrix.com
State New
Headers show
Series
  • OvmfPkg/XenBusDxe: Fix ExitBootServices handler to avoid allocation
Related show

Commit Message

Anthony PERARD Sept. 13, 2019, 2:50 p.m. UTC
In order to be able to reset the backend before handing it to the next
operating system, it should be reset properly. This patch register a
callback function to be called by XenBusDxe during the
ExitBootServices event.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2190
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
 OvmfPkg/XenPvBlkDxe/BlockFront.c  | 37 ++++++++++++++++++++++++++++---
 OvmfPkg/XenPvBlkDxe/BlockFront.h  | 12 +++++++++-
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c |  4 ++--
 3 files changed, 47 insertions(+), 6 deletions(-)

Patch
diff mbox series

diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.c b/OvmfPkg/XenPvBlkDxe/BlockFront.c
index 25a398ccc4..7c166888bd 100644
--- a/OvmfPkg/XenPvBlkDxe/BlockFront.c
+++ b/OvmfPkg/XenPvBlkDxe/BlockFront.c
@@ -309,6 +309,8 @@  XenPvBlockFrontInitialization (
           Dev->MediaInfo.Sectors, Dev->MediaInfo.SectorSize));
 
   *DevPtr = Dev;
+
+  XenBusIo->RegisterExitCallback (XenBusIo, XenPvBlockFrontReset, Dev);
   return EFI_SUCCESS;
 
 Error2:
@@ -326,13 +328,16 @@  XenPvBlockFrontInitialization (
 
 VOID
 XenPvBlockFrontShutdown (
-  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  IN XEN_BLOCK_FRONT_DEVICE *Dev,
+  IN BOOLEAN                ResetOnly
   )
 {
   XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
   XENSTORE_STATUS Status;
   UINT64 Value;
 
+  XenBusIo->RegisterExitCallback (XenBusIo, NULL, NULL);
+
   XenPvBlockSync (Dev);
 
   Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosing);
@@ -393,12 +398,38 @@  XenPvBlockFrontShutdown (
   }
 
 Close:
-  XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
+  if (!ResetOnly) {
+    XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
+  }
   XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
   XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
   XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
 
-  XenPvBlockFree (Dev);
+  if (ResetOnly) {
+    XenBusIo->GrantEndAccess (XenBusIo, Dev->RingRef);
+    XenBusIo->EventChannelClose (XenBusIo, Dev->EventChannel);
+  } else {
+    XenPvBlockFree (Dev);
+  }
+}
+
+/**
+  To be called when ExitBootServices has been called.
+
+  This should reset the PV backend without using memory allocation
+  services.
+**/
+VOID
+EFIAPI
+XenPvBlockFrontReset (
+  IN VOID *Context
+  )
+{
+  XEN_BLOCK_FRONT_DEVICE *Dev;
+
+  Dev = Context;
+
+  XenPvBlockFrontShutdown (Dev, TRUE);
 }
 
 STATIC
diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.h b/OvmfPkg/XenPvBlkDxe/BlockFront.h
index 7c2d7f2c9e..ebce4fe434 100644
--- a/OvmfPkg/XenPvBlkDxe/BlockFront.h
+++ b/OvmfPkg/XenPvBlkDxe/BlockFront.h
@@ -67,9 +67,19 @@  XenPvBlockFrontInitialization (
   OUT XEN_BLOCK_FRONT_DEVICE **DevPtr
   );
 
+/**
+  @param ResetOnly      Set to TRUE when called during the ExitBootServices.
+**/
 VOID
 XenPvBlockFrontShutdown (
-  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  IN XEN_BLOCK_FRONT_DEVICE *Dev,
+  IN BOOLEAN                ResetOnly
+  );
+
+VOID
+EFIAPI
+XenPvBlockFrontReset (
+  IN VOID *Context
   );
 
 VOID
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
index bfe7b1a754..3031406980 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
@@ -312,7 +312,7 @@  XenPvBlkDxeDriverBindingStart (
 
 UninitBlockFront:
   FreePool (Media);
-  XenPvBlockFrontShutdown (Dev);
+  XenPvBlockFrontShutdown (Dev, FALSE);
 CloseProtocol:
   gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
                       This->DriverBindingHandle, ControllerHandle);
@@ -377,7 +377,7 @@  XenPvBlkDxeDriverBindingStop (
 
   Media = BlockIo->Media;
   Dev = XEN_BLOCK_FRONT_FROM_BLOCK_IO (BlockIo);
-  XenPvBlockFrontShutdown (Dev);
+  XenPvBlockFrontShutdown (Dev, FALSE);
 
   FreePool (Media);