Commit 4d51ff5b authored by Yeoreum Yun's avatar Yeoreum Yun Committed by Catalin Marinas
Browse files

arm64/kernel: Support store-only mte tag check



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: default avatarYeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: default avatarMark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20250618092957.2069907-4-yeoreum.yun@arm.com


Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent b1fabef3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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>
+10 −1
Original line number Diff line number Diff line
@@ -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;
}
+5 −1
Original line number Diff line number Diff line
@@ -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;