On 20.08.24 13:56, Peter Maydell wrote:
On Tue, 20 Aug 2024 at 12:40, David Hildenbrand <da...@redhat.com> wrote:
On 14.08.24 14:32, Juraj Marcin wrote:
On Tue, Aug 13, 2024 at 6:37 PM Peter Maydell <peter.mayd...@linaro.org> wrote:
On Tue, 13 Aug 2024 at 16:39, Juraj Marcin <jmar...@redhat.com> wrote:
Some devices need to distinguish cold start reset from waking up from a
suspended state. This patch adds new value to the enum, and updates the
i386 wakeup method to use this new reset type.
Signed-off-by: Juraj Marcin <jmar...@redhat.com>
Reviewed-by: David Hildenbrand <da...@redhat.com>
---
docs/devel/reset.rst | 8 ++++++++
hw/i386/pc.c | 2 +-
include/hw/resettable.h | 2 ++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
index 9746a4e8a0..a7c9467313 100644
--- a/docs/devel/reset.rst
+++ b/docs/devel/reset.rst
@@ -44,6 +44,14 @@ The Resettable interface handles reset types with an enum
``ResetType``:
value on each cold reset, such as RNG seed information, and which they
must not reinitialize on a snapshot-load reset.
+``RESET_TYPE_WAKEUP``
+ This type is called for a reset when the system is being woken-up from a
+ suspended state using the ``qemu_system_wakeup()`` function. If the machine
+ needs to reset its devices in its ``MachineClass::wakeup()`` method, this
+ reset type should be used, so devices can differentiate system wake-up from
+ other reset types. For example, a virtio-mem device must not unplug its
+ memory during wake-up as that would clear the guest RAM.
+
Devices which implement reset methods must treat any unknown ``ResetType``
as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
existing code we need to change if we add more types in future.
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ccb9731c91..49efd0a997 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1716,7 +1716,7 @@ static void pc_machine_reset(MachineState *machine,
ResetType type)
static void pc_machine_wakeup(MachineState *machine)
{
cpu_synchronize_all_states();
- pc_machine_reset(machine, RESET_TYPE_COLD);
+ pc_machine_reset(machine, RESET_TYPE_WAKEUP);
cpu_synchronize_all_post_reset();
}
I'm happy (following discussion in the previous thread)
that 'wakeup' is the right reset event to be using here.
But looking at the existing code for qemu_system_wakeup()
something seems odd here. qemu_system_wakeup() calls
the MachineClass::wakeup method if it's set, and does
nothing if it's not. The PC implementation of that calls
pc_machine_reset(), which does a qemu_devices_reset(),
which does a complete three-phase reset of the system.
But if the machine doesn't implement wakeup then we
never reset the system at all.
Shouldn't qemu_system_wakeup() do a qemu_devices_reset()
if there's no MachineClass::wakeup, in a similar way to
how qemu_system_reset() does a qemu_devices_reset()
if there's no MachineClass::reset method ? Having the
wakeup event be "sometimes this will do a RESET_TYPE_WAKEUP
but sometimes it won't" doesn't seem right to me...
One thing one could consider would probably be to send a WARM reset to
all devices. The main issue here is that other devices will default to a
COLD device then, and that's precisely what the other machines that
implement suspend+resume do not want. And ...
From my understanding that I have gathered from the code (but please,
someone correct me if I am wrong), this is machine specific. Some
machine types might not support suspend+wake-up at all. The support
has to be explicitly advertised through qemu_register_wakeup_support()
(for example, aarch64 with a generic virt machine type does not
advertise support). Even if the machine type advertises
suspend+wake-up support, it might not need to do anything machine
specific. This is the case of pSeries PowerPC machine (sPAPR) that
advertises support, but does not implement MachineClass::wakeup()
method as nothing needs to change in the machine state. [1]
So, if a restart during wake-up happens, it can be differentiated with
the wake-up reset type, and if the machine type does not need to reset
its devices during wake-up, there is no reset that needs to be
differentiated.
... if the machine does not do any resets during suspend+wakeup, this
implies that there is not even a warm reset.
I guess we should make that clearer in the documentation: it's up to a
machine implementation whether it wants to trigger a WARM reset during
suspend+wakeup. If not, not resets will be performed at all.
@Peter, does that sound reasonable?
Well, so far we've established that we need a "WAKEUP" reset
type, but not that we need a "WARM" reset type. The latter
Sorry, I meant "WAKEUP" ... :)
would be something we'd need to trigger for quite a lot of
reset-causes where we currently default to COLD reset, so
I don't think we should do that until we need it.
If suspend-and-wakeup really is supposed to be a reset event
on some machines but not on others, that sounds unhelpfully
nonstandard, but then hardware designers rarely make choices
to make our lives easier :-) And yes, we should make sure
that's clear in the documentation.
I think with adding new reset events it's going to be
important that we're clear about what they are (and in
particular what the triggering events that cause them
are) so that we have a solid guide for what it means.
The thing in particular I'm hoping to avoid here is that
we vaguely define, for example, a "warm" reset type and then
different parts of the system interpret "warm" in different
ways.
Okay, so we should make it clear that a WAKEUP reset may be used on
machines (especially x86) during a wakeup after suspending, when most of
the devices are supposed to just do the same as a COLD reset, and only
some of them (especially memory-layout/content related) need to preserve
their state. The primary reason of the WAKEUP event is for these devices
to handle these wakeups properly.
Then, we should document that some machines might not perform any reset
during a wakeup, which will result in no resets to be triggered at all.
--
Cheers,
David / dhildenb