Commit 19c585eb authored by Simon Guo's avatar Simon Guo Committed by Paul Mackerras

KVM: PPC: Book3S PR: Restore NV regs after emulating mfspr from TM SPRs

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 in privileged state.
If PR privileged-state guest is 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 for TM
facility unavailable exceptions in guest privileged state.
Signed-off-by: default avatarSimon Guo <wei.guo.simon@gmail.com>
Reviewed-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 5706340a
...@@ -989,6 +989,18 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac) ...@@ -989,6 +989,18 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
break; break;
} }
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/* 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;
#endif
return RESUME_GUEST; return RESUME_GUEST;
} }
...@@ -1350,8 +1362,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -1350,8 +1362,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
} }
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
case BOOK3S_INTERRUPT_FAC_UNAVAIL: case BOOK3S_INTERRUPT_FAC_UNAVAIL:
kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56); r = kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
r = RESUME_GUEST;
break; break;
#endif #endif
case BOOK3S_INTERRUPT_MACHINE_CHECK: case BOOK3S_INTERRUPT_MACHINE_CHECK:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment