aboutsummaryrefslogtreecommitdiff
path: root/target/arm/kvm64.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/kvm64.c')
-rw-r--r--target/arm/kvm64.c157
1 files changed, 97 insertions, 60 deletions
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 59ed579d02..28f6db57d5 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -24,7 +24,9 @@
#include "qemu/main-loop.h"
#include "exec/gdbstub.h"
#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
#include "kvm_arm.h"
+#include "hw/boards.h"
#include "internals.h"
static bool have_guest_debug;
@@ -593,6 +595,13 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
return true;
}
+bool kvm_arm_aarch32_supported(CPUState *cpu)
+{
+ KVMState *s = KVM_STATE(current_machine->accelerator);
+
+ return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT);
+}
+
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
int kvm_arch_init_vcpu(CPUState *cs)
@@ -710,13 +719,53 @@ int kvm_arm_cpreg_level(uint64_t regidx)
#define AARCH64_SIMD_CTRL_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U32 | \
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
-int kvm_arch_put_registers(CPUState *cs, int level)
+static int kvm_arch_put_fpsimd(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
struct kvm_one_reg reg;
uint32_t fpr;
+ int i, ret;
+
+ for (i = 0; i < 32; i++) {
+ uint64_t *q = aa64_vfp_qreg(env, i);
+#ifdef HOST_WORDS_BIGENDIAN
+ uint64_t fp_val[2] = { q[1], q[0] };
+ reg.addr = (uintptr_t)fp_val;
+#else
+ reg.addr = (uintptr_t)q;
+#endif
+ reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ reg.addr = (uintptr_t)(&fpr);
+ fpr = vfp_get_fpsr(env);
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (ret) {
+ return ret;
+ }
+
+ reg.addr = (uintptr_t)(&fpr);
+ fpr = vfp_get_fpcr(env);
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+ struct kvm_one_reg reg;
uint64_t val;
- int i;
- int ret;
+ int i, ret;
unsigned int el;
ARMCPU *cpu = ARM_CPU(cs);
@@ -806,61 +855,75 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
}
- /* Advanced SIMD and FP registers. */
+ ret = kvm_arch_put_fpsimd(cs);
+ if (ret) {
+ return ret;
+ }
+
+ ret = kvm_put_vcpu_events(cpu);
+ if (ret) {
+ return ret;
+ }
+
+ write_cpustate_to_list(cpu, true);
+
+ if (!write_list_to_kvmstate(cpu, level)) {
+ return -EINVAL;
+ }
+
+ kvm_arm_sync_mpstate_to_kvm(cpu);
+
+ return ret;
+}
+
+static int kvm_arch_get_fpsimd(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ uint32_t fpr;
+ int i, ret;
+
for (i = 0; i < 32; i++) {
uint64_t *q = aa64_vfp_qreg(env, i);
-#ifdef HOST_WORDS_BIGENDIAN
- uint64_t fp_val[2] = { q[1], q[0] };
- reg.addr = (uintptr_t)fp_val;
-#else
- reg.addr = (uintptr_t)q;
-#endif
reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ reg.addr = (uintptr_t)q;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
+ } else {
+#ifdef HOST_WORDS_BIGENDIAN
+ uint64_t t;
+ t = q[0], q[0] = q[1], q[1] = t;
+#endif
}
}
reg.addr = (uintptr_t)(&fpr);
- fpr = vfp_get_fpsr(env);
reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
}
+ vfp_set_fpsr(env, fpr);
- fpr = vfp_get_fpcr(env);
+ reg.addr = (uintptr_t)(&fpr);
reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
- if (ret) {
- return ret;
- }
-
- ret = kvm_put_vcpu_events(cpu);
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret) {
return ret;
}
+ vfp_set_fpcr(env, fpr);
- write_cpustate_to_list(cpu, true);
-
- if (!write_list_to_kvmstate(cpu, level)) {
- return EINVAL;
- }
-
- kvm_arm_sync_mpstate_to_kvm(cpu);
-
- return ret;
+ return 0;
}
int kvm_arch_get_registers(CPUState *cs)
{
struct kvm_one_reg reg;
uint64_t val;
- uint32_t fpr;
unsigned int el;
- int i;
- int ret;
+ int i, ret;
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
@@ -949,36 +1012,10 @@ int kvm_arch_get_registers(CPUState *cs)
env->spsr = env->banked_spsr[i];
}
- /* Advanced SIMD and FP registers */
- for (i = 0; i < 32; i++) {
- uint64_t *q = aa64_vfp_qreg(env, i);
- reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
- reg.addr = (uintptr_t)q;
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
- if (ret) {
- return ret;
- } else {
-#ifdef HOST_WORDS_BIGENDIAN
- uint64_t t;
- t = q[0], q[0] = q[1], q[1] = t;
-#endif
- }
- }
-
- reg.addr = (uintptr_t)(&fpr);
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+ ret = kvm_arch_get_fpsimd(cs);
if (ret) {
return ret;
}
- vfp_set_fpsr(env, fpr);
-
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
- if (ret) {
- return ret;
- }
- vfp_set_fpcr(env, fpr);
ret = kvm_get_vcpu_events(cpu);
if (ret) {
@@ -986,7 +1023,7 @@ int kvm_arch_get_registers(CPUState *cs)
}
if (!write_kvmstate_to_list(cpu)) {
- return EINVAL;
+ return -EINVAL;
}
/* Note that it's OK to have registers which aren't in CPUState,
* so we can ignore a failure return here.