diff options
| author | Simon Guo <wei.guo.simon@gmail.com> | 2018-05-23 15:02:02 +0800 | 
|---|---|---|
| committer | Paul Mackerras <paulus@ozlabs.org> | 2018-06-01 10:30:14 +1000 | 
| commit | 19c585eb45e360db43790c6724a3ea929ea03de3 (patch) | |
| tree | d307a2d9c7c05544fab12e812c33b4e62e2ff907 | |
| parent | 5706340a339283fe60d55ddc72ee7728a571a834 (diff) | |
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: Simon Guo <wei.guo.simon@gmail.com>
Reviewed-by: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
| -rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 15 | 
1 files changed, 13 insertions, 2 deletions
| diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index cc26be87e3b8..bb9209947db9 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -989,6 +989,18 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)  		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;  } @@ -1350,8 +1362,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,  	}  #ifdef CONFIG_PPC_BOOK3S_64  	case BOOK3S_INTERRUPT_FAC_UNAVAIL: -		kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56); -		r = RESUME_GUEST; +		r = kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);  		break;  #endif  	case BOOK3S_INTERRUPT_MACHINE_CHECK: | 
