2018-06-27 16:44:04 +03:00
|
|
|
/*
|
|
|
|
* TOD (Time Of Day) clock
|
|
|
|
*
|
|
|
|
* Copyright 2018 Red Hat, Inc.
|
|
|
|
* Author(s): David Hildenbrand <david@redhat.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef HW_S390_TOD_H
|
|
|
|
#define HW_S390_TOD_H
|
|
|
|
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-core.h"
|
2019-08-12 08:23:31 +03:00
|
|
|
#include "target/s390x/s390-tod.h"
|
2020-09-03 23:43:22 +03:00
|
|
|
#include "qom/object.h"
|
2018-06-27 16:44:04 +03:00
|
|
|
|
|
|
|
typedef struct S390TOD {
|
|
|
|
uint8_t high;
|
|
|
|
uint64_t low;
|
|
|
|
} S390TOD;
|
|
|
|
|
|
|
|
#define TYPE_S390_TOD "s390-tod"
|
2020-09-16 21:25:18 +03:00
|
|
|
OBJECT_DECLARE_TYPE(S390TODState, S390TODClass, S390_TOD)
|
2018-06-27 16:44:04 +03:00
|
|
|
#define TYPE_KVM_S390_TOD TYPE_S390_TOD "-kvm"
|
|
|
|
#define TYPE_QEMU_S390_TOD TYPE_S390_TOD "-qemu"
|
|
|
|
|
2020-09-03 23:43:22 +03:00
|
|
|
struct S390TODState {
|
2018-06-27 16:44:04 +03:00
|
|
|
/* private */
|
|
|
|
DeviceState parent_obj;
|
2018-06-27 16:44:06 +03:00
|
|
|
|
s390x/tod: Properly stop the KVM TOD while the guest is not running
Just like on other architectures, we should stop the clock while the guest
is not running. This is already properly done for TCG. Right now, doing an
offline migration (stop, migrate, cont) can easily trigger stalls in the
guest.
Even doing a
(hmp) stop
... wait 2 minutes ...
(hmp) cont
will already trigger stalls.
So whenever the guest stops, backup the KVM TOD. When continuing to run
the guest, restore the KVM TOD.
One special case is starting a simple VM: Reading the TOD from KVM to
stop it right away until the guest is actually started means that the
time of any simple VM will already differ to the host time. We can
simply leave the TOD running and the guest won't be able to recognize
it.
For migration, we actually want to keep the TOD stopped until really
starting the guest. To be able to catch most errors, we should however
try to set the TOD in addition to simply storing it. So we can still
catch basic migration problems.
If anything goes wrong while backing up/restoring the TOD, we have to
ignore it (but print a warning). This is then basically a fallback to
old behavior (TOD remains running).
I tested this very basically with an initrd:
1. Start a simple VM. Observed that the TOD is kept running. Old
behavior.
2. Ordinary live migration. Observed that the TOD is temporarily
stopped on the destination when setting the new value and
correctly started when finally starting the guest.
3. Offline live migration. (stop, migrate, cont). Observed that the
TOD will be stopped on the source with the "stop" command. On the
destination, the TOD is temporarily stopped when setting the new
value and correctly started when finally starting the guest via
"cont".
4. Simple stop/cont correctly stops/starts the TOD. (multiple stops
or conts in a row have no effect, so works as expected)
In the future, we might want to send the guest a special kind of time sync
interrupt under some conditions, so it can synchronize its tod to the
host tod. This is interesting for migration scenarios but also when we
get time sync interrupts ourselves. This however will most probably have
to be handled in KVM (e.g. when the tods differ too much) and is not
desired e.g. when debugging the guest (single stepping should not
result in permanent time syncs). I consider something like that an add-on
on top of this basic "don't break the guest" handling.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20181130094957.4121-1-david@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-11-30 12:49:57 +03:00
|
|
|
/*
|
|
|
|
* Used by TCG to remember the time base. Used by KVM to backup the TOD
|
|
|
|
* while the TOD is stopped.
|
|
|
|
*/
|
2018-06-27 16:44:06 +03:00
|
|
|
S390TOD base;
|
s390x/tod: Properly stop the KVM TOD while the guest is not running
Just like on other architectures, we should stop the clock while the guest
is not running. This is already properly done for TCG. Right now, doing an
offline migration (stop, migrate, cont) can easily trigger stalls in the
guest.
Even doing a
(hmp) stop
... wait 2 minutes ...
(hmp) cont
will already trigger stalls.
So whenever the guest stops, backup the KVM TOD. When continuing to run
the guest, restore the KVM TOD.
One special case is starting a simple VM: Reading the TOD from KVM to
stop it right away until the guest is actually started means that the
time of any simple VM will already differ to the host time. We can
simply leave the TOD running and the guest won't be able to recognize
it.
For migration, we actually want to keep the TOD stopped until really
starting the guest. To be able to catch most errors, we should however
try to set the TOD in addition to simply storing it. So we can still
catch basic migration problems.
If anything goes wrong while backing up/restoring the TOD, we have to
ignore it (but print a warning). This is then basically a fallback to
old behavior (TOD remains running).
I tested this very basically with an initrd:
1. Start a simple VM. Observed that the TOD is kept running. Old
behavior.
2. Ordinary live migration. Observed that the TOD is temporarily
stopped on the destination when setting the new value and
correctly started when finally starting the guest.
3. Offline live migration. (stop, migrate, cont). Observed that the
TOD will be stopped on the source with the "stop" command. On the
destination, the TOD is temporarily stopped when setting the new
value and correctly started when finally starting the guest via
"cont".
4. Simple stop/cont correctly stops/starts the TOD. (multiple stops
or conts in a row have no effect, so works as expected)
In the future, we might want to send the guest a special kind of time sync
interrupt under some conditions, so it can synchronize its tod to the
host tod. This is interesting for migration scenarios but also when we
get time sync interrupts ourselves. This however will most probably have
to be handled in KVM (e.g. when the tods differ too much) and is not
desired e.g. when debugging the guest (single stepping should not
result in permanent time syncs). I consider something like that an add-on
on top of this basic "don't break the guest" handling.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20181130094957.4121-1-david@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-11-30 12:49:57 +03:00
|
|
|
/* Used by KVM to remember if the TOD is stopped and base is valid. */
|
|
|
|
bool stopped;
|
2020-09-03 23:43:22 +03:00
|
|
|
};
|
2018-06-27 16:44:04 +03:00
|
|
|
|
2020-09-03 23:43:22 +03:00
|
|
|
struct S390TODClass {
|
2018-06-27 16:44:04 +03:00
|
|
|
/* private */
|
|
|
|
DeviceClass parent_class;
|
s390x/tod: Properly stop the KVM TOD while the guest is not running
Just like on other architectures, we should stop the clock while the guest
is not running. This is already properly done for TCG. Right now, doing an
offline migration (stop, migrate, cont) can easily trigger stalls in the
guest.
Even doing a
(hmp) stop
... wait 2 minutes ...
(hmp) cont
will already trigger stalls.
So whenever the guest stops, backup the KVM TOD. When continuing to run
the guest, restore the KVM TOD.
One special case is starting a simple VM: Reading the TOD from KVM to
stop it right away until the guest is actually started means that the
time of any simple VM will already differ to the host time. We can
simply leave the TOD running and the guest won't be able to recognize
it.
For migration, we actually want to keep the TOD stopped until really
starting the guest. To be able to catch most errors, we should however
try to set the TOD in addition to simply storing it. So we can still
catch basic migration problems.
If anything goes wrong while backing up/restoring the TOD, we have to
ignore it (but print a warning). This is then basically a fallback to
old behavior (TOD remains running).
I tested this very basically with an initrd:
1. Start a simple VM. Observed that the TOD is kept running. Old
behavior.
2. Ordinary live migration. Observed that the TOD is temporarily
stopped on the destination when setting the new value and
correctly started when finally starting the guest.
3. Offline live migration. (stop, migrate, cont). Observed that the
TOD will be stopped on the source with the "stop" command. On the
destination, the TOD is temporarily stopped when setting the new
value and correctly started when finally starting the guest via
"cont".
4. Simple stop/cont correctly stops/starts the TOD. (multiple stops
or conts in a row have no effect, so works as expected)
In the future, we might want to send the guest a special kind of time sync
interrupt under some conditions, so it can synchronize its tod to the
host tod. This is interesting for migration scenarios but also when we
get time sync interrupts ourselves. This however will most probably have
to be handled in KVM (e.g. when the tods differ too much) and is not
desired e.g. when debugging the guest (single stepping should not
result in permanent time syncs). I consider something like that an add-on
on top of this basic "don't break the guest" handling.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20181130094957.4121-1-david@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
2018-11-30 12:49:57 +03:00
|
|
|
void (*parent_realize)(DeviceState *dev, Error **errp);
|
2018-06-27 16:44:04 +03:00
|
|
|
|
|
|
|
/* public */
|
|
|
|
void (*get)(const S390TODState *td, S390TOD *tod, Error **errp);
|
|
|
|
void (*set)(S390TODState *td, const S390TOD *tod, Error **errp);
|
2020-09-03 23:43:22 +03:00
|
|
|
};
|
2018-06-27 16:44:04 +03:00
|
|
|
|
|
|
|
void s390_init_tod(void);
|
2018-06-27 16:44:06 +03:00
|
|
|
S390TODState *s390_get_todstate(void);
|
2018-06-27 16:44:04 +03:00
|
|
|
|
|
|
|
#endif
|