On 27/07/18 02:10, David Gibson wrote:
Right, I agree. Migrating shouldn't advance the time if we've already
explicitly stopped. But it's not really clear how to accomplish that
:/.
This topic is obviously of interest to me because it relates to various
discussions in the past relating to migrating guest timebases under TCG,
so below is my current understanding of what we are trying to achieve.
Using the following assumptions:
i) Sending host and receiving host have the same TB freq
ii) Sending host and receiving host have synchronised clocks
If we ignore any RTC issues for the moment (can we assume that the guest
will resync itself via NTP or similar on restart?) then it is possible
to model 2 separate scenarios:
1) Guest is stopped
In this case there is no timebase compensation required on the receiving
host. When restarted the guest will see the same timebase as at the
point in time in which it was stopped.
Sender:
When guest is stopped:
guestTB = sendHostTB + sendHostTBDiff
Receiver:
When guest moves to running state:
recvTBDiff = guestTB - recvHostTB
2) Guest is running
In this case the duration of the migration itself must be considered
when the guest starts executing on the receiver. Since the guest is
running the resulting guestTB is compensated for the time spent during
the migration phase itself.
Sender:
guestTB = sendHostTB + sendHostTBDiff
sendhostCLK = qemu_clock_get_ns(QEMU_CLOCK_REALTIME)
Receiver:
When guest moves to running state:
recvhostCLK = qemu_clock_get_ns(QEMU_CLOCK_REALTIME)
migrationTime = recvhostCLK - sendhostCLK
migrationTBDiff = migrationTime / recvHostTBFreq
recvTBDiff = guestTB + migrationTBDiff - recvHostTB
The VM running state should already be in the migration stream which
enables the receiving host to determine between scenarios 1 and 2, and
in fact they are equivalent if migrationTime is considered to be 0 in
scenario 1.
There is also the issue as to whether to allow migration between hosts
with different timebases; it should be possible to calculate the correct
recvTBDiff if sendTBFreq were included in the migration stream, but
could the guest OS detect this and change its behaviour accordingly?
Perhaps a solution here is to always have a separate field representing
the guestTB the last time the VM was stopped (stoppedGuestTB?) set via a
VM state change handler and include it in the migration stream?
The receiver knows whether the incoming guest is running or not, and so
can choose whether to use stoppedGuestTB (set at the last VM stop) or
guestTB (set during timebase_save) for its timebase calculations when
resuming the guest as required?
ATB,
Mark.