summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/mmu_context.h46
-rw-r--r--arch/powerpc/mm/mmu_context.c9
-rw-r--r--drivers/misc/cxl/api.c16
-rw-r--r--drivers/misc/cxl/context.c3
-rw-r--r--drivers/misc/cxl/file.c24
5 files changed, 84 insertions, 14 deletions
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index 309592589e30..a0d7145d6cd2 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -77,6 +77,52 @@ extern void switch_cop(struct mm_struct *next);
77extern int use_cop(unsigned long acop, struct mm_struct *mm); 77extern int use_cop(unsigned long acop, struct mm_struct *mm);
78extern void drop_cop(unsigned long acop, struct mm_struct *mm); 78extern void drop_cop(unsigned long acop, struct mm_struct *mm);
79 79
80#ifdef CONFIG_PPC_BOOK3S_64
81static inline void inc_mm_active_cpus(struct mm_struct *mm)
82{
83 atomic_inc(&mm->context.active_cpus);
84}
85
86static inline void dec_mm_active_cpus(struct mm_struct *mm)
87{
88 atomic_dec(&mm->context.active_cpus);
89}
90
91static inline void mm_context_add_copro(struct mm_struct *mm)
92{
93 /*
94 * On hash, should only be called once over the lifetime of
95 * the context, as we can't decrement the active cpus count
96 * and flush properly for the time being.
97 */
98 inc_mm_active_cpus(mm);
99}
100
101static inline void mm_context_remove_copro(struct mm_struct *mm)
102{
103 /*
104 * Need to broadcast a global flush of the full mm before
105 * decrementing active_cpus count, as the next TLBI may be
106 * local and the nMMU and/or PSL need to be cleaned up.
107 * Should be rare enough so that it's acceptable.
108 *
109 * Skip on hash, as we don't know how to do the proper flush
110 * for the time being. Invalidations will remain global if
111 * used on hash.
112 */
113 if (radix_enabled()) {
114 flush_all_mm(mm);
115 dec_mm_active_cpus(mm);
116 }
117}
118#else
119static inline void inc_mm_active_cpus(struct mm_struct *mm) { }
120static inline void dec_mm_active_cpus(struct mm_struct *mm) { }
121static inline void mm_context_add_copro(struct mm_struct *mm) { }
122static inline void mm_context_remove_copro(struct mm_struct *mm) { }
123#endif
124
125
80extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, 126extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
81 struct task_struct *tsk); 127 struct task_struct *tsk);
82 128
diff --git a/arch/powerpc/mm/mmu_context.c b/arch/powerpc/mm/mmu_context.c
index 0f613bc63c50..d60a62bf4fc7 100644
--- a/arch/powerpc/mm/mmu_context.c
+++ b/arch/powerpc/mm/mmu_context.c
@@ -34,15 +34,6 @@ static inline void switch_mm_pgdir(struct task_struct *tsk,
34 struct mm_struct *mm) { } 34 struct mm_struct *mm) { }
35#endif 35#endif
36 36
37#ifdef CONFIG_PPC_BOOK3S_64
38static inline void inc_mm_active_cpus(struct mm_struct *mm)
39{
40 atomic_inc(&mm->context.active_cpus);
41}
42#else
43static inline void inc_mm_active_cpus(struct mm_struct *mm) { }
44#endif
45
46void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, 37void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
47 struct task_struct *tsk) 38 struct task_struct *tsk)
48{ 39{
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c
index a0c44d16bf30..7c11bad5cded 100644
--- a/drivers/misc/cxl/api.c
+++ b/drivers/misc/cxl/api.c
@@ -15,6 +15,7 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/mount.h> 16#include <linux/mount.h>
17#include <linux/sched/mm.h> 17#include <linux/sched/mm.h>
18#include <linux/mmu_context.h>
18 19
19#include "cxl.h" 20#include "cxl.h"
20 21
@@ -331,9 +332,12 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
331 /* ensure this mm_struct can't be freed */ 332 /* ensure this mm_struct can't be freed */
332 cxl_context_mm_count_get(ctx); 333 cxl_context_mm_count_get(ctx);
333 334
334 /* decrement the use count */ 335 if (ctx->mm) {
335 if (ctx->mm) 336 /* decrement the use count from above */
336 mmput(ctx->mm); 337 mmput(ctx->mm);
338 /* make TLBIs for this context global */
339 mm_context_add_copro(ctx->mm);
340 }
337 } 341 }
338 342
339 /* 343 /*
@@ -342,13 +346,19 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
342 */ 346 */
343 cxl_ctx_get(); 347 cxl_ctx_get();
344 348
349 /* See the comment in afu_ioctl_start_work() */
350 smp_mb();
351
345 if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { 352 if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
346 put_pid(ctx->pid); 353 put_pid(ctx->pid);
347 ctx->pid = NULL; 354 ctx->pid = NULL;
348 cxl_adapter_context_put(ctx->afu->adapter); 355 cxl_adapter_context_put(ctx->afu->adapter);
349 cxl_ctx_put(); 356 cxl_ctx_put();
350 if (task) 357 if (task) {
351 cxl_context_mm_count_put(ctx); 358 cxl_context_mm_count_put(ctx);
359 if (ctx->mm)
360 mm_context_remove_copro(ctx->mm);
361 }
352 goto out; 362 goto out;
353 } 363 }
354 364
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index 8c32040b9c09..12a41b2753f0 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/idr.h> 19#include <linux/idr.h>
20#include <linux/sched/mm.h> 20#include <linux/sched/mm.h>
21#include <linux/mmu_context.h>
21#include <asm/cputable.h> 22#include <asm/cputable.h>
22#include <asm/current.h> 23#include <asm/current.h>
23#include <asm/copro.h> 24#include <asm/copro.h>
@@ -267,6 +268,8 @@ int __detach_context(struct cxl_context *ctx)
267 268
268 /* Decrease the mm count on the context */ 269 /* Decrease the mm count on the context */
269 cxl_context_mm_count_put(ctx); 270 cxl_context_mm_count_put(ctx);
271 if (ctx->mm)
272 mm_context_remove_copro(ctx->mm);
270 ctx->mm = NULL; 273 ctx->mm = NULL;
271 274
272 return 0; 275 return 0;
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 4bfad9f6dc9f..76c0b0ca9388 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -19,6 +19,7 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/sched/mm.h> 21#include <linux/sched/mm.h>
22#include <linux/mmu_context.h>
22#include <asm/cputable.h> 23#include <asm/cputable.h>
23#include <asm/current.h> 24#include <asm/current.h>
24#include <asm/copro.h> 25#include <asm/copro.h>
@@ -220,9 +221,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
220 /* ensure this mm_struct can't be freed */ 221 /* ensure this mm_struct can't be freed */
221 cxl_context_mm_count_get(ctx); 222 cxl_context_mm_count_get(ctx);
222 223
223 /* decrement the use count */ 224 if (ctx->mm) {
224 if (ctx->mm) 225 /* decrement the use count from above */
225 mmput(ctx->mm); 226 mmput(ctx->mm);
227 /* make TLBIs for this context global */
228 mm_context_add_copro(ctx->mm);
229 }
226 230
227 /* 231 /*
228 * Increment driver use count. Enables global TLBIs for hash 232 * Increment driver use count. Enables global TLBIs for hash
@@ -230,6 +234,20 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
230 */ 234 */
231 cxl_ctx_get(); 235 cxl_ctx_get();
232 236
237 /*
238 * A barrier is needed to make sure all TLBIs are global
239 * before we attach and the context starts being used by the
240 * adapter.
241 *
242 * Needed after mm_context_add_copro() for radix and
243 * cxl_ctx_get() for hash/p8.
244 *
245 * The barrier should really be mb(), since it involves a
246 * device. However, it's only useful when we have local
247 * vs. global TLBIs, i.e SMP=y. So keep smp_mb().
248 */
249 smp_mb();
250
233 trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); 251 trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
234 252
235 if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, 253 if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
@@ -240,6 +258,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
240 ctx->pid = NULL; 258 ctx->pid = NULL;
241 cxl_ctx_put(); 259 cxl_ctx_put();
242 cxl_context_mm_count_put(ctx); 260 cxl_context_mm_count_put(ctx);
261 if (ctx->mm)
262 mm_context_remove_copro(ctx->mm);
243 goto out; 263 goto out;
244 } 264 }
245 265