We've gotten the Android Emulator snapshots working again on M1 and noticed a time warp issue where the stopwatch app would, on a snapshot load, resume including the time the emulator wasn't running. This seems to fix it. Now we have snapshots mostly working (though file backed ram is a bit busted, still working on that)
On Wed, Dec 2, 2020 at 2:19 PM Frank Yang <l...@google.com> wrote: > > From downstream: > https://android-review.googlesource.com/c/platform/external/qemu/+/1515002 > > Based on v3 of Alexander Graf's patches > > https://patchew.org/QEMU/20201202190408.2041-1-ag...@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 <l...@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) >