[S390] pgtables: Fix race in enable_sie vs. page table ops
[linux-2.6.git] / arch / powerpc / kvm / booke_interrupts.S
index 3b653b5309b8ecc2dad5b5137163a9465408ca22..95e165baf85faee89b7dfa30e628b75778358618 100644 (file)
@@ -42,7 +42,8 @@
 #define HOST_STACK_LR   (HOST_STACK_SIZE + 4) /* In caller stack frame. */
 
 #define NEED_INST_MASK ((1<<BOOKE_INTERRUPT_PROGRAM) | \
-                        (1<<BOOKE_INTERRUPT_DTLB_MISS))
+                        (1<<BOOKE_INTERRUPT_DTLB_MISS) | \
+                        (1<<BOOKE_INTERRUPT_DEBUG))
 
 #define NEED_DEAR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
                         (1<<BOOKE_INTERRUPT_DTLB_MISS))
@@ -331,51 +332,57 @@ lightweight_exit:
 
        mfspr   r3, SPRN_PID
        stw     r3, VCPU_HOST_PID(r4)
-       lwz     r3, VCPU_PID(r4)
+       lwz     r3, VCPU_SHADOW_PID(r4)
        mtspr   SPRN_PID, r3
 
-       /* Prevent all TLB updates. */
+       /* Prevent all asynchronous TLB updates. */
        mfmsr   r5
        lis     r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@h
        ori     r6, r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
        andc    r6, r5, r6
        mtmsr   r6
 
-       /* Save the host's non-pinned TLB mappings, and load the guest mappings
-        * over them. Leave the host's "pinned" kernel mappings in place. */
-       /* XXX optimization: use generation count to avoid swapping unmodified
-        * entries. */
+       /* Load the guest mappings, leaving the host's "pinned" kernel mappings
+        * in place. */
        mfspr   r10, SPRN_MMUCR                 /* Save host MMUCR. */
-       lis     r8, tlb_44x_hwater@ha
-       lwz     r8, tlb_44x_hwater@l(r8)
-       addi    r3, r4, VCPU_HOST_TLB - 4
-       addi    r9, r4, VCPU_SHADOW_TLB - 4
-       li      r6, 0
+       li      r5, PPC44x_TLB_SIZE
+       lis     r5, tlb_44x_hwater@ha
+       lwz     r5, tlb_44x_hwater@l(r5)
+       mtctr   r5
+       addi    r9, r4, VCPU_SHADOW_TLB
+       addi    r5, r4, VCPU_SHADOW_MOD
+       li      r3, 0
 1:
-       /* Save host entry. */
-       tlbre   r7, r6, PPC44x_TLB_PAGEID
-       mfspr   r5, SPRN_MMUCR
-       stwu    r5, 4(r3)
-       stwu    r7, 4(r3)
-       tlbre   r7, r6, PPC44x_TLB_XLAT
-       stwu    r7, 4(r3)
-       tlbre   r7, r6, PPC44x_TLB_ATTRIB
-       stwu    r7, 4(r3)
+       lbzx    r7, r3, r5
+       cmpwi   r7, 0
+       beq     3f
+
        /* Load guest entry. */
-       lwzu    r7, 4(r9)
+       mulli   r11, r3, TLBE_BYTES
+       add     r11, r11, r9
+       lwz     r7, 0(r11)
        mtspr   SPRN_MMUCR, r7
-       lwzu    r7, 4(r9)
-       tlbwe   r7, r6, PPC44x_TLB_PAGEID
-       lwzu    r7, 4(r9)
-       tlbwe   r7, r6, PPC44x_TLB_XLAT
-       lwzu    r7, 4(r9)
-       tlbwe   r7, r6, PPC44x_TLB_ATTRIB
-       /* Increment index. */
-       addi    r6, r6, 1
-       cmpw    r6, r8
-       blt     1b
+       lwz     r7, 4(r11)
+       tlbwe   r7, r3, PPC44x_TLB_PAGEID
+       lwz     r7, 8(r11)
+       tlbwe   r7, r3, PPC44x_TLB_XLAT
+       lwz     r7, 12(r11)
+       tlbwe   r7, r3, PPC44x_TLB_ATTRIB
+3:
+       addi    r3, r3, 1                       /* Increment index. */
+       bdnz    1b
+
        mtspr   SPRN_MMUCR, r10                 /* Restore host MMUCR. */
 
+       /* Clear bitmap of modified TLB entries */
+       li      r5, PPC44x_TLB_SIZE>>2
+       mtctr   r5
+       addi    r5, r4, VCPU_SHADOW_MOD - 4
+       li      r6, 0
+1:
+       stwu    r6, 4(r5)
+       bdnz    1b
+
        iccci   0, 0 /* XXX hack */
 
        /* Load some guest volatiles. */
@@ -431,6 +438,14 @@ lightweight_exit:
        oris    r3, r3, KVMPPC_MSR_MASK@h
        ori     r3, r3, KVMPPC_MSR_MASK@l
        mtsrr1  r3
+
+       /* Clear any debug events which occurred since we disabled MSR[DE].
+        * XXX This gives us a 3-instruction window in which a breakpoint
+        * intended for guest context could fire in the host instead. */
+       lis     r3, 0xffff
+       ori     r3, r3, 0xffff
+       mtspr   SPRN_DBSR, r3
+
        lwz     r3, VCPU_GPR(r3)(r4)
        lwz     r4, VCPU_GPR(r4)(r4)
        rfi