4
4
*/
5
5
6
6
#include <linux/bitops.h>
7
+ #include <linux/cpu.h>
7
8
#include <linux/kernel.h>
8
9
#include <linux/mm.h>
9
10
#include <linux/prctl.h>
@@ -26,6 +27,8 @@ u64 gcr_kernel_excl __ro_after_init;
26
27
27
28
static bool report_fault_once = true;
28
29
30
+ static DEFINE_PER_CPU_READ_MOSTLY (u64 , mte_tcf_preferred ) ;
31
+
29
32
#ifdef CONFIG_KASAN_HW_TAGS
30
33
/* Whether the MTE asynchronous mode is enabled. */
31
34
DEFINE_STATIC_KEY_FALSE (mte_async_mode );
@@ -195,11 +198,18 @@ void mte_check_tfsr_el1(void)
195
198
196
199
static void mte_update_sctlr_user (struct task_struct * task )
197
200
{
201
+ /*
202
+ * This must be called with preemption disabled and can only be called
203
+ * on the current or next task since the CPU must match where the thread
204
+ * is going to run. The caller is responsible for calling
205
+ * update_sctlr_el1() later in the same preemption disabled block.
206
+ */
198
207
unsigned long sctlr = task -> thread .sctlr_user ;
199
- unsigned long pref = MTE_CTRL_TCF_ASYNC ;
200
208
unsigned long mte_ctrl = task -> thread .mte_ctrl ;
201
- unsigned long resolved_mte_tcf = ( mte_ctrl & pref ) ? pref : mte_ctrl ;
209
+ unsigned long pref , resolved_mte_tcf ;
202
210
211
+ pref = __this_cpu_read (mte_tcf_preferred );
212
+ resolved_mte_tcf = (mte_ctrl & pref ) ? pref : mte_ctrl ;
203
213
sctlr &= ~SCTLR_EL1_TCF0_MASK ;
204
214
if (resolved_mte_tcf & MTE_CTRL_TCF_ASYNC )
205
215
sctlr |= SCTLR_EL1_TCF0_ASYNC ;
@@ -438,3 +448,54 @@ int mte_ptrace_copy_tags(struct task_struct *child, long request,
438
448
439
449
return ret ;
440
450
}
451
+
452
+ static ssize_t mte_tcf_preferred_show (struct device * dev ,
453
+ struct device_attribute * attr , char * buf )
454
+ {
455
+ switch (per_cpu (mte_tcf_preferred , dev -> id )) {
456
+ case MTE_CTRL_TCF_ASYNC :
457
+ return sysfs_emit (buf , "async\n" );
458
+ case MTE_CTRL_TCF_SYNC :
459
+ return sysfs_emit (buf , "sync\n" );
460
+ default :
461
+ return sysfs_emit (buf , "???\n" );
462
+ }
463
+ }
464
+
465
+ static ssize_t mte_tcf_preferred_store (struct device * dev ,
466
+ struct device_attribute * attr ,
467
+ const char * buf , size_t count )
468
+ {
469
+ u64 tcf ;
470
+
471
+ if (sysfs_streq (buf , "async" ))
472
+ tcf = MTE_CTRL_TCF_ASYNC ;
473
+ else if (sysfs_streq (buf , "sync" ))
474
+ tcf = MTE_CTRL_TCF_SYNC ;
475
+ else
476
+ return - EINVAL ;
477
+
478
+ device_lock (dev );
479
+ per_cpu (mte_tcf_preferred , dev -> id ) = tcf ;
480
+ device_unlock (dev );
481
+
482
+ return count ;
483
+ }
484
+ static DEVICE_ATTR_RW (mte_tcf_preferred );
485
+
486
+ static int register_mte_tcf_preferred_sysctl (void )
487
+ {
488
+ unsigned int cpu ;
489
+
490
+ if (!system_supports_mte ())
491
+ return 0 ;
492
+
493
+ for_each_possible_cpu (cpu ) {
494
+ per_cpu (mte_tcf_preferred , cpu ) = MTE_CTRL_TCF_ASYNC ;
495
+ device_create_file (get_cpu_device (cpu ),
496
+ & dev_attr_mte_tcf_preferred );
497
+ }
498
+
499
+ return 0 ;
500
+ }
501
+ subsys_initcall (register_mte_tcf_preferred_sysctl );
0 commit comments