KVM: PPC: e500: Fix default tlb for victim hint
authorMihai Caraman <mihai.caraman@freescale.com>
Mon, 30 Jun 2014 12:54:58 +0000 (15:54 +0300)
committerAlexander Graf <agraf@suse.de>
Mon, 28 Jul 2014 13:22:20 +0000 (15:22 +0200)
Tlb search operation used for victim hint relies on the default tlb set by the
host. When hardware tablewalk support is enabled in the host, the default tlb is
TLB1 which leads KVM to evict the bolted entry. Set and restore the default tlb
when searching for victim hint.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
Reviewed-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/kvm/e500_mmu_host.c

index d0918e09557f95e3d09f4ed41babb7d36f4e7f70..8d24f788fd09d93a2789ad32be654f90f9b0186f 100644 (file)
@@ -40,7 +40,9 @@
 
 /* MAS registers bit definitions */
 
-#define MAS0_TLBSEL(x)         (((x) << 28) & 0x30000000)
+#define MAS0_TLBSEL_MASK        0x30000000
+#define MAS0_TLBSEL_SHIFT       28
+#define MAS0_TLBSEL(x)          (((x) << MAS0_TLBSEL_SHIFT) & MAS0_TLBSEL_MASK)
 #define MAS0_ESEL_MASK         0x0FFF0000
 #define MAS0_ESEL_SHIFT                16
 #define MAS0_ESEL(x)           (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
@@ -86,6 +88,7 @@
 #define MAS3_SPSIZE            0x0000003e
 #define MAS3_SPSIZE_SHIFT      1
 
+#define MAS4_TLBSEL_MASK       MAS0_TLBSEL_MASK
 #define MAS4_TLBSELD(x)        MAS0_TLBSEL(x)
 #define MAS4_INDD              0x00008000      /* Default IND */
 #define MAS4_TSIZED(x)         MAS1_TSIZE(x)
index dd2cc03f406f9a0e1f844473ca92c5560eca6c67..79677d76d1a4cec4311e938514735f1cf3d8af5b 100644 (file)
@@ -107,11 +107,15 @@ static u32 get_host_mas0(unsigned long eaddr)
 {
        unsigned long flags;
        u32 mas0;
+       u32 mas4;
 
        local_irq_save(flags);
        mtspr(SPRN_MAS6, 0);
+       mas4 = mfspr(SPRN_MAS4);
+       mtspr(SPRN_MAS4, mas4 & ~MAS4_TLBSEL_MASK);
        asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET));
        mas0 = mfspr(SPRN_MAS0);
+       mtspr(SPRN_MAS4, mas4);
        local_irq_restore(flags);
 
        return mas0;