[v2,19/30] KVM: PPC: Book3S PR: enable NV reg restore for reading TM SPR at guest privilege state

Message ID 1519753958-11756-9-git-send-email-wei.guo.simon@gmail.com
State Changes Requested
Headers show
  • Untitled series #30815
Related show

Commit Message

Simon Guo Feb. 27, 2018, 5:52 p.m.
From: Simon Guo <wei.guo.simon@gmail.com>

Currently kvmppc_handle_fac() will not update NV GPRs and thus it can
return with GUEST_RESUME.

However PR KVM guest always disables MSR_TM bit at privilege state. If PR
privilege guest are trying to read TM SPRs, it will trigger TM facility
unavailable exception and fall into kvmppc_handle_fac(). Then the emulation
will be done by kvmppc_core_emulate_mfspr_pr(). The mfspr instruction can
include a RT with NV reg. So it is necessary to restore NV GPRs at this
case, to reflect the update to NV RT.

This patch make kvmppc_handle_fac() return GUEST_RESUME_NV at TM fac
exception and with guest privilege state.

Signed-off-by: Simon Guo <wei.guo.simon@gmail.com>
Reviewed-by: Paul Mackerras <paulus@ozlabs.org>
 arch/powerpc/kvm/book3s_pr.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)


diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 82e1a74..f31f9de 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -998,6 +998,18 @@  static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
+	/* Since we disabled MSR_TM at privilege state, the mfspr instruction
+	 * for TM spr can trigger TM fac unavailable. In this case, the
+	 * emulation is handled by kvmppc_emulate_fac(), which invokes
+	 * kvmppc_emulate_mfspr() finally. But note the mfspr can include
+	 * RT for NV registers. So it need to restore those NV reg to reflect
+	 * the update.
+	 */
+	if ((fac == FSCR_TM_LG) && !(kvmppc_get_msr(vcpu) & MSR_PR))
+		return RESUME_GUEST_NV;
 	return RESUME_GUEST;
@@ -1359,8 +1371,7 @@  int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
 #ifdef CONFIG_PPC_BOOK3S_64
-		kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
+		r = kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);