When we emulate instructions during our critical section emulation we may
overwrite non-volatile registers that the looping code would need to load
back in.

Notify the callers of prepare_to_enter() when we emulated code, so that they
can set enable NV restoration on their exit path.

Signed-off-by: Alexander Graf <ag...@suse.de>
---
 arch/powerpc/kvm/book3s_pr.c | 16 +++++++++++++---
 arch/powerpc/kvm/booke.c     |  3 +++
 arch/powerpc/kvm/powerpc.c   |  6 +++++-
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 3b82e86..8cce531 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -1174,10 +1174,20 @@ program_interrupt:
                 * again due to a host external interrupt.
                 */
                s = kvmppc_prepare_to_enter(vcpu);
-               if (s <= 0)
+               switch (s) {
+               case -EINTR:
                        r = s;
-               else {
-                       /* interrupts now hard-disabled */
+                       break;
+               case 0:
+                       /* Exit_reason is set, go to host */
+                       r = RESUME_HOST;
+                       break;
+               case 2:
+                       /* Registers modified, reload then enter */
+                       r = RESUME_GUEST_NV;
+                       /* fall through */
+               case 1:
+                       /* Interrupts now hard-disabled, enter guest */
                        kvmppc_fix_ee_before_entry();
                }
 
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index c0a71ce..66718d4 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -1216,6 +1216,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct 
kvm_vcpu *vcpu,
                if (s <= 0)
                        r = (s << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
                else {
+                       if (s == 2)
+                               r = RESUME_GUEST_NV;
+
                        /* interrupts now hard-disabled */
                        kvmppc_fix_ee_before_entry();
                }
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 0a326e1..6757c47 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -103,12 +103,14 @@ static bool kvmppc_needs_emulation(struct kvm_vcpu *vcpu)
  *
  * returns:
  *
+ * == 2 if we're ready to go into guest state with NV registers restored
  * == 1 if we're ready to go into guest state
  * <= 0 if we need to go back to the host with return value
  */
 int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 {
        int r;
+       int enter_level = 1;
 
        WARN_ON(irqs_disabled());
        hard_irq_disable();
@@ -163,13 +165,15 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
                        r = kvmppc_emulate_any_instruction(vcpu);
                        if (r == EMULATE_DO_MMIO)
                                return 0;
+                       if (r == EMULATE_DONE)
+                               enter_level = 2;
 
                        hard_irq_disable();
                        continue;
                }
 
                kvm_guest_enter();
-               return 1;
+               return enter_level;
        }
 
        /* return to host */
-- 
1.8.1.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to