qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v1 1/1] hvf: arm: Properly sync guest time on migration


From: Frank Yang
Subject: [PATCH v1 1/1] hvf: arm: Properly sync guest time on migration
Date: Wed, 2 Dec 2020 14:19:31 -0800


From downstream: https://android-review.googlesource.com/c/platform/external/qemu/+/1515002

Based on v3 of Alexander Graf's patches

20201202190408.2041-1-agraf@csgraf.de">https://patchew.org/QEMU/20201202190408.2041-1-agraf@csgraf.de

We need to adjust CNTVOFF_EL2 so that time doesnt warp.  Even though we
can set separate CNTVOFF_EL2 values per vCPU, it just is not worth the
require effort to do that accurately---with individual values, even if
they are a tiny bit off it can result in a lockup due to inconsistent
time differences between vCPUs. So just use a global approximate value
for now.

Not tested in upstream yet, but Android emulator snapshots work without
time warp now.

Signed-off-by: Lingfeng Yang <lfy@google.com>
---
 accel/hvf/hvf-cpus.c     |  3 +++
 include/sysemu/hvf_int.h |  4 ++++
 target/arm/hvf/hvf.c     | 43 +++++++++++++++++++++++++++++++++++++++-
 target/i386/hvf/hvf.c    |  4 ++++
 4 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c
index a981ccde70..484c7717f5 100644
--- a/accel/hvf/hvf-cpus.c
+++ b/accel/hvf/hvf-cpus.c
@@ -456,6 +456,9 @@ static int hvf_accel_init(MachineState *ms)
     hvf_state = s;
     memory_listener_register(&hvf_memory_listener, &address_space_memory);
     cpus_register_accel(&hvf_cpus);
+
+    hvf_arch_init(s);
+
     return 0;
 }
 
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
index 13adf6ea77..08830782c9 100644
--- a/include/sysemu/hvf_int.h
+++ b/include/sysemu/hvf_int.h
@@ -55,6 +55,9 @@ struct HVFState {
     hvf_slot slots[32];
     int num_slots;
 
+#if defined(__aarch64__)
+    uint64_t ticks;
+#endif
     hvf_vcpu_caps *hvf_caps;
 };
 extern HVFState *hvf_state;
@@ -73,5 +76,6 @@ void hvf_arch_vcpu_destroy(CPUState *cpu);
 int hvf_vcpu_exec(CPUState *cpu);
 hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
 void hvf_kick_vcpu_thread(CPUState *cpu);
+void hvf_arch_init(HVFState* s);
 
 #endif
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index 9442e2f232..37380c6c53 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -312,6 +312,10 @@ int hvf_put_registers(CPUState *cpu)
     uint64_t val;
     int i;
 
+    /* Sync up CNTVOFF_EL2 */
+    env->cp15.cntvoff_el2 = hvf_state->ticks;
+    hv_vcpu_set_vtimer_offset(cpu->hvf->fd, env->cp15.cntvoff_el2);
+
     for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) {
         val = *(uint64_t *)((void *)env + hvf_reg_match[i].offset);
         ret = hv_vcpu_set_reg(cpu->hvf->fd, hvf_reg_match[i].reg, val);
@@ -418,6 +422,8 @@ void hvf_arch_vcpu_destroy(CPUState *cpu)
 {
 }
 
+static HVFState* hvf_state = 0;
+
 int hvf_arch_init_vcpu(CPUState *cpu)
 {
     ARMCPU *arm_cpu = ARM_CPU(cpu);
@@ -795,7 +801,11 @@ int hvf_vcpu_exec(CPUState *cpu)
                                         &cval);
                 assert_hvf_ok(r);
 
-                int64_t ticks_to_sleep = cval - mach_absolute_time();
+                /* mach_absolute_time() is an absolute host tick number. We
+                 * have set up the guest to use the host tick number offset
+                 * by env->cp15.cntvoff_el2.
+                 */
+                int64_t ticks_to_sleep = cval - (mach_absolute_time() - env->cp15.cntvoff_el2);
                 if (ticks_to_sleep < 0) {
                     break;
                 }
@@ -855,3 +865,34 @@ int hvf_vcpu_exec(CPUState *cpu)
         }
     }
 }
+
+static int hvf_mig_state_pre_save(void* opaque) {
+    struct HVFState* s = opaque;
+    s->ticks -= mach_absolute_time();
+    return 0;
+}
+
+static int hvf_mig_state_post_load(void* opaque) {
+    struct HVFState* s = opaque;
+    m->ticks += mach_absolute_time();
+    return 0;
+}
+
+
+const VMStateDescription vmstate_hvf_migration = {
+    .name = "hvf-migration",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .pre_save = hvf_mig_state_pre_save,
+    .post_load = hvf_mig_state_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(ticks_to_save, HVFState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+void hvf_arch_init(HVFState* s) {
+    hvf_state = s;
+    hvf_state->ticks = 0;
+    vmstate_register(NULL, 0, &vmstate_hvf_migration, hvf_state);
+}
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 08b4adecd9..7ca6387620 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -557,3 +557,7 @@ int hvf_vcpu_exec(CPUState *cpu)
 
     return ret;
 }
+
+void hvf_arch_init(HVFState* s) {
+    (void)s;
+}
--
2.24.3 (Apple Git-128)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]