|
@@ -1443,12 +1443,14 @@ mc_cont:
|
|
|
ori r6,r6,1
|
|
|
mtspr SPRN_CTRLT,r6
|
|
|
4:
|
|
|
- /* Read the guest SLB and save it away */
|
|
|
+ /* Check if we are running hash or radix and store it in cr2 */
|
|
|
ld r5, VCPU_KVM(r9)
|
|
|
lbz r0, KVM_RADIX(r5)
|
|
|
- cmpwi r0, 0
|
|
|
+ cmpwi cr2,r0,0
|
|
|
+
|
|
|
+ /* Read the guest SLB and save it away */
|
|
|
li r5, 0
|
|
|
- bne 3f /* for radix, save 0 entries */
|
|
|
+ bne cr2, 3f /* for radix, save 0 entries */
|
|
|
lwz r0,VCPU_SLB_NR(r9) /* number of entries in SLB */
|
|
|
mtctr r0
|
|
|
li r6,0
|
|
@@ -1712,11 +1714,6 @@ BEGIN_FTR_SECTION_NESTED(96)
|
|
|
END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96)
|
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|
|
22:
|
|
|
- /* Clear out SLB */
|
|
|
- li r5,0
|
|
|
- slbmte r5,r5
|
|
|
- slbia
|
|
|
- ptesync
|
|
|
|
|
|
/* Restore host values of some registers */
|
|
|
BEGIN_FTR_SECTION
|
|
@@ -1737,10 +1734,56 @@ BEGIN_FTR_SECTION
|
|
|
mtspr SPRN_PID, r7
|
|
|
mtspr SPRN_IAMR, r8
|
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC_RADIX_MMU
|
|
|
+ /*
|
|
|
+ * Are we running hash or radix ?
|
|
|
+ */
|
|
|
+ beq cr2,3f
|
|
|
+
|
|
|
+ /* Radix: Handle the case where the guest used an illegal PID */
|
|
|
+ LOAD_REG_ADDR(r4, mmu_base_pid)
|
|
|
+ lwz r3, VCPU_GUEST_PID(r9)
|
|
|
+ lwz r5, 0(r4)
|
|
|
+ cmpw cr0,r3,r5
|
|
|
+ blt 2f
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Illegal PID, the HW might have prefetched and cached in the TLB
|
|
|
+ * some translations for the LPID 0 / guest PID combination which
|
|
|
+ * Linux doesn't know about, so we need to flush that PID out of
|
|
|
+ * the TLB. First we need to set LPIDR to 0 so tlbiel applies to
|
|
|
+ * the right context.
|
|
|
+ */
|
|
|
+ li r0,0
|
|
|
+ mtspr SPRN_LPID,r0
|
|
|
+ isync
|
|
|
+
|
|
|
+ /* Then do a congruence class local flush */
|
|
|
+ ld r6,VCPU_KVM(r9)
|
|
|
+ lwz r0,KVM_TLB_SETS(r6)
|
|
|
+ mtctr r0
|
|
|
+ li r7,0x400 /* IS field = 0b01 */
|
|
|
+ ptesync
|
|
|
+ sldi r0,r3,32 /* RS has PID */
|
|
|
+1: PPC_TLBIEL(7,0,2,1,1) /* RIC=2, PRS=1, R=1 */
|
|
|
+ addi r7,r7,0x1000
|
|
|
+ bdnz 1b
|
|
|
+ ptesync
|
|
|
+
|
|
|
+2: /* Flush the ERAT on radix P9 DD1 guest exit */
|
|
|
BEGIN_FTR_SECTION
|
|
|
PPC_INVALIDATE_ERAT
|
|
|
END_FTR_SECTION_IFSET(CPU_FTR_POWER9_DD1)
|
|
|
+ b 4f
|
|
|
+#endif /* CONFIG_PPC_RADIX_MMU */
|
|
|
|
|
|
+ /* Hash: clear out SLB */
|
|
|
+3: li r5,0
|
|
|
+ slbmte r5,r5
|
|
|
+ slbia
|
|
|
+ ptesync
|
|
|
+4:
|
|
|
/*
|
|
|
* POWER7/POWER8 guest -> host partition switch code.
|
|
|
* We don't have to lock against tlbies but we do
|