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