linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: James Morse <james.morse@arm.com>
To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Cc: James Morse <james.morse@arm.com>,
	D Scott Phillips OS <scott@os.amperecomputing.com>,
	carl@os.amperecomputing.com, lcherian@marvell.com,
	bobo.shaobowang@huawei.com, tan.shaopeng@fujitsu.com,
	baolin.wang@linux.alibaba.com,
	Jamie Iles <quic_jiles@quicinc.com>,
	Xin Hao <xhao@linux.alibaba.com>,
	peternewman@google.com, dfustini@baylibre.com,
	amitsinght@marvell.com, David Hildenbrand <david@kernel.org>,
	Dave Martin <dave.martin@arm.com>, Koba Ko <kobak@nvidia.com>,
	Shanker Donthineni <sdonthineni@nvidia.com>,
	fenghuay@nvidia.com, baisheng.gao@unisoc.com,
	Jonathan Cameron <jonathan.cameron@huawei.com>,
	Gavin Shan <gshan@redhat.com>, Ben Horgan <ben.horgan@arm.com>,
	rohit.mathew@arm.com, reinette.chatre@intel.com,
	Punit Agrawal <punit.agrawal@oss.qualcomm.com>
Subject: [RFC PATCH 01/38] arm64: mpam: Context switch the MPAM registers
Date: Fri,  5 Dec 2025 21:58:24 +0000	[thread overview]
Message-ID: <20251205215901.17772-2-james.morse@arm.com> (raw)
In-Reply-To: <20251205215901.17772-1-james.morse@arm.com>

MPAM allows traffic in the SoC to be labeled by the OS, these labels
are used to apply policy in caches and bandwidth regulators, and to
monitor traffic in the SoC. The label is made up of a PARTID and PMG
value. The x86 equivalent calls these CLOSID and RMID, but they don't
map precisely.

MPAM has two CPU system registers that is used to hold the PARTID and PMG
values that traffic generated at each exception level will use. These can be
set per-task by the resctrl file system. (resctrl is the defacto interface
for controlling this stuff).

Add a helper to switch this.

struct task_struct's separate CLOSID and RMID fields are insufficient
to implement resctrl using MPAM, as resctrl can change the PARTID (CLOSID)
and PMG (sort of like the RMID) separately. On x86, the rmid is an
independent number, so a race that writes a mismatched  closid and rmid
into hardware is benign. On arm64, the pmg bits extend the partid.
(i.e. partid-5 has a pmg-0 that is not the same as partid-6's pmg-0).
In this case, mismatching the values will 'dirty' a pmg value that
resctrl believes is clean, and is not tracking with its 'limbo' code.

To avoid this, the partid and pmg are always read and written as a pair.
Instead of making struct task_struct's closid and rmid fields an
endian-unsafe union, add the value to struct thread_info and always use
READ_ONCE()/WRITE_ONCE() when accessing this field.

Resctrl allows a per-cpu 'default' value to be set, this overrides the
values when scheduling a task in the default control-group, which has
PARTID 0. The way 'code data prioritisation' gets emulated means the
register value for the default group needs to be a variable.

The current system register value is kept in a per-cpu variable to
avoid writing to the system register if the value isn't going to change.
Writes to this register may reset the hardware state for regulating
bandwidth.

Finally, there is no reason to context switch these registers unless
there is a driver changing the values in struct task_struct. Hide
the whole thing behind a static key. This also allows the driver to
disable MPAM in response to errors reported by hardware. Move the
existing static key to belong to the arch code, as in the future
the MPAM driver may become a loadable module.

All this should depend on whether there is an MPAM driver, hide
it behind CONFIG_MPAM.

CC: Amit Singh Tomar <amitsinght@marvell.com>
Signed-off-by: James Morse <james.morse@arm.com>
---
 arch/arm64/Kconfig                   |  2 +
 arch/arm64/include/asm/mpam.h        | 74 ++++++++++++++++++++++++++++
 arch/arm64/include/asm/thread_info.h |  3 ++
 arch/arm64/kernel/Makefile           |  1 +
 arch/arm64/kernel/mpam.c             | 13 +++++
 arch/arm64/kernel/process.c          |  7 +++
 drivers/resctrl/mpam_devices.c       |  2 -
 drivers/resctrl/mpam_internal.h      |  2 +
 8 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/mpam.h
 create mode 100644 arch/arm64/kernel/mpam.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 004d58cfbff8..558baa9e7c08 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2048,6 +2048,8 @@ config ARM64_MPAM
 
 	  MPAM is exposed to user-space via the resctrl pseudo filesystem.
 
+	  This option enables the extra context switch code.
+
 endmenu # "ARMv8.4 architectural features"
 
 menu "ARMv8.5 architectural features"
diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h
new file mode 100644
index 000000000000..86a55176f884
--- /dev/null
+++ b/arch/arm64/include/asm/mpam.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2025 Arm Ltd. */
+
+#ifndef __ASM__MPAM_H
+#define __ASM__MPAM_H
+
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/jump_label.h>
+#include <linux/percpu.h>
+#include <linux/sched.h>
+
+#include <asm/cpucaps.h>
+#include <asm/cpufeature.h>
+#include <asm/sysreg.h>
+
+DECLARE_STATIC_KEY_FALSE(mpam_enabled);
+DECLARE_PER_CPU(u64, arm64_mpam_default);
+DECLARE_PER_CPU(u64, arm64_mpam_current);
+
+/*
+ * The value of the MPAM0_EL1 sysreg when a task is in resctrl's default group.
+ * This is used by the context switch code to use the resctrl CPU property
+ * instead. The value is modified when CDP is enabled/disabled by mounting
+ * the resctrl filesystem.
+ */
+extern u64 arm64_mpam_global_default;
+
+/*
+ * The resctrl filesystem writes to the partid/pmg values for threads and CPUs,
+ * which may race with reads in __mpam_sched_in(). Ensure only one of the old
+ * or new values are used. Particular care should be taken with the pmg field
+ * as __mpam_sched_in() may read a partid and pmg that don't match, causing
+ * this value to be stored with cache allocations, despite being considered
+ * 'free' by resctrl.
+ *
+ * A value in struct thread_info is used instead of struct task_struct as the
+ * cpu's u64 register format is used, but struct task_struct has two u32'.
+ */
+static inline u64 mpam_get_regval(struct task_struct *tsk)
+{
+#ifdef CONFIG_ARM64_MPAM
+	return READ_ONCE(task_thread_info(tsk)->mpam_partid_pmg);
+#else
+	return 0;
+#endif
+}
+
+static inline void mpam_thread_switch(struct task_struct *tsk)
+{
+	u64 oldregval;
+	int cpu = smp_processor_id();
+	u64 regval = mpam_get_regval(tsk);
+
+	if (!IS_ENABLED(CONFIG_ARM64_MPAM) ||
+	    !static_branch_likely(&mpam_enabled))
+		return;
+
+	if (regval == READ_ONCE(arm64_mpam_global_default))
+		regval = READ_ONCE(per_cpu(arm64_mpam_default, cpu));
+
+	oldregval = READ_ONCE(per_cpu(arm64_mpam_current, cpu));
+	if (oldregval == regval)
+		return;
+
+	write_sysreg_s(regval, SYS_MPAM1_EL1);
+	isb();
+
+	/* Synchronising the EL0 write is left until the ERET to EL0 */
+	write_sysreg_s(regval, SYS_MPAM0_EL1);
+
+	WRITE_ONCE(per_cpu(arm64_mpam_current, cpu), regval);
+}
+#endif /* __ASM__MPAM_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index f241b8601ebd..c226dabd5019 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -41,6 +41,9 @@ struct thread_info {
 #ifdef CONFIG_SHADOW_CALL_STACK
 	void			*scs_base;
 	void			*scs_sp;
+#endif
+#ifdef CONFIG_ARM64_MPAM
+	u64			mpam_partid_pmg;
 #endif
 	u32			cpu;
 };
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 76f32e424065..15979f366519 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_CRASH_DUMP)		+= crash_dump.o
 obj-$(CONFIG_VMCORE_INFO)		+= vmcore_info.o
 obj-$(CONFIG_ARM_SDE_INTERFACE)		+= sdei.o
 obj-$(CONFIG_ARM64_PTR_AUTH)		+= pointer_auth.o
+obj-$(CONFIG_ARM64_MPAM)		+= mpam.o
 obj-$(CONFIG_ARM64_MTE)			+= mte.o
 obj-y					+= vdso-wrap.o
 obj-$(CONFIG_COMPAT_VDSO)		+= vdso32-wrap.o
diff --git a/arch/arm64/kernel/mpam.c b/arch/arm64/kernel/mpam.c
new file mode 100644
index 000000000000..9866d2ca0faa
--- /dev/null
+++ b/arch/arm64/kernel/mpam.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2025 Arm Ltd. */
+
+#include <asm/mpam.h>
+
+#include <linux/jump_label.h>
+#include <linux/percpu.h>
+
+DEFINE_STATIC_KEY_FALSE(mpam_enabled);
+DEFINE_PER_CPU(u64, arm64_mpam_default);
+DEFINE_PER_CPU(u64, arm64_mpam_current);
+
+u64 arm64_mpam_global_default;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index fba7ca102a8c..b510c0699313 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -51,6 +51,7 @@
 #include <asm/fpsimd.h>
 #include <asm/gcs.h>
 #include <asm/mmu_context.h>
+#include <asm/mpam.h>
 #include <asm/mte.h>
 #include <asm/processor.h>
 #include <asm/pointer_auth.h>
@@ -737,6 +738,12 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	if (prev->thread.sctlr_user != next->thread.sctlr_user)
 		update_sctlr_el1(next->thread.sctlr_user);
 
+	/*
+	 * MPAM thread switch happens after the DSB to ensure prev's accesses
+	 * use prev's MPAM settings.
+	 */
+	mpam_thread_switch(next);
+
 	/* the actual thread switch */
 	last = cpu_switch_to(prev, next);
 
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 0b5b158e1aaf..2996ad93fc3e 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -29,8 +29,6 @@
 
 #include "mpam_internal.h"
 
-DEFINE_STATIC_KEY_FALSE(mpam_enabled); /* This moves to arch code */
-
 /*
  * mpam_list_lock protects the SRCU lists when writing. Once the
  * mpam_enabled key is enabled these lists are read-only,
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index e79c3c47259c..4508a6654fe0 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -17,6 +17,8 @@
 #include <linux/srcu.h>
 #include <linux/types.h>
 
+#include <asm/mpam.h>
+
 #define MPAM_MSC_MAX_NUM_RIS	16
 
 struct platform_device;
-- 
2.39.5



  reply	other threads:[~2025-12-05 21:59 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-05 21:58 [RFC PATCH 00/38] arm_mpam: Add KVM/arm64 and resctrl glue code James Morse
2025-12-05 21:58 ` James Morse [this message]
2025-12-05 23:53   ` [RFC PATCH 01/38] arm64: mpam: Context switch the MPAM registers Fenghua Yu
2025-12-09 15:08     ` Ben Horgan
2025-12-09 14:49   ` Ben Horgan
2025-12-12 12:30   ` Ben Horgan
2025-12-18 10:35   ` Jonathan Cameron
2025-12-18 14:52     ` Ben Horgan
2025-12-18 14:55       ` Ben Horgan
2025-12-18 15:38         ` Jonathan Cameron
2025-12-18 15:54           ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 02/38] arm64: mpam: Re-initialise MPAM regs when CPU comes online James Morse
2025-12-09 15:13   ` Ben Horgan
2025-12-11 11:23     ` Ben Horgan
2025-12-11 11:32       ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 03/38] arm64: mpam: Advertise the CPUs MPAM limits to the driver James Morse
2025-12-18 10:38   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 04/38] arm64: mpam: Add cpu_pm notifier to restore MPAM sysregs James Morse
2025-12-11 13:41   ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 05/38] arm64: mpam: Add helpers to change a task or cpu's MPAM PARTID/PMG values James Morse
2025-12-18 10:44   ` Jonathan Cameron
2025-12-19 11:56     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 06/38] KVM: arm64: Force guest EL1 to use user-space's partid configuration James Morse
2025-12-09 15:32   ` Ben Horgan
2025-12-12 11:31   ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 07/38] arm_mpam: resctrl: Add boilerplate cpuhp and domain allocation James Morse
2025-12-09 15:43   ` Ben Horgan
2025-12-18 11:30   ` Jonathan Cameron
2025-12-19 12:02     ` Ben Horgan
2025-12-22 11:48       ` Jonathan Cameron
2026-01-02 11:07         ` Ben Horgan
2025-12-19 12:17     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 08/38] arm_mpam: resctrl: Pick the caches we will use as resctrl resources James Morse
2025-12-09 15:57   ` Ben Horgan
2025-12-16 10:14     ` Ben Horgan
2025-12-18 11:38   ` Jonathan Cameron
2025-12-19 12:04     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 09/38] arm_mpam: resctrl: Implement resctrl_arch_reset_all_ctrls() James Morse
2025-12-05 21:58 ` [RFC PATCH 10/38] arm_mpam: resctrl: Add resctrl_arch_get_config() James Morse
2025-12-05 21:58 ` [RFC PATCH 11/38] arm_mpam: resctrl: Implement helpers to update configuration James Morse
2025-12-18 11:47   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 12/38] arm_mpam: resctrl: Add plumbing against arm64 task and cpu hooks James Morse
2025-12-05 21:58 ` [RFC PATCH 13/38] arm_mpam: resctrl: Add CDP emulation James Morse
2025-12-16 13:49   ` Ben Horgan
2025-12-16 14:24   ` Ben Horgan
2025-12-18 11:58   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 14/38] arm_mpam: resctrl: Add rmid index helpers James Morse
2025-12-05 21:58 ` [RFC PATCH 15/38] arm_mpam: resctrl: Convert to/from MPAMs fixed-point formats James Morse
2025-12-05 21:58 ` [RFC PATCH 16/38] arm_mpam: resctrl: Add support for 'MB' resource James Morse
2025-12-12  4:27   ` Gavin Shan
2025-12-16 15:56     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 17/38] arm_mpam: resctrl: Add kunit test for control format conversions James Morse
2025-12-05 21:58 ` [RFC PATCH 18/38] arm_mpam: resctrl: Add support for csu counters James Morse
2025-12-16 13:55   ` Ben Horgan
2025-12-18 13:20   ` Jonathan Cameron
2025-12-19 12:06     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 19/38] arm_mpam: resctrl: pick classes for use as mbm counters James Morse
2025-12-18 13:36   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 20/38] arm_mpam: resctrl: Pre-allocate free running monitors James Morse
2025-12-05 21:58 ` [RFC PATCH 21/38] arm_mpam: resctrl: Pre-allocate assignable monitors James Morse
2025-12-18 13:42   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 22/38] arm_mpam: resctrl: Add kunit test for ABMC/CDP interactions James Morse
2025-12-05 21:58 ` [RFC PATCH 23/38] arm_mpam: resctrl: Add resctrl_arch_config_cntr() for ABMC use James Morse
2025-12-05 21:58 ` [RFC PATCH 24/38] arm_mpam: resctrl: Allow resctrl to allocate monitors James Morse
2025-12-16 16:58   ` Ben Horgan
2025-12-18 13:49   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 25/38] arm_mpam: resctrl: Add resctrl_arch_rmid_read() and resctrl_arch_reset_rmid() James Morse
2025-12-18 13:53   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 26/38] arm_mpam: resctrl: Add resctrl_arch_cntr_read() & resctrl_arch_reset_cntr() James Morse
2025-12-05 21:58 ` [RFC PATCH 27/38] arm_mpam: resctrl: Add empty definitions for assorted resctrl functions James Morse
2025-12-09 16:31   ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 28/38] arm64: mpam: Select ARCH_HAS_CPU_RESCTRL James Morse
2025-12-09 16:33   ` Ben Horgan
2025-12-18 13:55   ` Jonathan Cameron
2025-12-05 21:58 ` [RFC PATCH 29/38] arm_mpam: resctrl: Call resctrl_init() on platforms that can support resctrl James Morse
2025-12-05 21:58 ` [RFC PATCH 30/38] arm_mpam: resctrl: Call resctrl_exit() in the event of errors James Morse
2025-12-05 21:58 ` [RFC PATCH 31/38] arm_mpam: resctrl: Update the rmid reallocation limit James Morse
2025-12-06  0:06   ` Fenghua Yu
2025-12-09 16:36     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 32/38] arm_mpam: resctrl: Sort the order of the domain lists James Morse
2025-12-05 21:58 ` [RFC PATCH 33/38] arm_mpam: Generate a configuration for min controls James Morse
2025-12-09 16:45   ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 34/38] arm_mpam: Add quirk framework James Morse
2025-12-18 14:04   ` Jonathan Cameron
2025-12-19 12:19     ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 35/38] arm_mpam: Add workaround for T241-MPAM-1 James Morse
2025-12-10 12:20   ` Ben Horgan
2025-12-05 21:58 ` [RFC PATCH 36/38] arm_mpam: Add workaround for T241-MPAM-4 James Morse
2025-12-09 16:58   ` Ben Horgan
2025-12-05 21:59 ` [RFC PATCH 37/38] arm_mpam: Add workaround for T241-MPAM-6 James Morse
2025-12-09 17:06   ` Ben Horgan
2025-12-05 21:59 ` [RFC PATCH 38/38] arm_mpam: Quirk CMN-650's CSU NRDY behaviour James Morse
2025-12-09 14:40 ` [RFC PATCH 00/38] arm_mpam: Add KVM/arm64 and resctrl glue code Ben Horgan
2025-12-09 15:53   ` Peter Newman
2025-12-09 16:14     ` Ben Horgan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251205215901.17772-2-james.morse@arm.com \
    --to=james.morse@arm.com \
    --cc=amitsinght@marvell.com \
    --cc=baisheng.gao@unisoc.com \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=ben.horgan@arm.com \
    --cc=bobo.shaobowang@huawei.com \
    --cc=carl@os.amperecomputing.com \
    --cc=dave.martin@arm.com \
    --cc=david@kernel.org \
    --cc=dfustini@baylibre.com \
    --cc=fenghuay@nvidia.com \
    --cc=gshan@redhat.com \
    --cc=jonathan.cameron@huawei.com \
    --cc=kobak@nvidia.com \
    --cc=lcherian@marvell.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peternewman@google.com \
    --cc=punit.agrawal@oss.qualcomm.com \
    --cc=quic_jiles@quicinc.com \
    --cc=reinette.chatre@intel.com \
    --cc=rohit.mathew@arm.com \
    --cc=scott@os.amperecomputing.com \
    --cc=sdonthineni@nvidia.com \
    --cc=tan.shaopeng@fujitsu.com \
    --cc=xhao@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).