diff options
Diffstat (limited to 'target-arm/kvm64.c')
-rw-r--r-- | target-arm/kvm64.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c index ee727487b8..39c4364593 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -121,8 +121,24 @@ int kvm_arch_put_registers(CPUState *cs, int level) } } + /* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the + * QEMU side we keep the current SP in xregs[31] as well. + */ + if (env->pstate & PSTATE_SP) { + env->sp_el[1] = env->xregs[31]; + } else { + env->sp_el[0] = env->xregs[31]; + } + reg.id = AARCH64_CORE_REG(regs.sp); - reg.addr = (uintptr_t) &env->xregs[31]; + reg.addr = (uintptr_t) &env->sp_el[0]; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + reg.id = AARCH64_CORE_REG(sp_el1); + reg.addr = (uintptr_t) &env->sp_el[1]; ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); if (ret) { return ret; @@ -152,7 +168,6 @@ int kvm_arch_put_registers(CPUState *cs, int level) } /* TODO: - * SP_EL1 * SPSR[] * FP state * system registers @@ -180,7 +195,14 @@ int kvm_arch_get_registers(CPUState *cs) } reg.id = AARCH64_CORE_REG(regs.sp); - reg.addr = (uintptr_t) &env->xregs[31]; + reg.addr = (uintptr_t) &env->sp_el[0]; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + + reg.id = AARCH64_CORE_REG(sp_el1); + reg.addr = (uintptr_t) &env->sp_el[1]; ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); if (ret) { return ret; @@ -194,6 +216,15 @@ int kvm_arch_get_registers(CPUState *cs) } pstate_write(env, val); + /* KVM puts SP_EL0 in regs.sp and SP_EL1 in regs.sp_el1. On the + * QEMU side we keep the current SP in xregs[31] as well. + */ + if (env->pstate & PSTATE_SP) { + env->xregs[31] = env->sp_el[1]; + } else { + env->xregs[31] = env->sp_el[0]; + } + reg.id = AARCH64_CORE_REG(regs.pc); reg.addr = (uintptr_t) &env->pc; ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); |