From: "Gautham R. Shenoy" <e...@linux.vnet.ibm.com> If a guest executes a stop instruction when the hypervisor has set the PSSCR[ESL|EC] bits, the processor will throw an Hypervisor Facility Unavailable exception. Currently when we receive this exception, we only check if the exeception is generated due to a doorbell instruction, in which case we emulate it. For all other cases, including the case when the guest executes a stop-instruction, the hypervisor sends a PROGILL to the guest program, which results in a guest crash.
This patch adds code to handle the case when the hypervisor receives a H_FAC_UNAVAIL exception due to guest executing the stop instruction. The hypervisor increments the pc to the next instruction and resumes the guest as expected by the semantics of the PSSCR[ESL|EC] = 0 stop instruction. Signed-off-by: Gautham R. Shenoy <e...@linux.vnet.ibm.com> --- arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/kvm/book3s_hv.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index da5cab0..2568c18 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -399,6 +399,7 @@ /* HFSCR and FSCR bit numbers are the same */ #define FSCR_SCV_LG 12 /* Enable System Call Vectored */ #define FSCR_MSGP_LG 10 /* Enable MSGP */ +#define FSCR_STOP_LG 9 /* Enable stop states */ #define FSCR_TAR_LG 8 /* Enable Target Address Register */ #define FSCR_EBB_LG 7 /* Enable Event Based Branching */ #define FSCR_TM_LG 5 /* Enable Transactional Memory */ diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 33be4d9..cdb7224 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -1419,7 +1419,11 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, if (((vcpu->arch.hfscr >> 56) == FSCR_MSGP_LG) && cpu_has_feature(CPU_FTR_ARCH_300)) r = kvmppc_emulate_doorbell_instr(vcpu); - if (r == EMULATE_FAIL) { + else if (((vcpu->arch.hfscr >> 56) == FSCR_STOP_LG) && + cpu_has_feature(CPU_FTR_ARCH_300)) { + kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); + r = RESUME_GUEST; + } else if (r == EMULATE_FAIL) { kvmppc_core_queue_program(vcpu, SRR1_PROGILL); r = RESUME_GUEST; } -- 1.9.4