Skip to content

Commit 42b6b10

Browse files
pccctmarinas
authored andcommitted
arm64: mte: avoid TFSRE0_EL1 related operations unless in async mode
There is no reason to touch TFSRE0_EL1 nor issue a DSB unless our task is in asynchronous mode. Since these operations (especially the DSB) may be expensive on certain microarchitectures, only perform them if necessary. Furthermore, stop clearing TFSRE0_EL1 on entry because it will be cleared on exit and it is not necessary to have any particular value in TFSRE0_EL1 between entry and exit. Signed-off-by: Peter Collingbourne <[email protected]> Link: https://linux-review.googlesource.com/id/Ib353a63e3d0abc2b0b008e96aa2d9692cfc1b815 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent ff11764 commit 42b6b10

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

arch/arm64/kernel/entry.S

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,29 +133,37 @@ alternative_cb_end
133133
.endm
134134

135135
/* Check for MTE asynchronous tag check faults */
136-
.macro check_mte_async_tcf, tmp, ti_flags
136+
.macro check_mte_async_tcf, tmp, ti_flags, thread_sctlr
137137
#ifdef CONFIG_ARM64_MTE
138138
.arch_extension lse
139139
alternative_if_not ARM64_MTE
140140
b 1f
141141
alternative_else_nop_endif
142+
/*
143+
* Asynchronous tag check faults are only possible in ASYNC (2) or
144+
* ASYM (3) modes. In each of these modes bit 1 of SCTLR_EL1.TCF0 is
145+
* set, so skip the check if it is unset.
146+
*/
147+
tbz \thread_sctlr, #(SCTLR_EL1_TCF0_SHIFT + 1), 1f
142148
mrs_s \tmp, SYS_TFSRE0_EL1
143149
tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f
144150
/* Asynchronous TCF occurred for TTBR0 access, set the TI flag */
145151
mov \tmp, #_TIF_MTE_ASYNC_FAULT
146152
add \ti_flags, tsk, #TSK_TI_FLAGS
147153
stset \tmp, [\ti_flags]
148-
msr_s SYS_TFSRE0_EL1, xzr
149154
1:
150155
#endif
151156
.endm
152157

153158
/* Clear the MTE asynchronous tag check faults */
154-
.macro clear_mte_async_tcf
159+
.macro clear_mte_async_tcf thread_sctlr
155160
#ifdef CONFIG_ARM64_MTE
156161
alternative_if ARM64_MTE
162+
/* See comment in check_mte_async_tcf above. */
163+
tbz \thread_sctlr, #(SCTLR_EL1_TCF0_SHIFT + 1), 1f
157164
dsb ish
158165
msr_s SYS_TFSRE0_EL1, xzr
166+
1:
159167
alternative_else_nop_endif
160168
#endif
161169
.endm
@@ -231,8 +239,8 @@ alternative_else_nop_endif
231239
disable_step_tsk x19, x20
232240

233241
/* Check for asynchronous tag check faults in user space */
234-
check_mte_async_tcf x22, x23
235-
apply_ssbd 1, x22, x23
242+
ldr x0, [tsk, THREAD_SCTLR_USER]
243+
check_mte_async_tcf x22, x23, x0
236244

237245
#ifdef CONFIG_ARM64_PTR_AUTH
238246
alternative_if ARM64_HAS_ADDRESS_AUTH
@@ -245,7 +253,6 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
245253
* was disabled on kernel exit then we would have left the kernel IA
246254
* installed so there is no need to install it again.
247255
*/
248-
ldr x0, [tsk, THREAD_SCTLR_USER]
249256
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
250257
__ptrauth_keys_install_kernel_nosync tsk, x20, x22, x23
251258
b 2f
@@ -258,6 +265,8 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
258265
alternative_else_nop_endif
259266
#endif
260267

268+
apply_ssbd 1, x22, x23
269+
261270
mte_set_kernel_gcr x22, x23
262271

263272
scs_load tsk
@@ -362,6 +371,10 @@ alternative_else_nop_endif
362371
3:
363372
scs_save tsk
364373

374+
/* Ignore asynchronous tag check faults in the uaccess routines */
375+
ldr x0, [tsk, THREAD_SCTLR_USER]
376+
clear_mte_async_tcf x0
377+
365378
#ifdef CONFIG_ARM64_PTR_AUTH
366379
alternative_if ARM64_HAS_ADDRESS_AUTH
367380
/*
@@ -371,7 +384,6 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
371384
*
372385
* No kernel C function calls after this.
373386
*/
374-
ldr x0, [tsk, THREAD_SCTLR_USER]
375387
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
376388
__ptrauth_keys_install_user tsk, x0, x1, x2
377389
b 2f
@@ -599,8 +611,6 @@ SYM_CODE_START_LOCAL(ret_to_user)
599611
cbnz x2, work_pending
600612
finish_ret_to_user:
601613
user_enter_irqoff
602-
/* Ignore asynchronous tag check faults in the uaccess routines */
603-
clear_mte_async_tcf
604614
enable_step_tsk x19, x2
605615
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
606616
bl stackleak_erase

0 commit comments

Comments
 (0)