From patchwork Tue Feb 14 14:49:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 141113 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A099AB6FCA for ; Wed, 15 Feb 2012 01:49:46 +1100 (EST) Received: from localhost ([::1]:47122 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RxJhQ-0006LJ-Mz for incoming@patchwork.ozlabs.org; Tue, 14 Feb 2012 09:49:44 -0500 Received: from eggs.gnu.org ([140.186.70.92]:49590) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RxJhH-0006LD-5f for qemu-devel@nongnu.org; Tue, 14 Feb 2012 09:49:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RxJhB-0007P7-46 for qemu-devel@nongnu.org; Tue, 14 Feb 2012 09:49:35 -0500 Received: from mx1.redhat.com ([209.132.183.28]:64699) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RxJhA-0007Os-TM for qemu-devel@nongnu.org; Tue, 14 Feb 2012 09:49:29 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1EEnRDn020989 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 14 Feb 2012 09:49:27 -0500 Received: from rincewind.home.kraxel.org (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q1EEnH6h011879; Tue, 14 Feb 2012 09:49:21 -0500 Message-ID: <4F3A7469.3080604@redhat.com> Date: Tue, 14 Feb 2012 15:49:13 +0100 From: Gerd Hoffmann User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.26) Gecko/20120130 Red Hat/3.1.18-1.el6_2 Thunderbird/3.1.18 MIME-Version: 1.0 To: Gleb Natapov References: <1328807143-29499-1-git-send-email-kraxel@redhat.com> <1328807143-29499-6-git-send-email-kraxel@redhat.com> <20120213092123.GV18866@redhat.com> <4F3A18DA.4070405@redhat.com> <20120214083753.GZ18866@redhat.com> <4F3A21DD.2090601@redhat.com> <20120214090827.GB18866@redhat.com> In-Reply-To: <20120214090827.GB18866@redhat.com> X-Enigmail-Version: 1.1.2 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org Subject: Re: [Qemu-devel] [PATCH v4 05/11] suspend: add infrastructure X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Hi, >> I see. I've expeced the the guest os putting them into a hlt loop or >> some simliar idle state. Play save and expliticly pausing them all is >> certainly good from a robustness perspective. > Yes. We should not trust a guest to do the "right thing". Updated patch attached. >>> I think it is also important to reset all device >>> immediately to ensure that no device will do DMA into main memory after >>> suspend. >> >> Didn't investigate yet, but I suspect this could break wakeup from pci >> devices (nic, usb-tablet via uhci) ... > > Yes. Can't say I fully understand how this works on real HW. I know > that there are separate "power planes" for different system sates > (this is defined in ACPI spec). So in S3 some devices (or even part of > a device?) may be powered down, but others still have power. Not sure > we should dive into emulating that in this patch series. We'll do that later, one step at a time. cheers, Gerd From fa91a3c496e1a3795622b91079dd588d38fe59b4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 11 Jan 2012 13:09:38 +0100 Subject: [PATCH] suspend: add infrastructure This patch adds some infrastructure to handle suspend and resume to qemu. First there are two functions to switch state and second there is a suspend notifier: * qemu_system_suspend_request is supposed to be called when the guest asks for being be suspended, for example via ACPI. * qemu_system_wakeup_request is supposed to be called on events which should wake up the guest. * qemu_register_suspend_notifier can be used to register a notifier which will be called when the guest is suspended. Machine types and device models can hook in there to modify state if needed. * qemu_register_wakeup_notifier can be used to register a notifier which will be called when the guest is woken up. Machine types and device models can hook in there to modify state if needed. * qemu_system_wakeup_enable can be used to enable/disable wakeup events. Signed-off-by: Gerd Hoffmann --- sysemu.h | 9 ++++++++ vl.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 0 deletions(-) diff --git a/sysemu.h b/sysemu.h index 9d5ce33..af73813 100644 --- a/sysemu.h +++ b/sysemu.h @@ -38,7 +38,16 @@ void vm_start(void); void vm_stop(RunState state); void vm_stop_force_state(RunState state); +typedef enum WakeupReason { + QEMU_WAKEUP_REASON_OTHER = 0, +} WakeupReason; + void qemu_system_reset_request(void); +void qemu_system_suspend_request(void); +void qemu_register_suspend_notifier(Notifier *notifier); +void qemu_system_wakeup_request(WakeupReason reason); +void qemu_system_wakeup_enable(WakeupReason reason, bool enabled); +void qemu_register_wakeup_notifier(Notifier *notifier); void qemu_system_shutdown_request(void); void qemu_system_powerdown_request(void); void qemu_system_debug_request(void); diff --git a/vl.c b/vl.c index 63dd725..bfdcb7c 100644 --- a/vl.c +++ b/vl.c @@ -1283,6 +1283,13 @@ static int shutdown_requested, shutdown_signal = -1; static pid_t shutdown_pid; static int powerdown_requested; static int debug_requested; +static int suspend_requested; +static bool is_suspended; +static NotifierList suspend_notifiers = + NOTIFIER_LIST_INITIALIZER(suspend_notifiers); +static NotifierList wakeup_notifiers = + NOTIFIER_LIST_INITIALIZER(wakeup_notifiers); +static uint32_t wakeup_reason_mask = ~0; static RunState vmstop_requested = RUN_STATE_MAX; int qemu_shutdown_requested_get(void) @@ -1325,6 +1332,13 @@ int qemu_reset_requested(void) return r; } +static int qemu_suspend_requested(void) +{ + int r = suspend_requested; + suspend_requested = 0; + return r; +} + int qemu_powerdown_requested(void) { int r = powerdown_requested; @@ -1398,6 +1412,56 @@ void qemu_system_reset_request(void) qemu_notify_event(); } +static void qemu_system_suspend(void) +{ + pause_all_vcpus(); + notifier_list_notify(&suspend_notifiers, NULL); + is_suspended = true; +} + +void qemu_system_suspend_request(void) +{ + if (is_suspended) { + return; + } + suspend_requested = 1; + cpu_stop_current(); + qemu_notify_event(); +} + +void qemu_register_suspend_notifier(Notifier *notifier) +{ + notifier_list_add(&suspend_notifiers, notifier); +} + +void qemu_system_wakeup_request(WakeupReason reason) +{ + if (!is_suspended) { + return; + } + if (!(wakeup_reason_mask & (1 << reason))) { + return; + } + notifier_list_notify(&wakeup_notifiers, &reason); + reset_requested = 1; + qemu_notify_event(); + is_suspended = false; +} + +void qemu_system_wakeup_enable(WakeupReason reason, bool enabled) +{ + if (enabled) { + wakeup_reason_mask |= (1 << reason); + } else { + wakeup_reason_mask &= ~(1 << reason); + } +} + +void qemu_register_wakeup_notifier(Notifier *notifier) +{ + notifier_list_add(&wakeup_notifiers, notifier); +} + void qemu_system_killed(int signal, pid_t pid) { shutdown_signal = signal; @@ -1438,6 +1502,9 @@ static bool main_loop_should_exit(void) if (qemu_debug_requested()) { vm_stop(RUN_STATE_DEBUG); } + if (qemu_suspend_requested()) { + qemu_system_suspend(); + } if (qemu_shutdown_requested()) { qemu_kill_report(); monitor_protocol_event(QEVENT_SHUTDOWN, NULL);