summaryrefslogtreecommitdiff
path: root/arch/powerpc/kvm/book3s_64_slb.S
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-01-08 02:58:04 +0100
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 12:35:48 -0300
commitb4433a7cceed59714b0778e1ace624befdd15ded (patch)
tree745f0477d7368155cddc363fed6e8f3dc28f83cd /arch/powerpc/kvm/book3s_64_slb.S
parent7e57cba06074da84d7c24d8c3f44040d2d8c88ac (diff)
KVM: PPC: Implement 'skip instruction' mode
To fetch the last instruction we were interrupted on, we enable DR in early exit code, where we are still in a very transitional phase between guest and host state. Most of the time this seemed to work, but another CPU can easily flush our TLB and HTAB which makes us go in the Linux page fault handler which totally breaks because we still use the guest's SLB entries. To work around that, let's introduce a second KVM guest mode that defines that whenever we get a trap, we don't call the Linux handler or go into the KVM exit code, but just jump over the faulting instruction. That way a potentially bad lwz doesn't trigger any faults and we can later on interpret the invalid instruction we fetched as "fetch didn't work". Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s_64_slb.S')
-rw-r--r--arch/powerpc/kvm/book3s_64_slb.S16
1 files changed, 11 insertions, 5 deletions
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S
index 7188c11ed7d1..d07b88617b2c 100644
--- a/arch/powerpc/kvm/book3s_64_slb.S
+++ b/arch/powerpc/kvm/book3s_64_slb.S
@@ -212,10 +212,6 @@ kvmppc_handler_trampoline_exit:
mfdar r5
mfdsisr r6
- /* Unset guest state */
- li r9, 0
- stb r9, PACA_KVM_IN_GUEST(r13)
-
/*
* In order for us to easily get the last instruction,
* we got the #vmexit at, we exploit the fact that the
@@ -233,18 +229,28 @@ kvmppc_handler_trampoline_exit:
ld_last_inst:
/* Save off the guest instruction we're at */
+
+ /* Set guest mode to 'jump over instruction' so if lwz faults
+ * we'll just continue at the next IP. */
+ li r9, KVM_GUEST_MODE_SKIP
+ stb r9, PACA_KVM_IN_GUEST(r13)
+
/* 1) enable paging for data */
mfmsr r9
ori r11, r9, MSR_DR /* Enable paging for data */
mtmsr r11
/* 2) fetch the instruction */
- /* XXX implement PACA_KVM_IN_GUEST=2 path to safely jump over this */
+ li r0, KVM_INST_FETCH_FAILED /* In case lwz faults */
lwz r0, 0(r3)
/* 3) disable paging again */
mtmsr r9
no_ld_last_inst:
+ /* Unset guest mode */
+ li r9, KVM_GUEST_MODE_NONE
+ stb r9, PACA_KVM_IN_GUEST(r13)
+
/* Restore bolted entries from the shadow and fix it along the way */
/* We don't store anything in entry 0, so we don't need to take care of it */