@@ -120,10 +120,32 @@ static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
__sysreg_save_vel1_state(ctxt);
}
+static u64 __hyp_text from_hw_pstate(const struct kvm_cpu_context *ctxt)
+{
+ u64 reg = read_sysreg_el2(SYS_SPSR);
+
+ if (__is_hyp_ctxt(ctxt)) {
+ u64 mode = reg & PSR_MODE_MASK;
+
+ switch (mode) {
+ case PSR_MODE_EL1t:
+ mode = PSR_MODE_EL2t;
+ break;
+ case PSR_MODE_EL1h:
+ mode = PSR_MODE_EL2h;
+ break;
+ }
+
+ return (reg & ~PSR_MODE_MASK) | mode;
+ }
+
+ return reg;
+}
+
static void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt)
{
ctxt->gp_regs.regs.pc = read_sysreg_el2(SYS_ELR);
- ctxt->gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR);
+ ctxt->gp_regs.regs.pstate = from_hw_pstate(ctxt);
if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN))
ctxt->sys_regs[DISR_EL1] = read_sysreg_s(SYS_VDISR_EL2);
@@ -288,10 +310,25 @@ static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
__sysreg_restore_vel1_state(ctxt);
}
+/* Read the VCPU state's PSTATE, but translate (v)EL2 to EL1. */
+static u64 __hyp_text to_hw_pstate(const struct kvm_cpu_context *ctxt)
+{
+ u64 mode = ctxt->gp_regs.regs.pstate & PSR_MODE_MASK;
+
+ switch (mode) {
+ case PSR_MODE_EL2t:
+ mode = PSR_MODE_EL1t;
+ case PSR_MODE_EL2h:
+ mode = PSR_MODE_EL1h;
+ }
+
+ return (ctxt->gp_regs.regs.pstate & ~PSR_MODE_MASK) | mode;
+}
+
static void __hyp_text
__sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt)
{
- u64 pstate = ctxt->gp_regs.regs.pstate;
+ u64 pstate = to_hw_pstate(ctxt);
u64 mode = pstate & PSR_AA32_MODE_MASK;
/*