]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
arm64/kernel: Support store-only mte tag check
authorYeoreum Yun <yeoreum.yun@arm.com>
Wed, 18 Jun 2025 09:29:52 +0000 (10:29 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Wed, 2 Jul 2025 17:49:04 +0000 (18:49 +0100)
Introduce new flag -- MTE_CTRL_STORE_ONLY used to set store-only tag check.
This flag isn't overridden by prefered tcf flag setting but set together
with prefered setting of way to report tag check fault.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20250618092957.2069907-4-yeoreum.yun@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/processor.h
arch/arm64/kernel/mte.c
arch/arm64/kernel/process.c

index 1bf1a3b16e88641ad066798b4755ae7898c81bb4..61d62bfd5a7bfc0289b9feb93edab93ce63534f4 100644 (file)
@@ -23,6 +23,8 @@
 #define MTE_CTRL_TCF_ASYNC             (1UL << 17)
 #define MTE_CTRL_TCF_ASYMM             (1UL << 18)
 
+#define MTE_CTRL_STORE_ONLY            (1UL << 19)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/build_bug.h>
index 2fbfd27ff5f293e1597e9de7967e22fccbc034b6..e5e773844889a81396e02e2657507520e240d178 100644 (file)
@@ -200,7 +200,7 @@ static void mte_update_sctlr_user(struct task_struct *task)
         * program requested values go with what was requested.
         */
        resolved_mte_tcf = (mte_ctrl & pref) ? pref : mte_ctrl;
-       sctlr &= ~SCTLR_EL1_TCF0_MASK;
+       sctlr &= ~(SCTLR_EL1_TCF0_MASK | SCTLR_EL1_TCSO0_MASK);
        /*
         * Pick an actual setting. The order in which we check for
         * set bits and map into register values determines our
@@ -212,6 +212,10 @@ static void mte_update_sctlr_user(struct task_struct *task)
                sctlr |= SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF0, ASYNC);
        else if (resolved_mte_tcf & MTE_CTRL_TCF_SYNC)
                sctlr |= SYS_FIELD_PREP_ENUM(SCTLR_EL1, TCF0, SYNC);
+
+       if (mte_ctrl & MTE_CTRL_STORE_ONLY)
+               sctlr |= SYS_FIELD_PREP(SCTLR_EL1, TCSO0, 1);
+
        task->thread.sctlr_user = sctlr;
 }
 
@@ -371,6 +375,9 @@ long set_mte_ctrl(struct task_struct *task, unsigned long arg)
            (arg & PR_MTE_TCF_SYNC))
                mte_ctrl |= MTE_CTRL_TCF_ASYMM;
 
+       if (arg & PR_MTE_STORE_ONLY)
+               mte_ctrl |= MTE_CTRL_STORE_ONLY;
+
        task->thread.mte_ctrl = mte_ctrl;
        if (task == current) {
                preempt_disable();
@@ -398,6 +405,8 @@ long get_mte_ctrl(struct task_struct *task)
                ret |= PR_MTE_TCF_ASYNC;
        if (mte_ctrl & MTE_CTRL_TCF_SYNC)
                ret |= PR_MTE_TCF_SYNC;
+       if (mte_ctrl & MTE_CTRL_STORE_ONLY)
+               ret |= PR_MTE_STORE_ONLY;
 
        return ret;
 }
index a5ca15daeb8a6cca9b4f009eae8cdc27c6bf4d0a..fc49f2b3ded1256aea16941c4da52f3da844b257 100644 (file)
@@ -849,10 +849,14 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
        if (is_compat_thread(ti))
                return -EINVAL;
 
-       if (system_supports_mte())
+       if (system_supports_mte()) {
                valid_mask |= PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC \
                        | PR_MTE_TAG_MASK;
 
+               if (cpus_have_cap(ARM64_MTE_STORE_ONLY))
+                       valid_mask |= PR_MTE_STORE_ONLY;
+       }
+
        if (arg & ~valid_mask)
                return -EINVAL;