On Tue, 1 Aug 2023 13:00:02 -0400 "Annie.li" <annie...@oracle.com> wrote:
> Hi Igor, > > On 7/14/2023 10:04 AM, Igor Mammedov wrote: > > On Fri, 7 Jul 2023 13:43:36 -0400 > > "Annie.li" <annie...@oracle.com> wrote: > > > >> Hi Igor, > >> > >> Revisiting this thread and have more questions, please clarify, thank you! > >> > >> On 9/20/2021 3:53 AM, Igor Mammedov wrote: > >>> On Fri, 6 Aug 2021 16:18:09 -0400 > >>> "Annie.li" <annie...@oracle.com> wrote: > >>> > >>>> Hello Igor, > >>>> > >>>> This is an old patch, but it does what we need. > >>>> I am getting a little bit lost about not implementing fixed hardware > >>>> sleep button, can you please clarify? thank you! > >>>> > >>>> On 7/20/2017 10:59 AM, Igor Mammedov wrote: > >>>>> On Thu, 20 Jul 2017 11:31:26 +0200 > >>>>> Stefan Fritsch <s...@sfritsch.de> wrote: > >>>>> > >>>>>> From: Stefan Fritsch <stefan_frit...@genua.de> > >>>>>> > >>>>>> Add an ACPI sleep button and QMP/HMP commands to trigger it. A sleep > >>>>>> button is a so called "fixed hardware feature", which makes it more > >>>>>> suitable for putting the system to sleep than a laptop lid, for > >>>>>> example. > >>>>>> > >>>>>> The sleep button is disabled by default (Bit 5 in the FACP flags > >>>>>> register set and no button "device" present in SSDT/DSDT). Clearing > >>>>>> said > >>>>>> bit enables it as a fixed feature device. > >>>>> per spec sleep button is used for both putting system into > >>>>> sleep and for waking it up. > >>>>> > >>>>> Reusing system_wakeup 'button' to behave as per spec would > >>>>> make this patch significantly smaller. > >> Current 'system_wakeup' sets the WAK_STS bit and PWRBTN_STS to wake up > >> the system, the system_wakeup 'button' is the power button. So(Correct me > >> if I am wrong) reusing the system_wakeup 'button' means reusing the power > >> button for sleep. See the following code of setting WAK_STS and PWRBTN_STS > >> for 'system_wakeup', > >> case QEMU_WAKEUP_REASON_OTHER: > >> /* ACPI_BITMASK_WAKE_STATUS should be set on resume. > >> Pretend that resume was caused by power button */ > >> ar->pm1.evt.sts |= > >> (ACPI_BITMASK_WAKE_STATUS | > >> ACPI_BITMASK_POWER_BUTTON_STATUS); > > (that's quite ancient code (0bacd1300d) and I couldn't find a reason why > > power button was chosen. > > > > https://urldefense.com/v3/__https://www.mail-archive.com/kvm@vger.kernel.org/msg05742.html__;!!ACWV5N9M2RV99hQ!PQp9_UyWYc4gTuTwNUiyPgE0Xwinlsi8F-J6zWOA8KRLUh0EIv68g01XQQrFzKipeZbe-vhHfpGZBb0$ > > that was tested with WinXP so would be wise to check if SLEEP button > > works there. (though I'm not sure if we still care for XP being runnable on > > QEMU) > > ) > > don't have WinXP at hand to check for now... > Microsoft has ended the WinXP support since Apr 8, 2014. > If someone is still running WinXP, not sure if they care about > the sleep button. the only thing I care here is not regressing current state. I can test WnXP and RHEL6 for you > > > > it doesn't have to be ACPI_BITMASK_POWER_BUTTON_STATUS, > > you can convert it to sleep button by using > > ACPI_BITMASK_SLEEP_BUTTON_STATUS. > > However you'll have to enable sleep button (which is disabled currently) > > in FADT (ACPI_FADT_F_SLP_BUTTON), for guest to see the button. > Agree > Per ACPI spec, SLPBTN_STS - > > "This optional bit is set when the sleep button is pressed. In the system > working state, while SLPBTN_EN and SLPBTN_STS are both set, an > interrupt event is raised. In the sleep or soft-off states a wake event is > generated when the sleeping button is pressed and the SLPBTN_EN bit > is set." > > Using ACPI_BITMASK_SLEEP_BUTTON_STATUS means qemu ends up with > supporting the sleep button. With this, implementing the fixed > hardware sleep button(what this patch does) is one option. The interesting > topic is whether it should be implemented as General Control sleep button > or fixed hardware button. > > > > >> break; > >> > >> Per the ACPI spec, the power button can be used in single button model, > >> i.e. > >> it can be used to either shut down the system or put the system into sleep. > >> However, this depends on the software policy and user's setting of the > >> system. > >> Sleep/shutdown can not be done through the power button in the same > >> scenario. > >> If the system has configured pressing the power button to put the system > >> into sleep, > >> system_sleep will put the system into sleep state through the power > >> button, as well > >> as system_powerdown. Pressing the power button will not shut down the > >> system. > >> In this case, system_powerdown has its own issue, but this is different > >> story and > >> let's just focus on things related to system_sleep here. > > regardless of what button is used OSPM is free to enable or disable it > > using FOO_EN bits. > > Nod > The system_powerdown issue I mentioned above is - > If the guest is configured to go into sleep when the power button is > pressed, system_powerdown will trigger the guest to go into sleep state. > However, system_wakeup won't be able to wake up the guest in such case. > Looks the current qemu doesn't handle this scenario properly. > >>>> About reusing "system_wakeup", does it mean the following? > >>>> > >>>> 1. when guest is in sleep state, "system_wakeup" wakes up the guest > >>>> 2. when guest is running, "system_wakeup" puts the guest into sleep > >>> yes, it could be something like this > >>> > >>> > >>>> "system_wakeup" sets WAK_STS and then system transitions to the > >>>> working state. Correspondingly, I suppose both SLPBTN_STS and > >>>> SLPBTN_EN need to be set for sleeping, and this is what fixed > >>>> hardware sleep button requires? > >>> yep > >>> > >>>> I have combined the sleep and wakeup together, share the > >>>> code between. But Xen also registers the wakeup notifier, and > >>>> this makes things more complicated if this notifier is shared > >>>> between sleep and wakeup. Or this is my misunderstanding? > >>>> please correct me if I am wrong. > >>> you'd have to fixup xen notifier to handle that > >>> > >>>>> If you like idea of separate command/button better, then > >>>>> I'd go generic control sleep button way instead of fixed > >>>>> hardware, it would allow us to reuse most of the code in > >>>>> ARM target, plus I'd avoid notifiers and use acpi device > >>>>> lookup instead (see: qmp_query_acpi_ospm_status as example) > > > >> Implementing the generic control sleep button for x86 does align > >> to the generic control power button implementation in ARM, but > >> it doesn't align to the current fixed hardware power button for x86. > >> Should sleep button be implemented as generic control sleep button > >> to reuse code in ARM or fixed hardware button to align to the fixed > >> power button for x86? > > sleep control button device was present in ACPI 1.0b so it might be > > supported by x86 as well (one just need to test it with ancient OS > > to find out if it were implemented. (WinXP,Vista,some ancient linux...)) > > If qemu needs to cover the ancient OS, isn't the fixed sleep hardware > button more appropriate? As long as using control method approach doesn't break anything it should be fine. > How about qemu uses fixed sleep button for x86(just like what this > patch does), and share the sleep button for between wake-up and sleep? Fixed HW button is not supported on HW reduced platforms (arm/virt, microvm), so I'd try control method way 1st (so it could be reused there as well) and only if that doesn't work out would fallback to fixed hw approach. PS: only instead of introducing new system_sleep, I'd suggest to reuse existing system_wakeup. > The power button has been implemented as fixed hardware button for x86. > Thanks > Annie > > >>>>> > >>>> Do you mean the "Control Method Sleep Button" that needs to > >>>> notify OSPM by event indication 0x80? > >>> yes, in addition to virt-arm machine it could be reused by > >>> microvm which also uses 'reduced hardware' acpi model > >>> (i.e. it lacks fixed hardware registers like virt-arm does) > >>> > >>> maybe while adding button to pc/q35 you can look into adding > >>> it to microvm and virt-arm at the same time (should be trivial > >>> on top of pc/q35 support). > >>> > >>>> Thanks > >>>> Annie > >>>>>> Signed-off-by: Stefan Fritsch <stefan_frit...@genua.de> > >>>>>> --- > >>>>>> hmp-commands.hx | 16 ++++++++++++++++ > >>>>>> hmp.c | 5 +++++ > >>>>>> hmp.h | 1 + > >>>>>> hw/acpi/core.c | 8 ++++++++ > >>>>>> hw/acpi/ich9.c | 10 ++++++++++ > >>>>>> hw/acpi/piix4.c | 12 ++++++++++++ > >>>>>> hw/i386/acpi-build.c | 1 - > >>>>>> include/hw/acpi/acpi.h | 2 ++ > >>>>>> include/hw/acpi/ich9.h | 1 + > >>>>>> include/sysemu/sysemu.h | 2 ++ > >>>>>> qapi-schema.json | 12 ++++++++++++ > >>>>>> qmp.c | 5 +++++ > >>>>>> tests/test-hmp.c | 1 + > >>>>>> vl.c | 29 +++++++++++++++++++++++++++++ > >>>>>> 14 files changed, 104 insertions(+), 1 deletion(-) > >>>>>> > >>>>>> diff --git a/hmp-commands.hx b/hmp-commands.hx > >>>>>> index 1941e19932..8ba4380883 100644 > >>>>>> --- a/hmp-commands.hx > >>>>>> +++ b/hmp-commands.hx > >>>>>> @@ -638,6 +638,22 @@ Reset the system. > >>>>>> ETEXI > >>>>>> > >>>>>> { > >>>>>> + .name = "system_sleep", > >>>>>> + .args_type = "", > >>>>>> + .params = "", > >>>>>> + .help = "send ACPI sleep event", > >>>>>> + .cmd = hmp_system_sleep, > >>>>>> + }, > >>>>>> + > >>>>>> +STEXI > >>>>>> +@item system_sleep > >>>>>> +@findex system_sleep > >>>>>> + > >>>>>> +Push the virtual sleep button; if supported the system will enter > >>>>>> +an ACPI sleep state. > >>>>>> +ETEXI > >>>>>> + > >>>>>> + { > >>>>>> .name = "system_powerdown", > >>>>>> .args_type = "", > >>>>>> .params = "", > >>>>>> diff --git a/hmp.c b/hmp.c > >>>>>> index bf1de747d5..b4b584016c 100644 > >>>>>> --- a/hmp.c > >>>>>> +++ b/hmp.c > >>>>>> @@ -1047,6 +1047,11 @@ void hmp_system_reset(Monitor *mon, const QDict > >>>>>> *qdict) > >>>>>> qmp_system_reset(NULL); > >>>>>> } > >>>>>> > >>>>>> +void hmp_system_sleep(Monitor *mon, const QDict *qdict) > >>>>>> +{ > >>>>>> + qmp_system_sleep(NULL); > >>>>>> +} > >>>>>> + > >>>>>> void hmp_system_powerdown(Monitor *mon, const QDict *qdict) > >>>>>> { > >>>>>> qmp_system_powerdown(NULL); > >>>>>> diff --git a/hmp.h b/hmp.h > >>>>>> index 1ff455295e..15b53de9ed 100644 > >>>>>> --- a/hmp.h > >>>>>> +++ b/hmp.h > >>>>>> @@ -45,6 +45,7 @@ void hmp_info_iothreads(Monitor *mon, const QDict > >>>>>> *qdict); > >>>>>> void hmp_quit(Monitor *mon, const QDict *qdict); > >>>>>> void hmp_stop(Monitor *mon, const QDict *qdict); > >>>>>> void hmp_system_reset(Monitor *mon, const QDict *qdict); > >>>>>> +void hmp_system_sleep(Monitor *mon, const QDict *qdict); > >>>>>> void hmp_system_powerdown(Monitor *mon, const QDict *qdict); > >>>>>> void hmp_cpu(Monitor *mon, const QDict *qdict); > >>>>>> void hmp_memsave(Monitor *mon, const QDict *qdict); > >>>>>> diff --git a/hw/acpi/core.c b/hw/acpi/core.c > >>>>>> index 95fcac95a2..2ee64b6878 100644 > >>>>>> --- a/hw/acpi/core.c > >>>>>> +++ b/hw/acpi/core.c > >>>>>> @@ -422,6 +422,14 @@ void acpi_pm1_evt_power_down(ACPIREGS *ar) > >>>>>> } > >>>>>> } > >>>>>> > >>>>>> +void acpi_pm1_evt_sleep(ACPIREGS *ar) > >>>>>> +{ > >>>>>> + if (ar->pm1.evt.en & ACPI_BITMASK_SLEEP_BUTTON_ENABLE) { > >>>>>> + ar->pm1.evt.sts |= ACPI_BITMASK_SLEEP_BUTTON_STATUS; > >>>>>> + ar->tmr.update_sci(ar); > >>>>>> + } > >>>>>> +} > >>>>>> + > >>>>>> void acpi_pm1_evt_reset(ACPIREGS *ar) > >>>>>> { > >>>>>> ar->pm1.evt.sts = 0; > >>>>>> diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c > >>>>>> index c5d8646abc..3faeab4d2e 100644 > >>>>>> --- a/hw/acpi/ich9.c > >>>>>> +++ b/hw/acpi/ich9.c > >>>>>> @@ -260,6 +260,14 @@ static void pm_reset(void *opaque) > >>>>>> acpi_update_sci(&pm->acpi_regs, pm->irq); > >>>>>> } > >>>>>> > >>>>>> +static void pm_sleep_req(Notifier *n, void *opaque) > >>>>>> +{ > >>>>>> + ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, > >>>>>> sleep_notifier); > >>>>>> + > >>>>>> + acpi_pm1_evt_sleep(&pm->acpi_regs); > >>>>>> +} > >>>>>> + > >>>>>> + > >>>>>> static void pm_powerdown_req(Notifier *n, void *opaque) > >>>>>> { > >>>>>> ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, > >>>>>> powerdown_notifier); > >>>>>> @@ -299,6 +307,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, > >>>>>> ICH9LPCPMRegs *pm, > >>>>>> qemu_register_reset(pm_reset, pm); > >>>>>> pm->powerdown_notifier.notify = pm_powerdown_req; > >>>>>> qemu_register_powerdown_notifier(&pm->powerdown_notifier); > >>>>>> + pm->sleep_notifier.notify = pm_sleep_req; > >>>>>> + qemu_register_sleep_notifier(&pm->sleep_notifier); > >>>>>> > >>>>>> legacy_acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), > >>>>>> OBJECT(lpc_pci), &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE); > >>>>>> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c > >>>>>> index f276967365..15e20976c3 100644 > >>>>>> --- a/hw/acpi/piix4.c > >>>>>> +++ b/hw/acpi/piix4.c > >>>>>> @@ -79,6 +79,7 @@ typedef struct PIIX4PMState { > >>>>>> int smm_enabled; > >>>>>> Notifier machine_ready; > >>>>>> Notifier powerdown_notifier; > >>>>>> + Notifier sleep_notifier; > >>>>>> > >>>>>> AcpiPciHpState acpi_pci_hotplug; > >>>>>> bool use_acpi_pci_hotplug; > >>>>>> @@ -371,6 +372,15 @@ static void piix4_pm_powerdown_req(Notifier *n, > >>>>>> void *opaque) > >>>>>> acpi_pm1_evt_power_down(&s->ar); > >>>>>> } > >>>>>> > >>>>>> +static void piix4_pm_sleep_req(Notifier *n, void *opaque) > >>>>>> +{ > >>>>>> + PIIX4PMState *s = container_of(n, PIIX4PMState, sleep_notifier); > >>>>>> + > >>>>>> + assert(s != NULL); > >>>>>> + acpi_pm1_evt_sleep(&s->ar); > >>>>>> +} > >>>>>> + > >>>>>> + > >>>>>> static void piix4_device_plug_cb(HotplugHandler *hotplug_dev, > >>>>>> DeviceState *dev, Error **errp) > >>>>>> { > >>>>>> @@ -535,6 +545,8 @@ static void piix4_pm_realize(PCIDevice *dev, Error > >>>>>> **errp) > >>>>>> > >>>>>> s->powerdown_notifier.notify = piix4_pm_powerdown_req; > >>>>>> qemu_register_powerdown_notifier(&s->powerdown_notifier); > >>>>>> + s->sleep_notifier.notify = piix4_pm_sleep_req; > >>>>>> + qemu_register_sleep_notifier(&s->sleep_notifier); > >>>>>> > >>>>>> s->machine_ready.notify = piix4_pm_machine_ready; > >>>>>> qemu_add_machine_init_done_notifier(&s->machine_ready); > >>>>>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > >>>>>> index 6b7bade183..06b28dacfe 100644 > >>>>>> --- a/hw/i386/acpi-build.c > >>>>>> +++ b/hw/i386/acpi-build.c > >>>>>> @@ -294,7 +294,6 @@ static void fadt_setup(AcpiFadtDescriptorRev3 > >>>>>> *fadt, AcpiPmInfo *pm) > >>>>>> fadt->plvl3_lat = cpu_to_le16(0xfff); /* C3 state not > >>>>>> supported */ > >>>>>> fadt->flags = cpu_to_le32((1 << ACPI_FADT_F_WBINVD) | > >>>>>> (1 << ACPI_FADT_F_PROC_C1) | > >>>>>> - (1 << ACPI_FADT_F_SLP_BUTTON) | > >>>>>> (1 << ACPI_FADT_F_RTC_S4)); > >>>>>> fadt->flags |= cpu_to_le32(1 << > >>>>>> ACPI_FADT_F_USE_PLATFORM_CLOCK); > >>>>>> /* APIC destination mode ("Flat Logical") has an upper limit > >>>>>> of 8 CPUs > >>>>>> diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h > >>>>>> index 7b3d93cf0d..51cf901ef6 100644 > >>>>>> --- a/include/hw/acpi/acpi.h > >>>>>> +++ b/include/hw/acpi/acpi.h > >>>>>> @@ -78,6 +78,7 @@ > >>>>>> #define ACPI_BITMASK_PM1_COMMON_ENABLED ( \ > >>>>>> ACPI_BITMASK_RT_CLOCK_ENABLE | \ > >>>>>> ACPI_BITMASK_POWER_BUTTON_ENABLE | \ > >>>>>> + ACPI_BITMASK_SLEEP_BUTTON_ENABLE | \ > >>>>>> ACPI_BITMASK_GLOBAL_LOCK_ENABLE | \ > >>>>>> ACPI_BITMASK_TIMER_ENABLE) > >>>>>> > >>>>>> @@ -148,6 +149,7 @@ void acpi_pm_tmr_reset(ACPIREGS *ar); > >>>>>> /* PM1a_EVT: piix and ich9 don't implement PM1b. */ > >>>>>> uint16_t acpi_pm1_evt_get_sts(ACPIREGS *ar); > >>>>>> void acpi_pm1_evt_power_down(ACPIREGS *ar); > >>>>>> +void acpi_pm1_evt_sleep(ACPIREGS *ar); > >>>>>> void acpi_pm1_evt_reset(ACPIREGS *ar); > >>>>>> void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, > >>>>>> MemoryRegion *parent); > >>>>>> diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h > >>>>>> index a352c94fde..2073eec168 100644 > >>>>>> --- a/include/hw/acpi/ich9.h > >>>>>> +++ b/include/hw/acpi/ich9.h > >>>>>> @@ -48,6 +48,7 @@ typedef struct ICH9LPCPMRegs { > >>>>>> > >>>>>> uint32_t pm_io_base; > >>>>>> Notifier powerdown_notifier; > >>>>>> + Notifier sleep_notifier; > >>>>>> > >>>>>> bool cpu_hotplug_legacy; > >>>>>> AcpiCpuHotplug gpe_cpu; > >>>>>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h > >>>>>> index b21369672a..00f54653dc 100644 > >>>>>> --- a/include/sysemu/sysemu.h > >>>>>> +++ b/include/sysemu/sysemu.h > >>>>>> @@ -75,6 +75,8 @@ void qemu_register_wakeup_notifier(Notifier > >>>>>> *notifier); > >>>>>> void qemu_system_shutdown_request(ShutdownCause reason); > >>>>>> void qemu_system_powerdown_request(void); > >>>>>> void qemu_register_powerdown_notifier(Notifier *notifier); > >>>>>> +void qemu_system_sleep_request(void); > >>>>>> +void qemu_register_sleep_notifier(Notifier *notifier); > >>>>>> void qemu_system_debug_request(void); > >>>>>> void qemu_system_vmstop_request(RunState reason); > >>>>>> void qemu_system_vmstop_request_prepare(void); > >>>>>> diff --git a/qapi-schema.json b/qapi-schema.json > >>>>>> index 8b015bee2e..c6ccfcd70f 100644 > >>>>>> --- a/qapi-schema.json > >>>>>> +++ b/qapi-schema.json > >>>>>> @@ -2314,6 +2314,18 @@ > >>>>>> { 'command': 'system_reset' } > >>>>>> > >>>>>> ## > >>>>>> +# @system_sleep: > >>>>>> +# > >>>>>> +# Requests that a guest perform a ACPI sleep transition by pushing a > >>>>>> virtual > >>>>>> +# sleep button. > >>>>>> +# > >>>>>> +# Notes: A guest may or may not respond to this command. This command > >>>>>> +# returning does not indicate that a guest has accepted the > >>>>>> request or > >>>>>> +# that it has gone to sleep. > >>>>>> +## > >>>>>> +{ 'command': 'system_sleep' } > >>>>>> + > >>>>>> +## > >>>>>> # @system_powerdown: > >>>>>> # > >>>>>> # Requests that a guest perform a powerdown operation. > >>>>>> diff --git a/qmp.c b/qmp.c > >>>>>> index b86201e349..bc1f2e3d7f 100644 > >>>>>> --- a/qmp.c > >>>>>> +++ b/qmp.c > >>>>>> @@ -108,6 +108,11 @@ void qmp_system_reset(Error **errp) > >>>>>> qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP); > >>>>>> } > >>>>>> > >>>>>> +void qmp_system_sleep(Error **erp) > >>>>>> +{ > >>>>>> + qemu_system_sleep_request(); > >>>>>> +} > >>>>>> + > >>>>>> void qmp_system_powerdown(Error **erp) > >>>>>> { > >>>>>> qemu_system_powerdown_request(); > >>>>>> diff --git a/tests/test-hmp.c b/tests/test-hmp.c > >>>>>> index d77b3c8710..3fa850bf1e 100644 > >>>>>> --- a/tests/test-hmp.c > >>>>>> +++ b/tests/test-hmp.c > >>>>>> @@ -67,6 +67,7 @@ static const char *hmp_cmds[] = { > >>>>>> "sum 0 512", > >>>>>> "x /8i 0x100", > >>>>>> "xp /16x 0", > >>>>>> + "system_sleep", > >>>>>> NULL > >>>>>> }; > >>>>>> > >>>>>> diff --git a/vl.c b/vl.c > >>>>>> index fb6b2efafa..6a0f847dcf 100644 > >>>>>> --- a/vl.c > >>>>>> +++ b/vl.c > >>>>>> @@ -1608,6 +1608,7 @@ static ShutdownCause reset_requested; > >>>>>> static ShutdownCause shutdown_requested; > >>>>>> static int shutdown_signal; > >>>>>> static pid_t shutdown_pid; > >>>>>> +static int sleep_requested; > >>>>>> static int powerdown_requested; > >>>>>> static int debug_requested; > >>>>>> static int suspend_requested; > >>>>>> @@ -1618,6 +1619,8 @@ static NotifierList suspend_notifiers = > >>>>>> NOTIFIER_LIST_INITIALIZER(suspend_notifiers); > >>>>>> static NotifierList wakeup_notifiers = > >>>>>> NOTIFIER_LIST_INITIALIZER(wakeup_notifiers); > >>>>>> +static NotifierList sleep_notifiers = > >>>>>> + NOTIFIER_LIST_INITIALIZER(sleep_notifiers); > >>>>>> static uint32_t wakeup_reason_mask = ~(1 << > >>>>>> QEMU_WAKEUP_REASON_NONE); > >>>>>> > >>>>>> ShutdownCause qemu_shutdown_requested_get(void) > >>>>>> @@ -1838,6 +1841,24 @@ static void qemu_system_powerdown(void) > >>>>>> notifier_list_notify(&powerdown_notifiers, NULL); > >>>>>> } > >>>>>> > >>>>>> +static void qemu_system_sleep(void) > >>>>>> +{ > >>>>>> + notifier_list_notify(&sleep_notifiers, NULL); > >>>>>> +} > >>>>>> + > >>>>>> +static int qemu_sleep_requested(void) > >>>>>> +{ > >>>>>> + int r = sleep_requested; > >>>>>> + sleep_requested = 0; > >>>>>> + return r; > >>>>>> +} > >>>>>> + > >>>>>> +void qemu_system_sleep_request(void) > >>>>>> +{ > >>>>>> + sleep_requested = 1; > >>>>>> + qemu_notify_event(); > >>>>>> +} > >>>>>> + > >>>>>> void qemu_system_powerdown_request(void) > >>>>>> { > >>>>>> trace_qemu_system_powerdown_request(); > >>>>>> @@ -1850,6 +1871,11 @@ void qemu_register_powerdown_notifier(Notifier > >>>>>> *notifier) > >>>>>> notifier_list_add(&powerdown_notifiers, notifier); > >>>>>> } > >>>>>> > >>>>>> +void qemu_register_sleep_notifier(Notifier *notifier) > >>>>>> +{ > >>>>>> + notifier_list_add(&sleep_notifiers, notifier); > >>>>>> +} > >>>>>> + > >>>>>> void qemu_system_debug_request(void) > >>>>>> { > >>>>>> debug_requested = 1; > >>>>>> @@ -1899,6 +1925,9 @@ static bool main_loop_should_exit(void) > >>>>>> if (qemu_powerdown_requested()) { > >>>>>> qemu_system_powerdown(); > >>>>>> } > >>>>>> + if (qemu_sleep_requested()) { > >>>>>> + qemu_system_sleep(); > >>>>>> + } > >>>>>> if (qemu_vmstop_requested(&r)) { > >>>>>> vm_stop(r); > >>>>>> } > >>> >