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)
>

Reply via email to