Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Suchanek <msuchanek@suse.de>2019-10-02 15:17:02 +0200
committerMichal Suchanek <msuchanek@suse.de>2019-10-02 21:10:16 +0200
commit1f54c64b1a6bb322874eed7e1f26e8fc78cee66e (patch)
tree8f4e0cb253526d5e6dd1b9cb7926355445cd651b
parentd7b6f7c2e5a4d50ac4241f891982cc337b60aab2 (diff)
powerpc/mm/radix: implement LPID based TLB flushes to be used by KVM
(bsc#1152161 ltc#181664). - Refresh patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch.
-rw-r--r--patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch7
-rw-r--r--patches.suse/powerpc-mm-radix-implement-LPID-based-TLB-flushes-to.patch296
-rw-r--r--series.conf1
3 files changed, 301 insertions, 3 deletions
diff --git a/patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch b/patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch
index 95fa88db68..f6ac54ccd4 100644
--- a/patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch
+++ b/patches.suse/powerpc-64s-Remove-POWER9-DD1-support.patch
@@ -165,14 +165,15 @@ Acked-by: Michal Suchanek <msuchanek@suse.de>
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
-@@ -43,7 +43,5 @@ extern void radix__flush_tlb_page_psize(
+@@ -43,8 +43,6 @@ extern void radix__flush_tlb_page_psize(
extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr);
extern void radix__flush_tlb_all(void);
-extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
- unsigned long address);
- #endif
+ extern void radix__flush_tlb_lpid_page(unsigned int lpid,
+ unsigned long addr,
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -209,7 +209,6 @@ static inline void cpu_feature_keys_init
@@ -779,7 +780,7 @@ Acked-by: Michal Suchanek <msuchanek@suse.de>
old_pte = __radix_pte_update(ptep, ~0, 0);
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
-@@ -548,24 +548,6 @@ void radix__flush_tlb_all(void)
+@@ -930,24 +930,6 @@ void radix__flush_tlb_all(void)
asm volatile("eieio; tlbsync; ptesync": : :"memory");
}
diff --git a/patches.suse/powerpc-mm-radix-implement-LPID-based-TLB-flushes-to.patch b/patches.suse/powerpc-mm-radix-implement-LPID-based-TLB-flushes-to.patch
new file mode 100644
index 0000000000..372c04a747
--- /dev/null
+++ b/patches.suse/powerpc-mm-radix-implement-LPID-based-TLB-flushes-to.patch
@@ -0,0 +1,296 @@
+From 0078778a86b14f85bf50e96d9ddeb3b70b55805d Mon Sep 17 00:00:00 2001
+From: Nicholas Piggin <npiggin@gmail.com>
+Date: Wed, 9 May 2018 12:20:18 +1000
+Subject: [PATCH] powerpc/mm/radix: implement LPID based TLB flushes to be used
+ by KVM
+
+References: bsc#1152161 ltc#181664
+Patch-mainline: v4.18-rc1
+Git-commit: 0078778a86b14f85bf50e96d9ddeb3b70b55805d
+
+Implement a local TLB flush for invalidating an LPID with variants for
+process or partition scope. And a global TLB flush for invalidating
+a partition scoped page of an LPID.
+
+These will be used by KVM in subsequent patches.
+
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ .../include/asm/book3s/64/tlbflush-radix.h | 7 +
+ arch/powerpc/mm/tlb-radix.c | 207 ++++++++++++++++++
+ 2 files changed, 214 insertions(+)
+
+diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
+index 19b45ba6caf9..ef5c3f2994c9 100644
+--- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
++++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
+@@ -51,4 +51,11 @@ extern void radix__flush_tlb_all(void);
+ extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
+ unsigned long address);
+
++extern void radix__flush_tlb_lpid_page(unsigned int lpid,
++ unsigned long addr,
++ unsigned long page_size);
++extern void radix__flush_pwc_lpid(unsigned int lpid);
++extern void radix__local_flush_tlb_lpid(unsigned int lpid);
++extern void radix__local_flush_tlb_lpid_guest(unsigned int lpid);
++
+ #endif
+diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
+index a5d7309c2d05..5ac3206c51cc 100644
+--- a/arch/powerpc/mm/tlb-radix.c
++++ b/arch/powerpc/mm/tlb-radix.c
+@@ -118,6 +118,53 @@ static inline void __tlbie_pid(unsigned long pid, unsigned long ric)
+ trace_tlbie(0, 0, rb, rs, ric, prs, r);
+ }
+
++static inline void __tlbiel_lpid(unsigned long lpid, int set,
++ unsigned long ric)
++{
++ unsigned long rb,rs,prs,r;
++
++ rb = PPC_BIT(52); /* IS = 2 */
++ rb |= set << PPC_BITLSHIFT(51);
++ rs = 0; /* LPID comes from LPIDR */
++ prs = 0; /* partition scoped */
++ r = 1; /* radix format */
++
++ asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
++ : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
++ trace_tlbie(lpid, 1, rb, rs, ric, prs, r);
++}
++
++static inline void __tlbie_lpid(unsigned long lpid, unsigned long ric)
++{
++ unsigned long rb,rs,prs,r;
++
++ rb = PPC_BIT(52); /* IS = 2 */
++ rs = lpid;
++ prs = 0; /* partition scoped */
++ r = 1; /* radix format */
++
++ asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
++ : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
++ trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
++}
++
++static inline void __tlbiel_lpid_guest(unsigned long lpid, int set,
++ unsigned long ric)
++{
++ unsigned long rb,rs,prs,r;
++
++ rb = PPC_BIT(52); /* IS = 2 */
++ rb |= set << PPC_BITLSHIFT(51);
++ rs = 0; /* LPID comes from LPIDR */
++ prs = 1; /* process scoped */
++ r = 1; /* radix format */
++
++ asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
++ : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
++ trace_tlbie(lpid, 1, rb, rs, ric, prs, r);
++}
++
++
+ static inline void __tlbiel_va(unsigned long va, unsigned long pid,
+ unsigned long ap, unsigned long ric)
+ {
+@@ -150,6 +197,22 @@ static inline void __tlbie_va(unsigned long va, unsigned long pid,
+ trace_tlbie(0, 0, rb, rs, ric, prs, r);
+ }
+
++static inline void __tlbie_lpid_va(unsigned long va, unsigned long lpid,
++ unsigned long ap, unsigned long ric)
++{
++ unsigned long rb,rs,prs,r;
++
++ rb = va & ~(PPC_BITMASK(52, 63));
++ rb |= ap << PPC_BITLSHIFT(58);
++ rs = lpid;
++ prs = 0; /* partition scoped */
++ r = 1; /* radix format */
++
++ asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
++ : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
++ trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
++}
++
+ static inline void fixup_tlbie(void)
+ {
+ unsigned long pid = 0;
+@@ -161,6 +224,16 @@ static inline void fixup_tlbie(void)
+ }
+ }
+
++static inline void fixup_tlbie_lpid(unsigned long lpid)
++{
++ unsigned long va = ((1UL << 52) - 1);
++
++ if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
++ asm volatile("ptesync": : :"memory");
++ __tlbie_lpid_va(va, lpid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
++ }
++}
++
+ /*
+ * We use 128 set in radix mode and 256 set in hpt mode.
+ */
+@@ -214,6 +287,86 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
+ asm volatile("eieio; tlbsync; ptesync": : :"memory");
+ }
+
++static inline void _tlbiel_lpid(unsigned long lpid, unsigned long ric)
++{
++ int set;
++
++ VM_BUG_ON(mfspr(SPRN_LPID) != lpid);
++
++ asm volatile("ptesync": : :"memory");
++
++ /*
++ * Flush the first set of the TLB, and if we're doing a RIC_FLUSH_ALL,
++ * also flush the entire Page Walk Cache.
++ */
++ __tlbiel_lpid(lpid, 0, ric);
++
++ /* For PWC, only one flush is needed */
++ if (ric == RIC_FLUSH_PWC) {
++ asm volatile("ptesync": : :"memory");
++ return;
++ }
++
++ /* For the remaining sets, just flush the TLB */
++ for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++)
++ __tlbiel_lpid(lpid, set, RIC_FLUSH_TLB);
++
++ asm volatile("ptesync": : :"memory");
++ asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
++}
++
++static inline void _tlbie_lpid(unsigned long lpid, unsigned long ric)
++{
++ asm volatile("ptesync": : :"memory");
++
++ /*
++ * Workaround the fact that the "ric" argument to __tlbie_pid
++ * must be a compile-time contraint to match the "i" constraint
++ * in the asm statement.
++ */
++ switch (ric) {
++ case RIC_FLUSH_TLB:
++ __tlbie_lpid(lpid, RIC_FLUSH_TLB);
++ break;
++ case RIC_FLUSH_PWC:
++ __tlbie_lpid(lpid, RIC_FLUSH_PWC);
++ break;
++ case RIC_FLUSH_ALL:
++ default:
++ __tlbie_lpid(lpid, RIC_FLUSH_ALL);
++ }
++ fixup_tlbie_lpid(lpid);
++ asm volatile("eieio; tlbsync; ptesync": : :"memory");
++}
++
++static inline void _tlbiel_lpid_guest(unsigned long lpid, unsigned long ric)
++{
++ int set;
++
++ VM_BUG_ON(mfspr(SPRN_LPID) != lpid);
++
++ asm volatile("ptesync": : :"memory");
++
++ /*
++ * Flush the first set of the TLB, and if we're doing a RIC_FLUSH_ALL,
++ * also flush the entire Page Walk Cache.
++ */
++ __tlbiel_lpid_guest(lpid, 0, ric);
++
++ /* For PWC, only one flush is needed */
++ if (ric == RIC_FLUSH_PWC) {
++ asm volatile("ptesync": : :"memory");
++ return;
++ }
++
++ /* For the remaining sets, just flush the TLB */
++ for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++)
++ __tlbiel_lpid_guest(lpid, set, RIC_FLUSH_TLB);
++
++ asm volatile("ptesync": : :"memory");
++}
++
++
+ static inline void __tlbiel_va_range(unsigned long start, unsigned long end,
+ unsigned long pid, unsigned long page_size,
+ unsigned long psize)
+@@ -268,6 +421,17 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid,
+ asm volatile("eieio; tlbsync; ptesync": : :"memory");
+ }
+
++static inline void _tlbie_lpid_va(unsigned long va, unsigned long lpid,
++ unsigned long psize, unsigned long ric)
++{
++ unsigned long ap = mmu_get_ap(psize);
++
++ asm volatile("ptesync": : :"memory");
++ __tlbie_lpid_va(va, lpid, ap, ric);
++ fixup_tlbie_lpid(lpid);
++ asm volatile("eieio; tlbsync; ptesync": : :"memory");
++}
++
+ static inline void _tlbie_va_range(unsigned long start, unsigned long end,
+ unsigned long pid, unsigned long page_size,
+ unsigned long psize, bool also_pwc)
+@@ -534,6 +698,49 @@ static int radix_get_mmu_psize(int page_size)
+ return psize;
+ }
+
++/*
++ * Flush partition scoped LPID address translation for all CPUs.
++ */
++void radix__flush_tlb_lpid_page(unsigned int lpid,
++ unsigned long addr,
++ unsigned long page_size)
++{
++ int psize = radix_get_mmu_psize(page_size);
++
++ _tlbie_lpid_va(addr, lpid, psize, RIC_FLUSH_TLB);
++}
++EXPORT_SYMBOL_GPL(radix__flush_tlb_lpid_page);
++
++/*
++ * Flush partition scoped PWC from LPID for all CPUs.
++ */
++void radix__flush_pwc_lpid(unsigned int lpid)
++{
++ _tlbie_lpid(lpid, RIC_FLUSH_PWC);
++}
++EXPORT_SYMBOL_GPL(radix__flush_pwc_lpid);
++
++/*
++ * Flush partition scoped translations from LPID (=LPIDR)
++ */
++void radix__local_flush_tlb_lpid(unsigned int lpid)
++{
++ _tlbiel_lpid(lpid, RIC_FLUSH_ALL);
++}
++EXPORT_SYMBOL_GPL(radix__local_flush_tlb_lpid);
++
++/*
++ * Flush process scoped translations from LPID (=LPIDR).
++ * Important difference, the guest normally manages its own translations,
++ * but some cases e.g., vCPU CPU migration require KVM to flush.
++ */
++void radix__local_flush_tlb_lpid_guest(unsigned int lpid)
++{
++ _tlbiel_lpid_guest(lpid, RIC_FLUSH_ALL);
++}
++EXPORT_SYMBOL_GPL(radix__local_flush_tlb_lpid_guest);
++
++
+ static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
+ unsigned long end, int psize);
+
+--
+2.23.0
+
diff --git a/series.conf b/series.conf
index 4b597e036a..106d507b31 100644
--- a/series.conf
+++ b/series.conf
@@ -17294,6 +17294,7 @@
patches.suse/powerpc-powernv-cpuidle-Init-all-present-cpus-for-de.patch
patches.suse/powerpc-livepatch-fix-build-error-with-kprobes-disabled.patch
patches.suse/cxl-Configure-PSL-to-not-use-APC-virtual-machines.patch
+ patches.suse/powerpc-mm-radix-implement-LPID-based-TLB-flushes-to.patch
patches.suse/mm-powerpc-x86-define-VM_PKEY_BITx-bits-if-CONFIG_AR.patch
patches.suse/mm-powerpc-x86-introduce-an-additional-vma-bit-for-p.patch
patches.suse/mm-pkeys-Remove-include-of-asm-mmu_context.h-from-pk.patch