BACKPORT: FROMLIST: arm64: mte: avoid TFSR related operations unless in async mode
There is no reason to touch TFSR 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 TFSR on entry because it will be cleared on exit and it is not necessary to have any particular value in TFSR between entry and exit. Signed-off-by: Peter Collingbourne <pcc@google.com> Link: https://linux-review.googlesource.com/id/Ib353a63e3d0abc2b0b008e96aa2d9692cfc1b815 Change-Id: I9132dd39ce6f994ee993cae67b2476dfa73ef64a Bug: 192536783 Link: https://lore.kernel.org/linux-arm-kernel/20210709023532.2133673-1-pcc@google.com/ Signed-off-by: Elliot Berman <quic_eberman@quicinc.com> Signed-off-by: Peter Collingbourne <pcc@google.com>
This commit is contained in:

committed by
Todd Kjos

parent
3972be647a
commit
a20103c331
@@ -148,29 +148,37 @@ alternative_cb_end
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* Check for MTE asynchronous tag check faults */
|
/* Check for MTE asynchronous tag check faults */
|
||||||
.macro check_mte_async_tcf, tmp, ti_flags
|
.macro check_mte_async_tcf, tmp, ti_flags, thread_sctlr
|
||||||
#ifdef CONFIG_ARM64_MTE
|
#ifdef CONFIG_ARM64_MTE
|
||||||
.arch_extension lse
|
.arch_extension lse
|
||||||
alternative_if_not ARM64_MTE
|
alternative_if_not ARM64_MTE
|
||||||
b 1f
|
b 1f
|
||||||
alternative_else_nop_endif
|
alternative_else_nop_endif
|
||||||
|
/*
|
||||||
|
* Asynchronous tag check faults are only possible in ASYNC (2) or
|
||||||
|
* ASYM (3) modes. In each of these modes bit 1 of SCTLR_EL1.TCF0 is
|
||||||
|
* set, so skip the check if it is unset.
|
||||||
|
*/
|
||||||
|
tbz \thread_sctlr, #(SCTLR_EL1_TCF0_SHIFT + 1), 1f
|
||||||
mrs_s \tmp, SYS_TFSRE0_EL1
|
mrs_s \tmp, SYS_TFSRE0_EL1
|
||||||
tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f
|
tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f
|
||||||
/* Asynchronous TCF occurred for TTBR0 access, set the TI flag */
|
/* Asynchronous TCF occurred for TTBR0 access, set the TI flag */
|
||||||
mov \tmp, #_TIF_MTE_ASYNC_FAULT
|
mov \tmp, #_TIF_MTE_ASYNC_FAULT
|
||||||
add \ti_flags, tsk, #TSK_TI_FLAGS
|
add \ti_flags, tsk, #TSK_TI_FLAGS
|
||||||
stset \tmp, [\ti_flags]
|
stset \tmp, [\ti_flags]
|
||||||
msr_s SYS_TFSRE0_EL1, xzr
|
|
||||||
1:
|
1:
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* Clear the MTE asynchronous tag check faults */
|
/* Clear the MTE asynchronous tag check faults */
|
||||||
.macro clear_mte_async_tcf
|
.macro clear_mte_async_tcf thread_sctlr
|
||||||
#ifdef CONFIG_ARM64_MTE
|
#ifdef CONFIG_ARM64_MTE
|
||||||
alternative_if ARM64_MTE
|
alternative_if ARM64_MTE
|
||||||
|
/* See comment in check_mte_async_tcf above. */
|
||||||
|
tbz \thread_sctlr, #(SCTLR_EL1_TCF0_SHIFT + 1), 1f
|
||||||
dsb ish
|
dsb ish
|
||||||
msr_s SYS_TFSRE0_EL1, xzr
|
msr_s SYS_TFSRE0_EL1, xzr
|
||||||
|
1:
|
||||||
alternative_else_nop_endif
|
alternative_else_nop_endif
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
@@ -246,8 +254,8 @@ alternative_else_nop_endif
|
|||||||
disable_step_tsk x19, x20
|
disable_step_tsk x19, x20
|
||||||
|
|
||||||
/* Check for asynchronous tag check faults in user space */
|
/* Check for asynchronous tag check faults in user space */
|
||||||
check_mte_async_tcf x22, x23
|
ldr x0, [tsk, THREAD_SCTLR_USER]
|
||||||
apply_ssbd 1, x22, x23
|
check_mte_async_tcf x22, x23, x0
|
||||||
|
|
||||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||||
alternative_if ARM64_HAS_ADDRESS_AUTH
|
alternative_if ARM64_HAS_ADDRESS_AUTH
|
||||||
@@ -260,7 +268,6 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
|
|||||||
* was disabled on kernel exit then we would have left the kernel IA
|
* was disabled on kernel exit then we would have left the kernel IA
|
||||||
* installed so there is no need to install it again.
|
* installed so there is no need to install it again.
|
||||||
*/
|
*/
|
||||||
ldr x0, [tsk, THREAD_SCTLR_USER]
|
|
||||||
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
|
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
|
||||||
__ptrauth_keys_install_kernel_nosync tsk, x20, x22, x23
|
__ptrauth_keys_install_kernel_nosync tsk, x20, x22, x23
|
||||||
b 2f
|
b 2f
|
||||||
@@ -273,6 +280,8 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
|
|||||||
alternative_else_nop_endif
|
alternative_else_nop_endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
apply_ssbd 1, x22, x23
|
||||||
|
|
||||||
mte_set_kernel_gcr x22, x23
|
mte_set_kernel_gcr x22, x23
|
||||||
|
|
||||||
scs_load tsk, x20
|
scs_load tsk, x20
|
||||||
@@ -389,6 +398,10 @@ alternative_else_nop_endif
|
|||||||
3:
|
3:
|
||||||
scs_save tsk, x0
|
scs_save tsk, x0
|
||||||
|
|
||||||
|
/* Ignore asynchronous tag check faults in the uaccess routines */
|
||||||
|
ldr x0, [tsk, THREAD_SCTLR_USER]
|
||||||
|
clear_mte_async_tcf x0
|
||||||
|
|
||||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||||
alternative_if ARM64_HAS_ADDRESS_AUTH
|
alternative_if ARM64_HAS_ADDRESS_AUTH
|
||||||
/*
|
/*
|
||||||
@@ -398,7 +411,6 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
|
|||||||
*
|
*
|
||||||
* No kernel C function calls after this.
|
* No kernel C function calls after this.
|
||||||
*/
|
*/
|
||||||
ldr x0, [tsk, THREAD_SCTLR_USER]
|
|
||||||
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
|
tbz x0, SCTLR_ELx_ENIA_SHIFT, 1f
|
||||||
__ptrauth_keys_install_user tsk, x0, x1, x2
|
__ptrauth_keys_install_user tsk, x0, x1, x2
|
||||||
b 2f
|
b 2f
|
||||||
@@ -824,8 +836,6 @@ SYM_CODE_START_LOCAL(ret_to_user)
|
|||||||
cbnz x2, work_pending
|
cbnz x2, work_pending
|
||||||
finish_ret_to_user:
|
finish_ret_to_user:
|
||||||
user_enter_irqoff
|
user_enter_irqoff
|
||||||
/* Ignore asynchronous tag check faults in the uaccess routines */
|
|
||||||
clear_mte_async_tcf
|
|
||||||
enable_step_tsk x19, x2
|
enable_step_tsk x19, x2
|
||||||
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
|
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
|
||||||
bl stackleak_erase
|
bl stackleak_erase
|
||||||
|
Reference in New Issue
Block a user