aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/accelerators/ocxl.rst5
-rw-r--r--arch/powerpc/boot/Makefile3
-rw-r--r--arch/powerpc/include/asm/book3s/64/mmu.h3
-rw-r--r--arch/powerpc/include/asm/book3s/64/tlbflush-radix.h3
-rw-r--r--arch/powerpc/include/asm/cputable.h4
-rw-r--r--arch/powerpc/include/asm/mmu_context.h18
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c7
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S2
-rw-r--r--arch/powerpc/kernel/irq.c8
-rw-r--r--arch/powerpc/kernel/prom_init.c1
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_radix.c3
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c11
-rw-r--r--arch/powerpc/mm/hash_native_64.c16
-rw-r--r--arch/powerpc/mm/mmu_context_book3s64.c1
-rw-r--r--arch/powerpc/mm/pgtable_64.c1
-rw-r--r--arch/powerpc/mm/tlb-radix.c169
-rw-r--r--drivers/misc/ocxl/file.c27
-rw-r--r--include/uapi/misc/ocxl.h17
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c14
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-trap.c2
21 files changed, 223 insertions, 94 deletions
diff --git a/Documentation/accelerators/ocxl.rst b/Documentation/accelerators/ocxl.rst
index 4f7af841d935..ddcc58d01cfb 100644
--- a/Documentation/accelerators/ocxl.rst
+++ b/Documentation/accelerators/ocxl.rst
@@ -152,6 +152,11 @@ OCXL_IOCTL_IRQ_SET_FD:
152 Associate an event fd to an AFU interrupt so that the user process 152 Associate an event fd to an AFU interrupt so that the user process
153 can be notified when the AFU sends an interrupt. 153 can be notified when the AFU sends an interrupt.
154 154
155OCXL_IOCTL_GET_METADATA:
156
157 Obtains configuration information from the card, such at the size of
158 MMIO areas, the AFU version, and the PASID for the current context.
159
155 160
156mmap 161mmap
157---- 162----
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ef6549e57157..26d5d2a5b8e9 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -101,7 +101,8 @@ $(addprefix $(obj)/,$(zlib-y)): \
101libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c 101libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
102libfdtheader := fdt.h libfdt.h libfdt_internal.h 102libfdtheader := fdt.h libfdt.h libfdt_internal.h
103 103
104$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o opal.o): \ 104$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o opal.o \
105 treeboot-akebono.o treeboot-currituck.o treeboot-iss4xx.o): \
105 $(addprefix $(obj)/,$(libfdtheader)) 106 $(addprefix $(obj)/,$(libfdtheader))
106 107
107src-wlib-y := string.S crt0.S stdio.c decompress.c main.c \ 108src-wlib-y := string.S crt0.S stdio.c decompress.c main.c \
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index 777778579305..c8c836e8ad1b 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -97,6 +97,9 @@ typedef struct {
97 /* Number of bits in the mm_cpumask */ 97 /* Number of bits in the mm_cpumask */
98 atomic_t active_cpus; 98 atomic_t active_cpus;
99 99
100 /* Number of users of the external (Nest) MMU */
101 atomic_t copros;
102
100 /* NPU NMMU context */ 103 /* NPU NMMU context */
101 struct npu_context *npu_context; 104 struct npu_context *npu_context;
102 105
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
index 8eea90f80e45..19b45ba6caf9 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
@@ -47,9 +47,6 @@ extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmad
47#endif 47#endif
48extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr); 48extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
49extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr); 49extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr);
50extern void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
51 unsigned long page_size);
52extern void radix__flush_tlb_lpid(unsigned long lpid);
53extern void radix__flush_tlb_all(void); 50extern void radix__flush_tlb_all(void);
54extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm, 51extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
55 unsigned long address); 52 unsigned long address);
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 734ff976b82f..66eba1e0007b 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -215,6 +215,7 @@ static inline void cpu_feature_keys_init(void) { }
215#define CPU_FTR_POWER9_DD2_1 LONG_ASM_CONST(0x0000080000000000) 215#define CPU_FTR_POWER9_DD2_1 LONG_ASM_CONST(0x0000080000000000)
216#define CPU_FTR_P9_TM_HV_ASSIST LONG_ASM_CONST(0x0000100000000000) 216#define CPU_FTR_P9_TM_HV_ASSIST LONG_ASM_CONST(0x0000100000000000)
217#define CPU_FTR_P9_TM_XER_SO_BUG LONG_ASM_CONST(0x0000200000000000) 217#define CPU_FTR_P9_TM_XER_SO_BUG LONG_ASM_CONST(0x0000200000000000)
218#define CPU_FTR_P9_TLBIE_BUG LONG_ASM_CONST(0x0000400000000000)
218 219
219#ifndef __ASSEMBLY__ 220#ifndef __ASSEMBLY__
220 221
@@ -465,7 +466,8 @@ static inline void cpu_feature_keys_init(void) { }
465 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ 466 CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
466 CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ 467 CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
467 CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ 468 CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
468 CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY) 469 CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \
470 CPU_FTR_P9_TLBIE_BUG)
469#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ 471#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
470 (~CPU_FTR_SAO)) 472 (~CPU_FTR_SAO))
471#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9 473#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index 051b3d63afe3..3a15b6db9501 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -92,15 +92,23 @@ static inline void dec_mm_active_cpus(struct mm_struct *mm)
92static inline void mm_context_add_copro(struct mm_struct *mm) 92static inline void mm_context_add_copro(struct mm_struct *mm)
93{ 93{
94 /* 94 /*
95 * On hash, should only be called once over the lifetime of 95 * If any copro is in use, increment the active CPU count
96 * the context, as we can't decrement the active cpus count 96 * in order to force TLB invalidations to be global as to
97 * and flush properly for the time being. 97 * propagate to the Nest MMU.
98 */ 98 */
99 inc_mm_active_cpus(mm); 99 if (atomic_inc_return(&mm->context.copros) == 1)
100 inc_mm_active_cpus(mm);
100} 101}
101 102
102static inline void mm_context_remove_copro(struct mm_struct *mm) 103static inline void mm_context_remove_copro(struct mm_struct *mm)
103{ 104{
105 int c;
106
107 c = atomic_dec_if_positive(&mm->context.copros);
108
109 /* Detect imbalance between add and remove */
110 WARN_ON(c < 0);
111
104 /* 112 /*
105 * Need to broadcast a global flush of the full mm before 113 * Need to broadcast a global flush of the full mm before
106 * decrementing active_cpus count, as the next TLBI may be 114 * decrementing active_cpus count, as the next TLBI may be
@@ -111,7 +119,7 @@ static inline void mm_context_remove_copro(struct mm_struct *mm)
111 * for the time being. Invalidations will remain global if 119 * for the time being. Invalidations will remain global if
112 * used on hash. 120 * used on hash.
113 */ 121 */
114 if (radix_enabled()) { 122 if (c == 0 && radix_enabled()) {
115 flush_all_mm(mm); 123 flush_all_mm(mm);
116 dec_mm_active_cpus(mm); 124 dec_mm_active_cpus(mm);
117 } 125 }
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 0af2c5dc5162..4313ff07edca 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -714,8 +714,10 @@ static __init void cpufeatures_cpu_quirks(void)
714 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST | 714 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST |
715 CPU_FTR_P9_TM_XER_SO_BUG; 715 CPU_FTR_P9_TM_XER_SO_BUG;
716 716
717 if ((version & 0xffff0000) == 0x004e0000) 717 if ((version & 0xffff0000) == 0x004e0000) {
718 cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); 718 cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR);
719 cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_BUG;
720 }
719} 721}
720 722
721static void __init cpufeatures_setup_finished(void) 723static void __init cpufeatures_setup_finished(void)
@@ -727,6 +729,9 @@ static void __init cpufeatures_setup_finished(void)
727 cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE; 729 cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE;
728 } 730 }
729 731
732 /* Make sure powerpc_base_platform is non-NULL */
733 powerpc_base_platform = cur_cpu_spec->platform;
734
730 system_registers.lpcr = mfspr(SPRN_LPCR); 735 system_registers.lpcr = mfspr(SPRN_LPCR);
731 system_registers.hfscr = mfspr(SPRN_HFSCR); 736 system_registers.hfscr = mfspr(SPRN_HFSCR);
732 system_registers.fscr = mfspr(SPRN_FSCR); 737 system_registers.fscr = mfspr(SPRN_FSCR);
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index a19fbaa8e873..6bee20c43feb 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -706,7 +706,7 @@ EXC_COMMON_BEGIN(bad_addr_slb)
706 ld r3, PACA_EXSLB+EX_DAR(r13) 706 ld r3, PACA_EXSLB+EX_DAR(r13)
707 std r3, _DAR(r1) 707 std r3, _DAR(r1)
708 beq cr6, 2f 708 beq cr6, 2f
709 li r10, 0x480 /* fix trap number for I-SLB miss */ 709 li r10, 0x481 /* fix trap number for I-SLB miss */
710 std r10, _TRAP(r1) 710 std r10, _TRAP(r1)
7112: bl save_nvgprs 7112: bl save_nvgprs
712 addi r3, r1, STACK_FRAME_OVERHEAD 712 addi r3, r1, STACK_FRAME_OVERHEAD
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index f88038847790..061aa0f47bb1 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -476,6 +476,14 @@ void force_external_irq_replay(void)
476 */ 476 */
477 WARN_ON(!arch_irqs_disabled()); 477 WARN_ON(!arch_irqs_disabled());
478 478
479 /*
480 * Interrupts must always be hard disabled before irq_happened is
481 * modified (to prevent lost update in case of interrupt between
482 * load and store).
483 */
484 __hard_irq_disable();
485 local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
486
479 /* Indicate in the PACA that we have an interrupt to replay */ 487 /* Indicate in the PACA that we have an interrupt to replay */
480 local_paca->irq_happened |= PACA_IRQ_EE; 488 local_paca->irq_happened |= PACA_IRQ_EE;
481} 489}
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 8ca3f4c915e3..0323e073341d 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -874,7 +874,6 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
874 .mmu = 0, 874 .mmu = 0,
875 .hash_ext = 0, 875 .hash_ext = 0,
876 .radix_ext = 0, 876 .radix_ext = 0,
877 .byte22 = 0,
878 }, 877 },
879 878
880 /* option vector 6: IBM PAPR hints */ 879 /* option vector 6: IBM PAPR hints */
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index 0c854816e653..0837b9738d76 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -157,6 +157,9 @@ static void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
157 asm volatile("ptesync": : :"memory"); 157 asm volatile("ptesync": : :"memory");
158 asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1) 158 asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
159 : : "r" (addr), "r" (kvm->arch.lpid) : "memory"); 159 : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
160 if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG))
161 asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
162 : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
160 asm volatile("ptesync": : :"memory"); 163 asm volatile("ptesync": : :"memory");
161} 164}
162 165
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 8888e625a999..e1c083fbe434 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -473,6 +473,17 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
473 trace_tlbie(kvm->arch.lpid, 0, rbvalues[i], 473 trace_tlbie(kvm->arch.lpid, 0, rbvalues[i],
474 kvm->arch.lpid, 0, 0, 0); 474 kvm->arch.lpid, 0, 0, 0);
475 } 475 }
476
477 if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
478 /*
479 * Need the extra ptesync to make sure we don't
480 * re-order the tlbie
481 */
482 asm volatile("ptesync": : :"memory");
483 asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
484 "r" (rbvalues[0]), "r" (kvm->arch.lpid));
485 }
486
476 asm volatile("eieio; tlbsync; ptesync" : : : "memory"); 487 asm volatile("eieio; tlbsync; ptesync" : : : "memory");
477 kvm->arch.tlbie_lock = 0; 488 kvm->arch.tlbie_lock = 0;
478 } else { 489 } else {
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 993842f1ed60..1d049c78c82a 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -201,6 +201,15 @@ static inline unsigned long ___tlbie(unsigned long vpn, int psize,
201 return va; 201 return va;
202} 202}
203 203
204static inline void fixup_tlbie(unsigned long vpn, int psize, int apsize, int ssize)
205{
206 if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
207 /* Need the extra ptesync to ensure we don't reorder tlbie*/
208 asm volatile("ptesync": : :"memory");
209 ___tlbie(vpn, psize, apsize, ssize);
210 }
211}
212
204static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) 213static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
205{ 214{
206 unsigned long rb; 215 unsigned long rb;
@@ -278,6 +287,7 @@ static inline void tlbie(unsigned long vpn, int psize, int apsize,
278 asm volatile("ptesync": : :"memory"); 287 asm volatile("ptesync": : :"memory");
279 } else { 288 } else {
280 __tlbie(vpn, psize, apsize, ssize); 289 __tlbie(vpn, psize, apsize, ssize);
290 fixup_tlbie(vpn, psize, apsize, ssize);
281 asm volatile("eieio; tlbsync; ptesync": : :"memory"); 291 asm volatile("eieio; tlbsync; ptesync": : :"memory");
282 } 292 }
283 if (lock_tlbie && !use_local) 293 if (lock_tlbie && !use_local)
@@ -771,7 +781,7 @@ static void native_hpte_clear(void)
771 */ 781 */
772static void native_flush_hash_range(unsigned long number, int local) 782static void native_flush_hash_range(unsigned long number, int local)
773{ 783{
774 unsigned long vpn; 784 unsigned long vpn = 0;
775 unsigned long hash, index, hidx, shift, slot; 785 unsigned long hash, index, hidx, shift, slot;
776 struct hash_pte *hptep; 786 struct hash_pte *hptep;
777 unsigned long hpte_v; 787 unsigned long hpte_v;
@@ -843,6 +853,10 @@ static void native_flush_hash_range(unsigned long number, int local)
843 __tlbie(vpn, psize, psize, ssize); 853 __tlbie(vpn, psize, psize, ssize);
844 } pte_iterate_hashed_end(); 854 } pte_iterate_hashed_end();
845 } 855 }
856 /*
857 * Just do one more with the last used values.
858 */
859 fixup_tlbie(vpn, psize, psize, ssize);
846 asm volatile("eieio; tlbsync; ptesync":::"memory"); 860 asm volatile("eieio; tlbsync; ptesync":::"memory");
847 861
848 if (lock_tlbie) 862 if (lock_tlbie)
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c
index 80acad52b006..422be81bf69f 100644
--- a/arch/powerpc/mm/mmu_context_book3s64.c
+++ b/arch/powerpc/mm/mmu_context_book3s64.c
@@ -166,6 +166,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
166 mm_iommu_init(mm); 166 mm_iommu_init(mm);
167#endif 167#endif
168 atomic_set(&mm->context.active_cpus, 0); 168 atomic_set(&mm->context.active_cpus, 0);
169 atomic_set(&mm->context.copros, 0);
169 170
170 return 0; 171 return 0;
171} 172}
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 28c980eb4422..adf469f312f2 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -481,6 +481,7 @@ void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
481 "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); 481 "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
482 trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0); 482 trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0);
483 } 483 }
484 /* do we need fixup here ?*/
484 asm volatile("eieio; tlbsync; ptesync" : : : "memory"); 485 asm volatile("eieio; tlbsync; ptesync" : : : "memory");
485} 486}
486EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry); 487EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 001c1f6458b6..291eab4ed7cd 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -119,6 +119,49 @@ static inline void __tlbie_pid(unsigned long pid, unsigned long ric)
119 trace_tlbie(0, 0, rb, rs, ric, prs, r); 119 trace_tlbie(0, 0, rb, rs, ric, prs, r);
120} 120}
121 121
122static inline void __tlbiel_va(unsigned long va, unsigned long pid,
123 unsigned long ap, unsigned long ric)
124{
125 unsigned long rb,rs,prs,r;
126
127 rb = va & ~(PPC_BITMASK(52, 63));
128 rb |= ap << PPC_BITLSHIFT(58);
129 rs = pid << PPC_BITLSHIFT(31);
130 prs = 1; /* process scoped */
131 r = 1; /* radix format */
132
133 asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
134 : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
135 trace_tlbie(0, 1, rb, rs, ric, prs, r);
136}
137
138static inline void __tlbie_va(unsigned long va, unsigned long pid,
139 unsigned long ap, unsigned long ric)
140{
141 unsigned long rb,rs,prs,r;
142
143 rb = va & ~(PPC_BITMASK(52, 63));
144 rb |= ap << PPC_BITLSHIFT(58);
145 rs = pid << PPC_BITLSHIFT(31);
146 prs = 1; /* process scoped */
147 r = 1; /* radix format */
148
149 asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
150 : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
151 trace_tlbie(0, 0, rb, rs, ric, prs, r);
152}
153
154static inline void fixup_tlbie(void)
155{
156 unsigned long pid = 0;
157 unsigned long va = ((1UL << 52) - 1);
158
159 if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
160 asm volatile("ptesync": : :"memory");
161 __tlbie_va(va, pid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
162 }
163}
164
122/* 165/*
123 * We use 128 set in radix mode and 256 set in hpt mode. 166 * We use 128 set in radix mode and 256 set in hpt mode.
124 */ 167 */
@@ -151,24 +194,25 @@ static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
151static inline void _tlbie_pid(unsigned long pid, unsigned long ric) 194static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
152{ 195{
153 asm volatile("ptesync": : :"memory"); 196 asm volatile("ptesync": : :"memory");
154 __tlbie_pid(pid, ric);
155 asm volatile("eieio; tlbsync; ptesync": : :"memory");
156}
157 197
158static inline void __tlbiel_va(unsigned long va, unsigned long pid, 198 /*
159 unsigned long ap, unsigned long ric) 199 * Workaround the fact that the "ric" argument to __tlbie_pid
160{ 200 * must be a compile-time contraint to match the "i" constraint
161 unsigned long rb,rs,prs,r; 201 * in the asm statement.
162 202 */
163 rb = va & ~(PPC_BITMASK(52, 63)); 203 switch (ric) {
164 rb |= ap << PPC_BITLSHIFT(58); 204 case RIC_FLUSH_TLB:
165 rs = pid << PPC_BITLSHIFT(31); 205 __tlbie_pid(pid, RIC_FLUSH_TLB);
166 prs = 1; /* process scoped */ 206 break;
167 r = 1; /* radix format */ 207 case RIC_FLUSH_PWC:
168 208 __tlbie_pid(pid, RIC_FLUSH_PWC);
169 asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) 209 break;
170 : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); 210 case RIC_FLUSH_ALL:
171 trace_tlbie(0, 1, rb, rs, ric, prs, r); 211 default:
212 __tlbie_pid(pid, RIC_FLUSH_ALL);
213 }
214 fixup_tlbie();
215 asm volatile("eieio; tlbsync; ptesync": : :"memory");
172} 216}
173 217
174static inline void __tlbiel_va_range(unsigned long start, unsigned long end, 218static inline void __tlbiel_va_range(unsigned long start, unsigned long end,
@@ -203,22 +247,6 @@ static inline void _tlbiel_va_range(unsigned long start, unsigned long end,
203 asm volatile("ptesync": : :"memory"); 247 asm volatile("ptesync": : :"memory");
204} 248}
205 249
206static inline void __tlbie_va(unsigned long va, unsigned long pid,
207 unsigned long ap, unsigned long ric)
208{
209 unsigned long rb,rs,prs,r;
210
211 rb = va & ~(PPC_BITMASK(52, 63));
212 rb |= ap << PPC_BITLSHIFT(58);
213 rs = pid << PPC_BITLSHIFT(31);
214 prs = 1; /* process scoped */
215 r = 1; /* radix format */
216
217 asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
218 : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
219 trace_tlbie(0, 0, rb, rs, ric, prs, r);
220}
221
222static inline void __tlbie_va_range(unsigned long start, unsigned long end, 250static inline void __tlbie_va_range(unsigned long start, unsigned long end,
223 unsigned long pid, unsigned long page_size, 251 unsigned long pid, unsigned long page_size,
224 unsigned long psize) 252 unsigned long psize)
@@ -237,6 +265,7 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid,
237 265
238 asm volatile("ptesync": : :"memory"); 266 asm volatile("ptesync": : :"memory");
239 __tlbie_va(va, pid, ap, ric); 267 __tlbie_va(va, pid, ap, ric);
268 fixup_tlbie();
240 asm volatile("eieio; tlbsync; ptesync": : :"memory"); 269 asm volatile("eieio; tlbsync; ptesync": : :"memory");
241} 270}
242 271
@@ -248,6 +277,7 @@ static inline void _tlbie_va_range(unsigned long start, unsigned long end,
248 if (also_pwc) 277 if (also_pwc)
249 __tlbie_pid(pid, RIC_FLUSH_PWC); 278 __tlbie_pid(pid, RIC_FLUSH_PWC);
250 __tlbie_va_range(start, end, pid, page_size, psize); 279 __tlbie_va_range(start, end, pid, page_size, psize);
280 fixup_tlbie();
251 asm volatile("eieio; tlbsync; ptesync": : :"memory"); 281 asm volatile("eieio; tlbsync; ptesync": : :"memory");
252} 282}
253 283
@@ -311,6 +341,16 @@ void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmadd
311} 341}
312EXPORT_SYMBOL(radix__local_flush_tlb_page); 342EXPORT_SYMBOL(radix__local_flush_tlb_page);
313 343
344static bool mm_needs_flush_escalation(struct mm_struct *mm)
345{
346 /*
347 * P9 nest MMU has issues with the page walk cache
348 * caching PTEs and not flushing them properly when
349 * RIC = 0 for a PID/LPID invalidate
350 */
351 return atomic_read(&mm->context.copros) != 0;
352}
353
314#ifdef CONFIG_SMP 354#ifdef CONFIG_SMP
315void radix__flush_tlb_mm(struct mm_struct *mm) 355void radix__flush_tlb_mm(struct mm_struct *mm)
316{ 356{
@@ -321,9 +361,12 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
321 return; 361 return;
322 362
323 preempt_disable(); 363 preempt_disable();
324 if (!mm_is_thread_local(mm)) 364 if (!mm_is_thread_local(mm)) {
325 _tlbie_pid(pid, RIC_FLUSH_TLB); 365 if (mm_needs_flush_escalation(mm))
326 else 366 _tlbie_pid(pid, RIC_FLUSH_ALL);
367 else
368 _tlbie_pid(pid, RIC_FLUSH_TLB);
369 } else
327 _tlbiel_pid(pid, RIC_FLUSH_TLB); 370 _tlbiel_pid(pid, RIC_FLUSH_TLB);
328 preempt_enable(); 371 preempt_enable();
329} 372}
@@ -435,10 +478,14 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
435 } 478 }
436 479
437 if (full) { 480 if (full) {
438 if (local) 481 if (local) {
439 _tlbiel_pid(pid, RIC_FLUSH_TLB); 482 _tlbiel_pid(pid, RIC_FLUSH_TLB);
440 else 483 } else {
441 _tlbie_pid(pid, RIC_FLUSH_TLB); 484 if (mm_needs_flush_escalation(mm))
485 _tlbie_pid(pid, RIC_FLUSH_ALL);
486 else
487 _tlbie_pid(pid, RIC_FLUSH_TLB);
488 }
442 } else { 489 } else {
443 bool hflush = false; 490 bool hflush = false;
444 unsigned long hstart, hend; 491 unsigned long hstart, hend;
@@ -465,6 +512,7 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
465 if (hflush) 512 if (hflush)
466 __tlbie_va_range(hstart, hend, pid, 513 __tlbie_va_range(hstart, hend, pid,
467 HPAGE_PMD_SIZE, MMU_PAGE_2M); 514 HPAGE_PMD_SIZE, MMU_PAGE_2M);
515 fixup_tlbie();
468 asm volatile("eieio; tlbsync; ptesync": : :"memory"); 516 asm volatile("eieio; tlbsync; ptesync": : :"memory");
469 } 517 }
470 } 518 }
@@ -548,6 +596,9 @@ static inline void __radix__flush_tlb_range_psize(struct mm_struct *mm,
548 } 596 }
549 597
550 if (full) { 598 if (full) {
599 if (!local && mm_needs_flush_escalation(mm))
600 also_pwc = true;
601
551 if (local) 602 if (local)
552 _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB); 603 _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB);
553 else 604 else
@@ -603,46 +654,6 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr)
603} 654}
604#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 655#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
605 656
606void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
607 unsigned long page_size)
608{
609 unsigned long rb,rs,prs,r;
610 unsigned long ap;
611 unsigned long ric = RIC_FLUSH_TLB;
612
613 ap = mmu_get_ap(radix_get_mmu_psize(page_size));
614 rb = gpa & ~(PPC_BITMASK(52, 63));
615 rb |= ap << PPC_BITLSHIFT(58);
616 rs = lpid & ((1UL << 32) - 1);
617 prs = 0; /* process scoped */
618 r = 1; /* radix format */
619
620 asm volatile("ptesync": : :"memory");
621 asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
622 : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
623 asm volatile("eieio; tlbsync; ptesync": : :"memory");
624 trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
625}
626EXPORT_SYMBOL(radix__flush_tlb_lpid_va);
627
628void radix__flush_tlb_lpid(unsigned long lpid)
629{
630 unsigned long rb,rs,prs,r;
631 unsigned long ric = RIC_FLUSH_ALL;
632
633 rb = 0x2 << PPC_BITLSHIFT(53); /* IS = 2 */
634 rs = lpid & ((1UL << 32) - 1);
635 prs = 0; /* partition scoped */
636 r = 1; /* radix format */
637
638 asm volatile("ptesync": : :"memory");
639 asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
640 : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
641 asm volatile("eieio; tlbsync; ptesync": : :"memory");
642 trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
643}
644EXPORT_SYMBOL(radix__flush_tlb_lpid);
645
646void radix__flush_pmd_tlb_range(struct vm_area_struct *vma, 657void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
647 unsigned long start, unsigned long end) 658 unsigned long start, unsigned long end)
648{ 659{
diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c
index 337462e1569f..038509e5d031 100644
--- a/drivers/misc/ocxl/file.c
+++ b/drivers/misc/ocxl/file.c
@@ -102,10 +102,32 @@ static long afu_ioctl_attach(struct ocxl_context *ctx,
102 return rc; 102 return rc;
103} 103}
104 104
105static long afu_ioctl_get_metadata(struct ocxl_context *ctx,
106 struct ocxl_ioctl_metadata __user *uarg)
107{
108 struct ocxl_ioctl_metadata arg;
109
110 memset(&arg, 0, sizeof(arg));
111
112 arg.version = 0;
113
114 arg.afu_version_major = ctx->afu->config.version_major;
115 arg.afu_version_minor = ctx->afu->config.version_minor;
116 arg.pasid = ctx->pasid;
117 arg.pp_mmio_size = ctx->afu->config.pp_mmio_stride;
118 arg.global_mmio_size = ctx->afu->config.global_mmio_size;
119
120 if (copy_to_user(uarg, &arg, sizeof(arg)))
121 return -EFAULT;
122
123 return 0;
124}
125
105#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \ 126#define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \
106 x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \ 127 x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \
107 x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \ 128 x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \
108 x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \ 129 x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \
130 x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \
109 "UNKNOWN") 131 "UNKNOWN")
110 132
111static long afu_ioctl(struct file *file, unsigned int cmd, 133static long afu_ioctl(struct file *file, unsigned int cmd,
@@ -159,6 +181,11 @@ static long afu_ioctl(struct file *file, unsigned int cmd,
159 irq_fd.eventfd); 181 irq_fd.eventfd);
160 break; 182 break;
161 183
184 case OCXL_IOCTL_GET_METADATA:
185 rc = afu_ioctl_get_metadata(ctx,
186 (struct ocxl_ioctl_metadata __user *) args);
187 break;
188
162 default: 189 default:
163 rc = -EINVAL; 190 rc = -EINVAL;
164 } 191 }
diff --git a/include/uapi/misc/ocxl.h b/include/uapi/misc/ocxl.h
index 4b0b0b756f3e..0af83d80fb3e 100644
--- a/include/uapi/misc/ocxl.h
+++ b/include/uapi/misc/ocxl.h
@@ -32,6 +32,22 @@ struct ocxl_ioctl_attach {
32 __u64 reserved3; 32 __u64 reserved3;
33}; 33};
34 34
35struct ocxl_ioctl_metadata {
36 __u16 version; // struct version, always backwards compatible
37
38 // Version 0 fields
39 __u8 afu_version_major;
40 __u8 afu_version_minor;
41 __u32 pasid; // PASID assigned to the current context
42
43 __u64 pp_mmio_size; // Per PASID MMIO size
44 __u64 global_mmio_size;
45
46 // End version 0 fields
47
48 __u64 reserved[13]; // Total of 16*u64
49};
50
35struct ocxl_ioctl_irq_fd { 51struct ocxl_ioctl_irq_fd {
36 __u64 irq_offset; 52 __u64 irq_offset;
37 __s32 eventfd; 53 __s32 eventfd;
@@ -45,5 +61,6 @@ struct ocxl_ioctl_irq_fd {
45#define OCXL_IOCTL_IRQ_ALLOC _IOR(OCXL_MAGIC, 0x11, __u64) 61#define OCXL_IOCTL_IRQ_ALLOC _IOR(OCXL_MAGIC, 0x11, __u64)
46#define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64) 62#define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64)
47#define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd) 63#define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
64#define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata)
48 65
49#endif /* _UAPI_MISC_OCXL_H */ 66#endif /* _UAPI_MISC_OCXL_H */
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c
index 35ade7406dcd..3ae77ba93208 100644
--- a/tools/testing/selftests/powerpc/mm/subpage_prot.c
+++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c
@@ -135,6 +135,16 @@ static int run_test(void *addr, unsigned long size)
135 return 0; 135 return 0;
136} 136}
137 137
138static int syscall_available(void)
139{
140 int rc;
141
142 errno = 0;
143 rc = syscall(__NR_subpage_prot, 0, 0, 0);
144
145 return rc == 0 || (errno != ENOENT && errno != ENOSYS);
146}
147
138int test_anon(void) 148int test_anon(void)
139{ 149{
140 unsigned long align; 150 unsigned long align;
@@ -145,6 +155,8 @@ int test_anon(void)
145 void *mallocblock; 155 void *mallocblock;
146 unsigned long mallocsize; 156 unsigned long mallocsize;
147 157
158 SKIP_IF(!syscall_available());
159
148 if (getpagesize() != 0x10000) { 160 if (getpagesize() != 0x10000) {
149 fprintf(stderr, "Kernel page size must be 64K!\n"); 161 fprintf(stderr, "Kernel page size must be 64K!\n");
150 return 1; 162 return 1;
@@ -180,6 +192,8 @@ int test_file(void)
180 off_t filesize; 192 off_t filesize;
181 int fd; 193 int fd;
182 194
195 SKIP_IF(!syscall_available());
196
183 fd = open(file_name, O_RDWR); 197 fd = open(file_name, O_RDWR);
184 if (fd == -1) { 198 if (fd == -1) {
185 perror("failed to open file"); 199 perror("failed to open file");
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 1c9e5d0a0491..c0e45d2dde25 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -16,7 +16,7 @@ $(OUTPUT)/tm-syscall: tm-syscall-asm.S
16$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 16$(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
17$(OUTPUT)/tm-tmspr: CFLAGS += -pthread 17$(OUTPUT)/tm-tmspr: CFLAGS += -pthread
18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 18$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.o 19$(OUTPUT)/tm-resched-dscr: ../pmu/lib.c
20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx 20$(OUTPUT)/tm-unavailable: CFLAGS += -O0 -pthread -m64 -Wno-error=uninitialized -mvsx
21$(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64 21$(OUTPUT)/tm-trap: CFLAGS += -O0 -pthread -m64
22 22
diff --git a/tools/testing/selftests/powerpc/tm/tm-trap.c b/tools/testing/selftests/powerpc/tm/tm-trap.c
index 5d92c23ee6cb..179d592f0073 100644
--- a/tools/testing/selftests/powerpc/tm/tm-trap.c
+++ b/tools/testing/selftests/powerpc/tm/tm-trap.c
@@ -255,6 +255,8 @@ int tm_trap_test(void)
255 255
256 struct sigaction trap_sa; 256 struct sigaction trap_sa;
257 257
258 SKIP_IF(!have_htm());
259
258 trap_sa.sa_flags = SA_SIGINFO; 260 trap_sa.sa_flags = SA_SIGINFO;
259 trap_sa.sa_sigaction = trap_signal_handler; 261 trap_sa.sa_sigaction = trap_signal_handler;
260 sigaction(SIGTRAP, &trap_sa, NULL); 262 sigaction(SIGTRAP, &trap_sa, NULL);