Skip to content

Commit bf587af

Browse files
committed
Merge branch 'for-next/mte' into for-next/core
* for-next/mte: docs: sysfs-devices-system-cpu: document "asymm" value for mte_tcf_preferred arm64/mte: Remove asymmetric mode from the prctl() interface kasan: fix a missing header include of static_keys.h arm64/mte: Add userspace interface for enabling asymmetric mode arm64/mte: Add hwcap for asymmetric mode arm64/mte: Add a little bit of documentation for mte_update_sctlr_user() arm64/mte: Document ABI for asymmetric mode arm64: mte: avoid clearing PSTATE.TCO on entry unless necessary kasan: split kasan_*enabled() functions into a separate header
2 parents 20fd2ed + 9986c76 commit bf587af

15 files changed

Lines changed: 127 additions & 39 deletions

File tree

Documentation/ABI/testing/sysfs-devices-system-cpu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ Description: Preferred MTE tag checking mode
662662

663663
================ ==============================================
664664
"sync" Prefer synchronous mode
665+
"asymm" Prefer asymmetric mode
665666
"async" Prefer asynchronous mode
666667
================ ==============================================
667668

Documentation/arm64/elf_hwcaps.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ HWCAP2_RPRES
259259

260260
Functionality implied by ID_AA64ISAR2_EL1.RPRES == 0b0001.
261261

262+
HWCAP2_MTE3
263+
264+
Functionality implied by ID_AA64PFR1_EL1.MTE == 0b0011, as described
265+
by Documentation/arm64/memory-tagging-extension.rst.
266+
262267
4. Unused AT_HWCAP bits
263268
-----------------------
264269

Documentation/arm64/memory-tagging-extension.rst

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ configurable behaviours:
7676
with ``.si_code = SEGV_MTEAERR`` and ``.si_addr = 0`` (the faulting
7777
address is unknown).
7878

79+
- *Asymmetric* - Reads are handled as for synchronous mode while writes
80+
are handled as for asynchronous mode.
81+
7982
The user can select the above modes, per thread, using the
8083
``prctl(PR_SET_TAGGED_ADDR_CTRL, flags, 0, 0, 0)`` system call where ``flags``
8184
contains any number of the following values in the ``PR_MTE_TCF_MASK``
@@ -140,18 +143,25 @@ tag checking mode as the CPU's preferred tag checking mode.
140143

141144
The preferred tag checking mode for each CPU is controlled by
142145
``/sys/devices/system/cpu/cpu<N>/mte_tcf_preferred``, to which a
143-
privileged user may write the value ``async`` or ``sync``. The default
144-
preferred mode for each CPU is ``async``.
146+
privileged user may write the value ``async``, ``sync`` or ``asymm``. The
147+
default preferred mode for each CPU is ``async``.
145148

146149
To allow a program to potentially run in the CPU's preferred tag
147150
checking mode, the user program may set multiple tag check fault mode
148151
bits in the ``flags`` argument to the ``prctl(PR_SET_TAGGED_ADDR_CTRL,
149-
flags, 0, 0, 0)`` system call. If the CPU's preferred tag checking
150-
mode is in the task's set of provided tag checking modes (this will
151-
always be the case at present because the kernel only supports two
152-
tag checking modes, but future kernels may support more modes), that
153-
mode will be selected. Otherwise, one of the modes in the task's mode
154-
set will be selected in a currently unspecified manner.
152+
flags, 0, 0, 0)`` system call. If both synchronous and asynchronous
153+
modes are requested then asymmetric mode may also be selected by the
154+
kernel. If the CPU's preferred tag checking mode is in the task's set
155+
of provided tag checking modes, that mode will be selected. Otherwise,
156+
one of the modes in the task's mode will be selected by the kernel
157+
from the task's mode set using the preference order:
158+
159+
1. Asynchronous
160+
2. Asymmetric
161+
3. Synchronous
162+
163+
Note that there is no way for userspace to request multiple modes and
164+
also disable asymmetric mode.
155165

156166
Initial process state
157167
---------------------

arch/arm64/include/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
#define KERNEL_HWCAP_ECV __khwcap2_feature(ECV)
109109
#define KERNEL_HWCAP_AFP __khwcap2_feature(AFP)
110110
#define KERNEL_HWCAP_RPRES __khwcap2_feature(RPRES)
111+
#define KERNEL_HWCAP_MTE3 __khwcap2_feature(MTE3)
111112

112113
/*
113114
* This yields a mask that user programs can use to figure out what

arch/arm64/include/asm/mte.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#ifndef __ASSEMBLY__
1212

1313
#include <linux/bitfield.h>
14+
#include <linux/kasan-enabled.h>
1415
#include <linux/page-flags.h>
16+
#include <linux/sched.h>
1517
#include <linux/types.h>
1618

1719
#include <asm/pgtable-types.h>
@@ -86,6 +88,26 @@ static inline int mte_ptrace_copy_tags(struct task_struct *child,
8688

8789
#endif /* CONFIG_ARM64_MTE */
8890

91+
static inline void mte_disable_tco_entry(struct task_struct *task)
92+
{
93+
if (!system_supports_mte())
94+
return;
95+
96+
/*
97+
* Re-enable tag checking (TCO set on exception entry). This is only
98+
* necessary if MTE is enabled in either the kernel or the userspace
99+
* task in synchronous or asymmetric mode (SCTLR_EL1.TCF0 bit 0 is set
100+
* for both). With MTE disabled in the kernel and disabled or
101+
* asynchronous in userspace, tag check faults (including in uaccesses)
102+
* are not reported, therefore there is no need to re-enable checking.
103+
* This is beneficial on microarchitectures where re-enabling TCO is
104+
* expensive.
105+
*/
106+
if (kasan_hw_tags_enabled() ||
107+
(task->thread.sctlr_user & (1UL << SCTLR_EL1_TCF0_SHIFT)))
108+
asm volatile(SET_PSTATE_TCO(0));
109+
}
110+
89111
#ifdef CONFIG_KASAN_HW_TAGS
90112
/* Whether the MTE asynchronous mode is enabled. */
91113
DECLARE_STATIC_KEY_FALSE(mte_async_or_asymm_mode);

arch/arm64/include/asm/processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#define MTE_CTRL_TCF_SYNC (1UL << 16)
2323
#define MTE_CTRL_TCF_ASYNC (1UL << 17)
24+
#define MTE_CTRL_TCF_ASYMM (1UL << 18)
2425

2526
#ifndef __ASSEMBLY__
2627

arch/arm64/include/uapi/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,6 @@
7878
#define HWCAP2_ECV (1 << 19)
7979
#define HWCAP2_AFP (1 << 20)
8080
#define HWCAP2_RPRES (1 << 21)
81+
#define HWCAP2_MTE3 (1 << 22)
8182

8283
#endif /* _UAPI__ASM_HWCAP_H */

arch/arm64/kernel/cpufeature.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2479,6 +2479,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
24792479
#endif
24802480
#ifdef CONFIG_ARM64_MTE
24812481
HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_MTE_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_MTE, CAP_HWCAP, KERNEL_HWCAP_MTE),
2482+
HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_MTE_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_MTE_ASYMM, CAP_HWCAP, KERNEL_HWCAP_MTE3),
24822483
#endif /* CONFIG_ARM64_MTE */
24832484
HWCAP_CAP(SYS_ID_AA64MMFR0_EL1, ID_AA64MMFR0_ECV_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ECV),
24842485
HWCAP_CAP(SYS_ID_AA64MMFR1_EL1, ID_AA64MMFR1_AFP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AFP),

arch/arm64/kernel/cpuinfo.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ static const char *const hwcap_str[] = {
9797
[KERNEL_HWCAP_ECV] = "ecv",
9898
[KERNEL_HWCAP_AFP] = "afp",
9999
[KERNEL_HWCAP_RPRES] = "rpres",
100+
[KERNEL_HWCAP_MTE3] = "mte3",
100101
};
101102

102103
#ifdef CONFIG_COMPAT

arch/arm64/kernel/entry-common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include <linux/context_tracking.h>
9+
#include <linux/kasan.h>
910
#include <linux/linkage.h>
1011
#include <linux/lockdep.h>
1112
#include <linux/ptrace.h>
@@ -56,6 +57,7 @@ static void noinstr enter_from_kernel_mode(struct pt_regs *regs)
5657
{
5758
__enter_from_kernel_mode(regs);
5859
mte_check_tfsr_entry();
60+
mte_disable_tco_entry(current);
5961
}
6062

6163
/*
@@ -103,6 +105,7 @@ static __always_inline void __enter_from_user_mode(void)
103105
CT_WARN_ON(ct_state() != CONTEXT_USER);
104106
user_exit_irqoff();
105107
trace_hardirqs_off_finish();
108+
mte_disable_tco_entry(current);
106109
}
107110

108111
static __always_inline void enter_from_user_mode(struct pt_regs *regs)

0 commit comments

Comments
 (0)