qemu-arm
[Top][All Lists]
Advanced

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

Re: [PATCH v12 04/10] hvf: Add Apple Silicon support


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH v12 04/10] hvf: Add Apple Silicon support
Date: Thu, 30 Nov 2023 15:17:30 +0100
User-agent: Mozilla Thunderbird

Hi,

On 16/9/21 17:53, Alexander Graf wrote:
With Apple Silicon available to the masses, it's a good time to add support
for driving its virtualization extensions from QEMU.

This patch adds all necessary architecture specific code to get basic VMs
working, including save/restore.

Known limitations:

   - WFI handling is missing (follows in later patch)
   - No watchpoint/breakpoint support

Signed-off-by: Alexander Graf <agraf@csgraf.de>
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>


---
  MAINTAINERS                 |   5 +
  accel/hvf/hvf-accel-ops.c   |   9 +
  include/sysemu/hvf_int.h    |  10 +-
  meson.build                 |   1 +
  target/arm/hvf/hvf.c        | 794 ++++++++++++++++++++++++++++++++++++
  target/arm/hvf/trace-events |  10 +
  target/i386/hvf/hvf.c       |   5 +
  7 files changed, 833 insertions(+), 1 deletion(-)
  create mode 100644 target/arm/hvf/hvf.c
  create mode 100644 target/arm/hvf/trace-events


+int hvf_arch_init_vcpu(CPUState *cpu)
+{
+    ARMCPU *arm_cpu = ARM_CPU(cpu);
+    CPUARMState *env = &arm_cpu->env;
+    uint32_t sregs_match_len = ARRAY_SIZE(hvf_sreg_match);
+    uint32_t sregs_cnt = 0;
+    uint64_t pfr;
+    hv_return_t ret;
+    int i;
+
+    env->aarch64 = 1;
+    asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz));
+
+    /* Allocate enough space for our sysreg sync */
+    arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes,
+                                     sregs_match_len);
+    arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values,
+                                    sregs_match_len);
+    arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t,
+                                             arm_cpu->cpreg_vmstate_indexes,
+                                             sregs_match_len);
+    arm_cpu->cpreg_vmstate_values = g_renew(uint64_t,
+                                            arm_cpu->cpreg_vmstate_values,
+                                            sregs_match_len);
+
+    memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t));
+
+    /* Populate cp list for all known sysregs */
+    for (i = 0; i < sregs_match_len; i++) {
+        const ARMCPRegInfo *ri;
+        uint32_t key = hvf_sreg_match[i].key;
+
+        ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key);
+        if (ri) {
+            assert(!(ri->type & ARM_CP_NO_RAW));
+            hvf_sreg_match[i].cp_idx = sregs_cnt;
+            arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key);

So this hash ...:

    /*
     * Convert a truncated 32 bit hashtable key into the full
     * 64 bit KVM register ID.
     */
    static uint64_t cpreg_to_kvm_id(uint32_t cpregid)
    {
        uint64_t kvmid;

        if (cpregid & CP_REG_AA64_MASK) {
            kvmid = cpregid & ~CP_REG_AA64_MASK;
            kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM64;
        } else {
            kvmid = cpregid & ~(1 << 15);
            if (cpregid & (1 << 15)) {
                kvmid |= CP_REG_SIZE_U64 | CP_REG_ARM;
            } else {
                kvmid |= CP_REG_SIZE_U32 | CP_REG_ARM;
            }
        }
        return kvmid;
    }

... just happens to work the same way for HVF?

+        } else {
+            hvf_sreg_match[i].cp_idx = -1;
+        }
+    }
+    arm_cpu->cpreg_array_len = sregs_cnt;
+    arm_cpu->cpreg_vmstate_array_len = sregs_cnt;
+
+    assert(write_cpustate_to_list(arm_cpu, false));
+
+    /* Set CP_NO_RAW system registers on init */
+    ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MIDR_EL1,
+                              arm_cpu->midr);
+    assert_hvf_ok(ret);
+
+    ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MPIDR_EL1,
+                              arm_cpu->mp_affinity);
+    assert_hvf_ok(ret);
+
+    ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, &pfr);
+    assert_hvf_ok(ret);
+    pfr |= env->gicv3state ? (1 << 24) : 0;
+    ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, pfr);
+    assert_hvf_ok(ret);
+
+    /* We're limited to underlying hardware caps, override internal versions */
+    ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1,
+                              &arm_cpu->isar.id_aa64mmfr0);
+    assert_hvf_ok(ret);
+
+    return 0;
+}




reply via email to

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