@@ -193,14 +193,19 @@ void mte_check_tfsr_el1(void)
193
193
}
194
194
#endif
195
195
196
- static void set_gcr_el1_excl ( u64 excl )
196
+ static void mte_update_sctlr_user ( struct task_struct * task )
197
197
{
198
- current -> thread .mte_ctrl = excl ;
198
+ unsigned long sctlr = task -> thread .sctlr_user ;
199
+ unsigned long pref = MTE_CTRL_TCF_ASYNC ;
200
+ unsigned long mte_ctrl = task -> thread .mte_ctrl ;
201
+ unsigned long resolved_mte_tcf = (mte_ctrl & pref ) ? pref : mte_ctrl ;
199
202
200
- /*
201
- * SYS_GCR_EL1 will be set to current->thread.gcr_user_excl value
202
- * by mte_set_user_gcr() in kernel_exit,
203
- */
203
+ sctlr &= ~SCTLR_EL1_TCF0_MASK ;
204
+ if (resolved_mte_tcf & MTE_CTRL_TCF_ASYNC )
205
+ sctlr |= SCTLR_EL1_TCF0_ASYNC ;
206
+ else if (resolved_mte_tcf & MTE_CTRL_TCF_SYNC )
207
+ sctlr |= SCTLR_EL1_TCF0_SYNC ;
208
+ task -> thread .sctlr_user = sctlr ;
204
209
}
205
210
206
211
void mte_thread_init_user (void )
@@ -212,15 +217,16 @@ void mte_thread_init_user(void)
212
217
dsb (ish );
213
218
write_sysreg_s (0 , SYS_TFSRE0_EL1 );
214
219
clear_thread_flag (TIF_MTE_ASYNC_FAULT );
215
- /* disable tag checking */
216
- set_task_sctlr_el1 ((current -> thread .sctlr_user & ~SCTLR_EL1_TCF0_MASK ) |
217
- SCTLR_EL1_TCF0_NONE );
218
- /* reset tag generation mask */
219
- set_gcr_el1_excl (SYS_GCR_EL1_EXCL_MASK );
220
+ /* disable tag checking and reset tag generation mask */
221
+ current -> thread .mte_ctrl = MTE_CTRL_GCR_USER_EXCL_MASK ;
222
+ mte_update_sctlr_user (current );
223
+ set_task_sctlr_el1 (current -> thread .sctlr_user );
220
224
}
221
225
222
226
void mte_thread_switch (struct task_struct * next )
223
227
{
228
+ mte_update_sctlr_user (next );
229
+
224
230
/*
225
231
* Check if an async tag exception occurred at EL1.
226
232
*
@@ -259,33 +265,21 @@ void mte_suspend_exit(void)
259
265
260
266
long set_mte_ctrl (struct task_struct * task , unsigned long arg )
261
267
{
262
- u64 sctlr = task -> thread .sctlr_user & ~SCTLR_EL1_TCF0_MASK ;
263
268
u64 mte_ctrl = (~((arg & PR_MTE_TAG_MASK ) >> PR_MTE_TAG_SHIFT ) &
264
269
SYS_GCR_EL1_EXCL_MASK ) << MTE_CTRL_GCR_USER_EXCL_SHIFT ;
265
270
266
271
if (!system_supports_mte ())
267
272
return 0 ;
268
273
269
- switch (arg & PR_MTE_TCF_MASK ) {
270
- case PR_MTE_TCF_NONE :
271
- sctlr |= SCTLR_EL1_TCF0_NONE ;
272
- break ;
273
- case PR_MTE_TCF_SYNC :
274
- sctlr |= SCTLR_EL1_TCF0_SYNC ;
275
- break ;
276
- case PR_MTE_TCF_ASYNC :
277
- sctlr |= SCTLR_EL1_TCF0_ASYNC ;
278
- break ;
279
- default :
280
- return - EINVAL ;
281
- }
274
+ if (arg & PR_MTE_TCF_ASYNC )
275
+ mte_ctrl |= MTE_CTRL_TCF_ASYNC ;
276
+ if (arg & PR_MTE_TCF_SYNC )
277
+ mte_ctrl |= MTE_CTRL_TCF_SYNC ;
282
278
283
- if (task != current ) {
284
- task -> thread .sctlr_user = sctlr ;
285
- task -> thread .mte_ctrl = mte_ctrl ;
286
- } else {
287
- set_task_sctlr_el1 (sctlr );
288
- set_gcr_el1_excl (mte_ctrl );
279
+ task -> thread .mte_ctrl = mte_ctrl ;
280
+ if (task == current ) {
281
+ mte_update_sctlr_user (task );
282
+ set_task_sctlr_el1 (task -> thread .sctlr_user );
289
283
}
290
284
291
285
return 0 ;
@@ -302,18 +296,10 @@ long get_mte_ctrl(struct task_struct *task)
302
296
return 0 ;
303
297
304
298
ret = incl << PR_MTE_TAG_SHIFT ;
305
-
306
- switch (task -> thread .sctlr_user & SCTLR_EL1_TCF0_MASK ) {
307
- case SCTLR_EL1_TCF0_NONE :
308
- ret |= PR_MTE_TCF_NONE ;
309
- break ;
310
- case SCTLR_EL1_TCF0_SYNC :
311
- ret |= PR_MTE_TCF_SYNC ;
312
- break ;
313
- case SCTLR_EL1_TCF0_ASYNC :
299
+ if (mte_ctrl & MTE_CTRL_TCF_ASYNC )
314
300
ret |= PR_MTE_TCF_ASYNC ;
315
- break ;
316
- }
301
+ if ( mte_ctrl & MTE_CTRL_TCF_SYNC )
302
+ ret |= PR_MTE_TCF_SYNC ;
317
303
318
304
return ret ;
319
305
}
0 commit comments