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?