hvf: Add Apple Silicon support

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>
Message-id: 20210916155404.86958-5-agraf@csgraf.de
[PMM: added missing #include]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Alexander Graf
2021-09-16 17:53:58 +02:00
committed by Peter Maydell
parent ce7f5b1c50
commit a1477da3dd
7 changed files with 834 additions and 1 deletions

View File

@@ -433,6 +433,11 @@ F: accel/accel-*.c
F: accel/Makefile.objs
F: accel/stubs/Makefile.objs
Apple Silicon HVF CPUs
M: Alexander Graf <agraf@csgraf.de>
S: Maintained
F: target/arm/hvf/
X86 HVF CPUs
M: Cameron Esfahani <dirty@apple.com>
M: Roman Bolshakov <r.bolshakov@yadro.com>

View File

@@ -60,6 +60,10 @@
HVFState *hvf_state;
#ifdef __aarch64__
#define HV_VM_DEFAULT NULL
#endif
/* Memory slots */
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
@@ -376,7 +380,11 @@ static int hvf_init_vcpu(CPUState *cpu)
pthread_sigmask(SIG_BLOCK, NULL, &set);
sigdelset(&set, SIG_IPI);
#ifdef __aarch64__
r = hv_vcpu_create(&cpu->hvf->fd, (hv_vcpu_exit_t **)&cpu->hvf->exit, NULL);
#else
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf->fd, HV_VCPU_DEFAULT);
#endif
cpu->vcpu_dirty = 1;
assert_hvf_ok(r);
@@ -452,6 +460,7 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
ops->create_vcpu_thread = hvf_start_vcpu_thread;
ops->kick_vcpu_thread = hvf_kick_vcpu_thread;
ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;

View File

@@ -11,7 +11,11 @@
#ifndef HVF_INT_H
#define HVF_INT_H
#ifdef __aarch64__
#include <Hypervisor/Hypervisor.h>
#else
#include <Hypervisor/hv.h>
#endif
/* hvf_slot flags */
#define HVF_SLOT_LOG (1 << 0)
@@ -40,11 +44,14 @@ struct HVFState {
int num_slots;
hvf_vcpu_caps *hvf_caps;
uint64_t vtimer_offset;
};
extern HVFState *hvf_state;
struct hvf_vcpu_state {
int fd;
uint64_t fd;
void *exit;
bool vtimer_masked;
};
void assert_hvf_ok(hv_return_t ret);
@@ -55,5 +62,6 @@ int hvf_vcpu_exec(CPUState *);
hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
int hvf_put_registers(CPUState *);
int hvf_get_registers(CPUState *);
void hvf_kick_vcpu_thread(CPUState *cpu);
#endif

View File

@@ -2169,6 +2169,7 @@ if have_system or have_user
'accel/tcg',
'hw/core',
'target/arm',
'target/arm/hvf',
'target/hppa',
'target/i386',
'target/i386/kvm',

794
target/arm/hvf/hvf.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
hvf_unhandled_sysreg_read(uint64_t pc, uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2) "unhandled sysreg read at pc=0x%"PRIx64": 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d)"
hvf_unhandled_sysreg_write(uint64_t pc, uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2) "unhandled sysreg write at pc=0x%"PRIx64": 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d)"
hvf_inject_fiq(void) "injecting FIQ"
hvf_inject_irq(void) "injecting IRQ"
hvf_data_abort(uint64_t pc, uint64_t va, uint64_t pa, bool isv, bool iswrite, bool s1ptw, uint32_t len, uint32_t srt) "data abort: [pc=0x%"PRIx64" va=0x%016"PRIx64" pa=0x%016"PRIx64" isv=%d iswrite=%d s1ptw=%d len=%d srt=%d]"
hvf_sysreg_read(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, uint64_t val) "sysreg read 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d) = 0x%016"PRIx64
hvf_sysreg_write(uint32_t reg, uint32_t op0, uint32_t op1, uint32_t crn, uint32_t crm, uint32_t op2, uint64_t val) "sysreg write 0x%08x (op0=%d op1=%d crn=%d crm=%d op2=%d, val=0x%016"PRIx64")"
hvf_unknown_hvc(uint64_t x0) "unknown HVC! 0x%016"PRIx64
hvf_unknown_smc(uint64_t x0) "unknown SMC! 0x%016"PRIx64
hvf_exit(uint64_t syndrome, uint32_t ec, uint64_t pc) "exit: 0x%"PRIx64" [ec=0x%x pc=0x%"PRIx64"]"

View File

@@ -53,6 +53,7 @@
#include "sysemu/hvf.h"
#include "sysemu/hvf_int.h"
#include "sysemu/runstate.h"
#include "sysemu/cpus.h"
#include "hvf-i386.h"
#include "vmcs.h"
#include "vmx.h"
@@ -206,6 +207,11 @@ static inline bool apic_bus_freq_is_known(CPUX86State *env)
return env->apic_bus_freq != 0;
}
void hvf_kick_vcpu_thread(CPUState *cpu)
{
cpus_kick_thread(cpu);
}
int hvf_arch_init(void)
{
return 0;