From 502e604ee9641b13af27809bc1d289d8dfa477da Mon Sep 17 00:00:00 2001 From: Jason Andryuk Date: Mon, 9 May 2022 12:08:55 -0400 Subject: [PATCH] xenmgr: Push ACPI power button multiple times Sometimes the shutdown command does not work. It seems like the longer the VM is up, the more likely it is to not shutdown. This is based on Windows 10 without PV drivers. The button press is seen by the VM to some extent because a DPMS off (black) screen will turn on, but shutdown is not initiated. A second press will trigger it - that was the intent to the xl trigger power line added in commit 1cfb6aa8e63e "xenmgr: Add xl trigger power to HVM shutdown". Re-work the code so a background thread is started that will push the power buttons* 3 times each with a 1 second delay. This will hopefully let the VM recognize the button press without going on for too long. *HVMs have two power and two sleep buttons. One is Xen emulating buttons for HVMs, and the second is from QEMU's acpi-pm-features.patch and ACPI changes. xl trigger power is pushing the Xen one and the xenstore hvm-shutdown write is triggering the QEMU one. With forkIO, the `xl shutdown -F -ww` runs before the `xl trigger power` commands. xl shutdown first tries PV shutdown and then (-F) fallback to ACPI. So this would push the Xen ACPI button before the QEMU one in pushPowerButton. Signed-off-by: Jason Andryuk --- xenmgr/XenMgr/Connect/Xl.hs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/xenmgr/XenMgr/Connect/Xl.hs b/xenmgr/XenMgr/Connect/Xl.hs index 9ecdf37f..391f2a47 100644 --- a/xenmgr/XenMgr/Connect/Xl.hs +++ b/xenmgr/XenMgr/Connect/Xl.hs @@ -166,6 +166,22 @@ domainXsPath uuid = do "" -> return $ "/local/domain/unknown" _ -> return $ "/local/domain/" ++ domid +pushPowerButton :: Uuid -> Int -> IO () +pushPowerButton uuid count = do + domid <- getDomainId uuid + stubdomid <- getStubDomainID uuid + let xs_path = "/local/domain/" ++ stubdomid ++ "/device-model/" ++ domid + _pushPowerButton uuid domid xs_path 1 count + where + _pushPowerButton :: Uuid -> String -> String -> Int -> Int -> IO () + _pushPowerButton uuid domid xs_path i max = do + debug $ "push power button " ++ show uuid ++ " " ++ show i ++ " of " ++ show max + xsWrite (xs_path ++ "/hvm-shutdown") "poweroff" + system_ ("xl trigger " ++ domid ++ " power") + if i < max + then do threadDelay $ 10^6 + _pushPowerButton uuid domid xs_path ( i + 1 ) max + else return () --The following functions are all domain lifecycle operations, and self-explanatory @@ -190,8 +206,7 @@ shutdown uuid = Just g -> do exitCode <- system_ ("xl shutdown -ww " ++ domid) case exitCode of ExitSuccess -> return () - _ -> do xsWrite (xs_path ++ "/hvm-shutdown") "poweroff" - _ <- system_ ("xl trigger " ++ domid ++ " power") + _ -> do forkIO $ pushPowerButton uuid 3 _ <- system_ ("xl shutdown -F -ww " ++ domid) return () Nothing -> do system_ ("xl shutdown -c -ww " ++ domid)