Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932087AbdIGJVr (ORCPT ); Thu, 7 Sep 2017 05:21:47 -0400 Received: from foss.arm.com ([217.140.101.70]:57586 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754556AbdIGJVp (ORCPT ); Thu, 7 Sep 2017 05:21:45 -0400 Message-ID: <59B10F52.9010400@arm.com> Date: Thu, 07 Sep 2017 10:20:18 +0100 From: James Morse User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.6.0 MIME-Version: 1.0 To: Dongjiu Geng CC: christoffer.dall@linaro.org, marc.zyngier@arm.com, vladimir.murzin@arm.com, rkrcmar@redhat.com, catalin.marinas@arm.com, shankerd@codeaurora.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, zhanghaibin7@huawei.com, huangshaoyu@huawei.com Subject: Re: [PATCH] arm64: KVM: VHE: reset PSTATE.UAO when switch to host References: <1504763684-30128-1-git-send-email-gengdongjiu@huawei.com> In-Reply-To: <1504763684-30128-1-git-send-email-gengdongjiu@huawei.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3122 Lines: 93 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 > #include > #include > +#include > > 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