From: Greg Kurz <gkurz@linux.vnet.ibm.com>
Subject: KVM: PPC: Book3S HV: Fix incorrect userspace exit on ioeventfd write
Git-commit: e59d24e61269de34d79d2f39d3d581c219ac7a94
Patch-mainline: v3.15-rc1
References: bnc#875242 
    
    When the guest does an MMIO write which is handled successfully by an
    ioeventfd, ioeventfd_write() returns 0 (success) and
    kvmppc_handle_store() returns EMULATE_DONE.  Then
    kvmppc_emulate_mmio() converts EMULATE_DONE to RESUME_GUEST_NV and
    this causes an exit from the loop in kvmppc_vcpu_run_hv(), causing an
    exit back to userspace with a bogus exit reason code, typically
    causing userspace (e.g. qemu) to crash with a message about an unknown
    exit code.
    
    This adds handling of RESUME_GUEST_NV in kvmppc_vcpu_run_hv() in order
    to fix that.  For generality, we define a helper to check for either
    of the return-to-guest codes we use, RESUME_GUEST and RESUME_GUEST_NV,
    to make it easy to check for either and provide one place to update if
    any other return-to-guest code gets defined in future.
    
    Since it only affects Book3S HV for now, the helper is added to
    the kvm_book3s.h header file.
    
    We use the helper in two places in kvmppc_run_core() as well for
    future-proofing, though we don't see RESUME_GUEST_NV in either place
    at present.
    
    [paulus@samba.org - combined 4 patches into one, rewrote description]
    
    Suggested-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Torsten Duwe <duwe@suse.de>

 arch/powerpc/include/asm/kvm_book3s.h | 5 +++++
 arch/powerpc/kvm/book3s_hv.c          | 6 +++---
 2 files changed, 8 insertions(+), 3 deletions(-)
Index: linux-3.12-SLE12/arch/powerpc/include/asm/kvm_book3s.h
===================================================================
--- linux-3.12-SLE12.orig/arch/powerpc/include/asm/kvm_book3s.h
+++ linux-3.12-SLE12/arch/powerpc/include/asm/kvm_book3s.h
@@ -491,6 +491,11 @@ static inline ulong kvmppc_get_fault_dar
 	return vcpu->arch.fault_dar;
 }
 
+static inline bool is_kvmppc_resume_guest(int r)
+{
+	return (r == RESUME_GUEST || r == RESUME_GUEST_NV);
+}
+
 static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
 {
 	return false;
Index: linux-3.12-SLE12/arch/powerpc/kvm/book3s_hv.c
===================================================================
--- linux-3.12-SLE12.orig/arch/powerpc/kvm/book3s_hv.c
+++ linux-3.12-SLE12/arch/powerpc/kvm/book3s_hv.c
@@ -1276,7 +1276,7 @@ static void kvmppc_run_core(struct kvmpp
 		vcpu->arch.trap = 0;
 
 		if (vcpu->arch.ceded) {
-			if (ret != RESUME_GUEST)
+			if (!is_kvmppc_resume_guest(ret))
 				kvmppc_end_cede(vcpu);
 			else
 				kvmppc_set_timer(vcpu);
@@ -1287,7 +1287,7 @@ static void kvmppc_run_core(struct kvmpp
 	vc->vcore_state = VCORE_INACTIVE;
 	list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
 				 arch.run_list) {
-		if (vcpu->arch.ret != RESUME_GUEST) {
+		if (!is_kvmppc_resume_guest(vcpu->arch.ret)) {
 			kvmppc_remove_runnable(vc, vcpu);
 			wake_up(&vcpu->arch.cpu_run);
 		}
@@ -1478,7 +1478,7 @@ int kvmppc_vcpu_run(struct kvm_run *run,
 				vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
 			srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
 		}
-	} while (r == RESUME_GUEST);
+	} while (is_kvmppc_resume_guest(r));
 
  out:
 	vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
