[PATCH] powerpc/mm: Remove kvm radix prefetch workaround for Power9 DD2.2

Jordan Niethe jniethe5 at gmail.com
Mon Dec 2 14:07:31 AEDT 2019


Commit a25bd72badfa ("powerpc/mm/radix: Workaround prefetch issue with
KVM") introduced a number of workarounds as coming out of a guest with
the mmu enabled would make the cpu would start running in hypervisor
state with the PID value from the guest. The cpu will then start
prefetching for the hypervisor with that PID value.

In Power9 DD2.2 the cpu behaviour was modified to fix this. When
accessing Quadrant 0 in hypervisor mode with LPID != 0 prefetching will
not be performed. This means that we can get rid of the workarounds for
Power9 DD2.2 and later revisions.

Signed-off-by: Jordan Niethe <jniethe5 at gmail.com>
---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S  |  9 +++++++++
 arch/powerpc/mm/book3s64/radix_pgtable.c | 18 ++++++++++++------
 arch/powerpc/mm/book3s64/radix_tlb.c     |  5 +++++
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index faebcbb8c4db..6bbc5fbc7ea9 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1793,6 +1793,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 	tlbsync
 	ptesync
 
+	/* We do not need this work around from POWER9 DD2.2 and onwards */
+	mfspr	r3, SPRN_PVR
+	srwi	r6, r3, 16
+	cmpwi	cr0, r6, PVR_POWER9
+	bne	cr0, 2f
+	andi.	r3, r3, 0xfff
+	cmpwi	cr0, r3, 0x202
+	bge	cr0, 2f
+
 	/* Radix: Handle the case where the guest used an illegal PID */
 	LOAD_REG_ADDR(r4, mmu_base_pid)
 	lwz	r3, VCPU_GUEST_PID(r9)
diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
index 6ee17d09649c..1f280124994e 100644
--- a/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -312,6 +312,7 @@ static void __init radix_init_pgtable(void)
 {
 	unsigned long rts_field;
 	struct memblock_region *reg;
+	unsigned int pvr;
 
 	/* We don't support slb for radix */
 	mmu_slb_size = 0;
@@ -336,24 +337,29 @@ static void __init radix_init_pgtable(void)
 	}
 
 	/* Find out how many PID bits are supported */
+	pvr = mfspr(SPRN_PVR);
 	if (cpu_has_feature(CPU_FTR_HVMODE)) {
 		if (!mmu_pid_bits)
 			mmu_pid_bits = 20;
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 		/*
-		 * When KVM is possible, we only use the top half of the
-		 * PID space to avoid collisions between host and guest PIDs
-		 * which can cause problems due to prefetch when exiting the
-		 * guest with AIL=3
+		 * Before Power9 DD2.2, when KVM is possible, we only use the
+		 * top half of the PID space to avoid collisions between host
+		 * and guest PIDs which can cause problems due to prefetch when
+		 * exiting the guest with AIL=3
 		 */
-		mmu_base_pid = 1 << (mmu_pid_bits - 1);
+		if (PVR_VER(pvr) == PVR_POWER9 && ((0xfff & pvr) < 0x202))
+			mmu_base_pid = 1;
+		else
+			mmu_base_pid = 1 << (mmu_pid_bits - 1);
 #else
 		mmu_base_pid = 1;
 #endif
 	} else {
 		/* The guest uses the bottom half of the PID space */
 		if (!mmu_pid_bits)
-			mmu_pid_bits = 19;
+			mmu_pid_bits = (PVR_VER(pvr) == PVR_POWER9 &&
+					((0xfff & pvr) < 0x202)) ? 19 : 20;
 		mmu_base_pid = 1;
 	}
 
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index 67af871190c6..cc86d8a88b86 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -1217,10 +1217,15 @@ void radix__flush_tlb_all(void)
 extern void radix_kvm_prefetch_workaround(struct mm_struct *mm)
 {
 	unsigned long pid = mm->context.id;
+	unsigned int pvr;
 
 	if (unlikely(pid == MMU_NO_CONTEXT))
 		return;
 
+	pvr = mfspr(SPRN_PVR);
+	if (PVR_VER(pvr) != PVR_POWER9 || ((0xfff & pvr) >= 0x202))
+		return;
+
 	/*
 	 * If this context hasn't run on that CPU before and KVM is
 	 * around, there's a slim chance that the guest on another
-- 
2.20.1



More information about the Linuxppc-dev mailing list