Hi Dongjiu Geng, On 07/09/17 06:54, Dongjiu Geng wrote: > In VHE mode, host kernel runs in the EL2 and can enable > 'User Access Override' when fs==KERNEL_DS so that it can > access kernel memory. However, PSTATE.UAO is set to 0 on > an exception taken from EL1 to EL2. Thus when VHE is used > and exception taken from a guest UAO will be disabled and > host will use the incorrect PSTATE.UAO. So check and reset > the PSTATE.UAO when switching to host. This would only be a problem if KVM were calling into world-switch with fs==KERNEL_DS. I can't see where this happens. kvm_arch_vcpu_ioctl_run() is the only place KVM calls world-switch, there are no set_fs() calls in it, or on the path to it. The addr_limit should be USER_DS, PSTATE.UAO will be clear, as it is when we come back from a guest. This isn't broken today. I agree it will break if KVM decides to set_fs(KERNEL_DS) around world switch, but until then we don't need this patch. > Move the reset PSTATE.PAN on entry to EL2 together with > PSTATE.UAO reset. Moving this breaks PAN-at-HYP for systems with PAN but without VHE. > diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S > index 12ee62d..7662ef5 100644 > --- a/arch/arm64/kvm/hyp/entry.S > +++ b/arch/arm64/kvm/hyp/entry.S > @@ -96,8 +96,6 @@ ENTRY(__guest_exit) > > add x1, x1, #VCPU_CONTEXT > > - ALTERNATIVE(nop, SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN) > - > // Store the guest regs x2 and x3 > stp x2, x3, [x1, #CPU_XREG_OFFSET(2)] > > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c > index a733461..715b3941 100644 > --- a/arch/arm64/kvm/hyp/switch.c > +++ b/arch/arm64/kvm/hyp/switch.c > @@ -22,6 +22,7 @@ > #include <asm/kvm_emulate.h> > #include <asm/kvm_hyp.h> > #include <asm/fpsimd.h> > +#include <asm/exec.h> > > static bool __hyp_text __fpsimd_enabled_nvhe(void) > { > @@ -399,6 +400,17 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) > > __sysreg_restore_host_state(host_ctxt); > > + if (has_vhe()) { > + /* > + * PSTATE was not saved over guest enter/exit, re-enable > + * any detecte features that might not have been set > + * correctly. > + */ > + uao_thread_switch(current); I don't see how addr_limit will ever be KERNEL_DS, so this is always clearing PSTATE.UAO, which was already clear from the guest-exit exception. (Also, the uao_thread_switch() code isn't accessible from EL2, neither is current) > + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), > + ARM64_HAS_PAN, CONFIG_ARM64_PAN)); ... and this is setting PSTATE.PAN on VHE, which was already set, and breaking PAN-at-HYP on non-VHE systems. Vladimir's commit message for that patch that added this enabling explained it is needed for !VHE as SCTLR_EL2 when HCR_EL2.E2H is clear doesn't have a SPAN bit. When we have VHE clearing SCTLR_EL2.SPAN (clearing because it was RES1 on v8.0) will cause the CPU to set PSTATE.PAN when we take an exception. > + } > + > if (fp_enabled) { > __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs); > __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs); > James