Add support for the srmcfg CSR defined in the Ssqosid ISA extension
(Supervisor-mode Quality of Service ID). The CSR contains two fields:
- Resource Control ID (RCID) used determine resource allocation
- Monitoring Counter ID (MCID) used to track resource usage
Requests from a hart to shared resources like cache will be tagged with
these IDs. This allows the usage of shared resources to be associated
with the task currently running on the hart.
A srmcfg field is added to thread_struct and has the same format as the
srmcfg CSR. This allows the scheduler to set the hart's srmcfg CSR to
contain the RCID and MCID for the task that is being scheduled in. The
srmcfg CSR is only written to if the thread_struct.srmcfg is different
than the current value of the CSR.
A per-cpu variable cpu_srmcfg is used to mirror that state of the CSR.
This is because access to L1D hot memory should be several times faster
than a CSR read. Also, in the case of virtualization, accesses to this
CSR are trapped in the hypervisor.
Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
Co-developed-by: Kornel Dulęba <mindal@semihalf.com>
Signed-off-by: Kornel Dulęba <mindal@semihalf.com>
[fustini: rename csr to srmcfg, refactor switch_to, rebase on v6.17-rc5]
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
MAINTAINERS | 7 +++++++
arch/riscv/Kconfig | 17 ++++++++++++++++
arch/riscv/include/asm/csr.h | 8 ++++++++
arch/riscv/include/asm/processor.h | 3 +++
arch/riscv/include/asm/qos.h | 41 ++++++++++++++++++++++++++++++++++++++
arch/riscv/include/asm/switch_to.h | 3 +++
arch/riscv/kernel/Makefile | 2 ++
arch/riscv/kernel/qos/Makefile | 2 ++
arch/riscv/kernel/qos/qos.c | 5 +++++
9 files changed, 88 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index cd7ff55b5d321752ac44c91d2d7e74de28e08960..93da9339d2fd6f5a6aed6041dab2282b27d86162 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21729,6 +21729,13 @@ F: drivers/perf/riscv_pmu.c
F: drivers/perf/riscv_pmu_legacy.c
F: drivers/perf/riscv_pmu_sbi.c
+RISC-V QOS RESCTRL SUPPORT
+M: Drew Fustini <fustini@kernel.org>
+L: linux-riscv@lists.infradead.org
+S: Supported
+F: arch/riscv/include/asm/qos.h
+F: arch/riscv/kernel/qos/
+
RISC-V SPACEMIT SoC Support
M: Yixun Lan <dlan@gentoo.org>
L: linux-riscv@lists.infradead.org
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 51dcd8eaa24356d947ebe0f1c4a701a3cfc6b757..9b09a7aad29621d99f14d414751e67a43cbdad3a 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -605,6 +605,23 @@ config RISCV_ISA_SVNAPOT
If you don't know what to do here, say Y.
+config RISCV_ISA_SSQOSID
+ bool "Ssqosid extension support for supervisor mode Quality of Service ID"
+ default y
+ help
+ Adds support for the Ssqosid ISA extension (Supervisor-mode
+ Quality of Service ID).
+
+ Ssqosid defines the srmcfg CSR which allows the system to tag the
+ running process with an RCID (Resource Control ID) and MCID
+ (Monitoring Counter ID). The RCID is used to determine resource
+ allocation. The MCID is used to track resource usage in event
+ counters.
+
+ For example, a cache controller may use the RCID to apply a
+ cache partitioning scheme and use the MCID to track how much
+ cache a process, or a group of processes, is using.
+
config RISCV_ISA_SVPBMT
bool "Svpbmt extension support for supervisor mode page-based memory types"
depends on 64BIT && MMU
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 6fed42e377059c7004ecd3c29eb36d5c0e36a656..ecc57492264c2a2616e1e147796157512da70e87 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -75,6 +75,13 @@
#define SATP_ASID_MASK _AC(0xFFFF, UL)
#endif
+/* SRMCFG fields */
+#define SRMCFG_RCID_MASK _AC(0x00000FFF, UL)
+#define SRMCFG_MCID_MASK SRMCFG_RCID_MASK
+#define SRMCFG_MCID_SHIFT 16
+#define SRMCFG_MASK ((SRMCFG_MCID_MASK << SRMCFG_MCID_SHIFT) | \
+ SRMCFG_RCID_MASK)
+
/* Exception cause high bit - is an interrupt if set */
#define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1))
@@ -317,6 +324,7 @@
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
#define CSR_SATP 0x180
+#define CSR_SRMCFG 0x181
#define CSR_STIMECMP 0x14D
#define CSR_STIMECMPH 0x15D
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 24d3af4d3807e37396744ef26533ac4661abcb4f..cc9548b85d363ecbc3c416e52906107a73e6053d 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -122,6 +122,9 @@ struct thread_struct {
/* A forced icache flush is not needed if migrating to the previous cpu. */
unsigned int prev_cpu;
#endif
+#ifdef CONFIG_RISCV_ISA_SSQOSID
+ u32 srmcfg;
+#endif
};
/* Whitelist the fstate from the task_struct for hardened usercopy */
diff --git a/arch/riscv/include/asm/qos.h b/arch/riscv/include/asm/qos.h
new file mode 100644
index 0000000000000000000000000000000000000000..7371e53e9e919b24f17c623ee72a0cbf62eadb2f
--- /dev/null
+++ b/arch/riscv/include/asm/qos.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_RISCV_QOS_H
+#define _ASM_RISCV_QOS_H
+
+#ifdef CONFIG_RISCV_ISA_SSQOSID
+
+#include <linux/sched.h>
+#include <linux/jump_label.h>
+
+#include <asm/barrier.h>
+#include <asm/csr.h>
+#include <asm/hwcap.h>
+
+/* cached value of srmcfg csr for each cpu */
+DECLARE_PER_CPU(u32, cpu_srmcfg);
+
+static inline void __switch_to_srmcfg(struct task_struct *next)
+{
+ u32 *cpu_srmcfg_ptr = this_cpu_ptr(&cpu_srmcfg);
+ u32 thread_srmcfg;
+
+ thread_srmcfg = READ_ONCE(next->thread.srmcfg);
+
+ if (thread_srmcfg != *cpu_srmcfg_ptr) {
+ *cpu_srmcfg_ptr = thread_srmcfg;
+ csr_write(CSR_SRMCFG, thread_srmcfg);
+ }
+}
+
+static __always_inline bool has_srmcfg(void)
+{
+ return riscv_has_extension_unlikely(RISCV_ISA_EXT_SSQOSID);
+}
+
+#else /* ! CONFIG_RISCV_ISA_SSQOSID */
+
+static __always_inline bool has_srmcfg(void) { return false; }
+#define __switch_to_srmcfg() do { } while (0)
+
+#endif /* CONFIG_RISCV_ISA_SSQOSID */
+#endif /* _ASM_RISCV_QOS_H */
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 0e71eb82f920cac2f14bb626879bb219a2f247cc..a684a3795d3d7f5e027ec0a83c30afd1a18d7228 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/csr.h>
+#include <asm/qos.h>
#ifdef CONFIG_FPU
extern void __fstate_save(struct task_struct *save_to);
@@ -119,6 +120,8 @@ do { \
__switch_to_fpu(__prev, __next); \
if (has_vector() || has_xtheadvector()) \
__switch_to_vector(__prev, __next); \
+ if (has_srmcfg()) \
+ __switch_to_srmcfg(__next); \
if (switch_to_should_flush_icache(__next)) \
local_flush_icache_all(); \
__switch_to_envcfg(__next); \
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index c7b542573407c813a4a45fe9bf78a676599c0503..0108a4e6338a7972b6805ef14048d4e5e8833d82 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -125,3 +125,5 @@ obj-$(CONFIG_ACPI) += acpi.o
obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o
obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += bugs.o
+
+obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos/
diff --git a/arch/riscv/kernel/qos/Makefile b/arch/riscv/kernel/qos/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..9f996263a86d7e2e410890d2425e74b2277a57ad
--- /dev/null
+++ b/arch/riscv/kernel/qos/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos.o
diff --git a/arch/riscv/kernel/qos/qos.c b/arch/riscv/kernel/qos/qos.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b06f7ae9056b8f2eb53a0eecf5a6512edc29fbe
--- /dev/null
+++ b/arch/riscv/kernel/qos/qos.c
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <asm/qos.h>
+
+/* cached value of sqoscfg csr for each cpu */
+DEFINE_PER_CPU(u32, cpu_srmcfg);
--
2.34.1
Hi Drew, kernel test robot noticed the following build errors: [auto build test ERROR on 76eeb9b8de9880ca38696b2fb56ac45ac0a25c6c] url: https://github.com/intel-lab-lkp/linux/commits/Drew-Fustini/dt-bindings-riscv-Add-Ssqosid-extension-description/20250916-131818 base: 76eeb9b8de9880ca38696b2fb56ac45ac0a25c6c patch link: https://lore.kernel.org/r/20250915-ssqosid-v6-17-rc5-v2-3-2d4b0254dfd6%40kernel.org patch subject: [PATCH v2 3/3] RISC-V: Add support for srmcfg CSR from Ssqosid ext config: riscv-allnoconfig (https://download.01.org/0day-ci/archive/20250916/202509162355.wByessnb-lkp@intel.com/config) compiler: riscv64-linux-gcc (GCC) 15.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250916/202509162355.wByessnb-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202509162355.wByessnb-lkp@intel.com/ All errors (new ones prefixed by >>): kernel/sched/core.c: In function 'context_switch': >> kernel/sched/core.c:5357:35: error: macro '__switch_to_srmcfg' passed 1 arguments, but takes just 0 5357 | switch_to(prev, next, prev); | ^ In file included from arch/riscv/include/asm/switch_to.h:17, from kernel/sched/core.c:80: arch/riscv/include/asm/qos.h:38:9: note: macro '__switch_to_srmcfg' defined here 38 | #define __switch_to_srmcfg() do { } while (0) | ^~~~~~~~~~~~~~~~~~ >> arch/riscv/include/asm/switch_to.h:124:17: error: '__switch_to_srmcfg' undeclared (first use in this function); did you mean '__switch_to_envcfg'? 124 | __switch_to_srmcfg(__next); \ | ^~~~~~~~~~~~~~~~~~ kernel/sched/core.c:5357:9: note: in expansion of macro 'switch_to' 5357 | switch_to(prev, next, prev); | ^~~~~~~~~ arch/riscv/include/asm/switch_to.h:124:17: note: each undeclared identifier is reported only once for each function it appears in 124 | __switch_to_srmcfg(__next); \ | ^~~~~~~~~~~~~~~~~~ kernel/sched/core.c:5357:9: note: in expansion of macro 'switch_to' 5357 | switch_to(prev, next, prev); | ^~~~~~~~~ vim +/__switch_to_srmcfg +5357 kernel/sched/core.c ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5296 ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5297 /* dfa50b605c2a93 kernel/sched/core.c Oleg Nesterov 2014-10-09 5298 * context_switch - switch to the new MM and the new thread's register state. ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5299 */ 049369487e2068 kernel/sched/core.c Josh Poimboeuf 2016-02-28 5300 static __always_inline struct rq * 70b97a7f0b19cf kernel/sched.c Ingo Molnar 2006-07-03 5301 context_switch(struct rq *rq, struct task_struct *prev, d8ac897137a230 kernel/sched/core.c Matt Fleming 2016-09-21 5302 struct task_struct *next, struct rq_flags *rf) ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5303 { e107be36efb2a2 kernel/sched.c Avi Kivity 2007-07-26 5304 prepare_task_switch(rq, prev, next); fe4b04fa31a6dc kernel/sched.c Peter Zijlstra 2011-02-02 5305 9226d125d94c7e kernel/sched.c Zachary Amsden 2007-02-13 5306 /* 9226d125d94c7e kernel/sched.c Zachary Amsden 2007-02-13 5307 * For paravirt, this is coupled with an exit in switch_to to 9226d125d94c7e kernel/sched.c Zachary Amsden 2007-02-13 5308 * combine the page table reload and the switch backend into 9226d125d94c7e kernel/sched.c Zachary Amsden 2007-02-13 5309 * one hypercall. 9226d125d94c7e kernel/sched.c Zachary Amsden 2007-02-13 5310 */ 224101ed69d3fb kernel/sched.c Jeremy Fitzhardinge 2009-02-18 5311 arch_start_context_switch(prev); 9226d125d94c7e kernel/sched.c Zachary Amsden 2007-02-13 5312 306e060435d7a3 kernel/sched/core.c Mathieu Desnoyers 2018-01-29 5313 /* 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5314 * kernel -> kernel lazy + transfer active aa464ba9a1e444 kernel/sched/core.c Nicholas Piggin 2023-02-03 5315 * user -> kernel lazy + mmgrab_lazy_tlb() active 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5316 * aa464ba9a1e444 kernel/sched/core.c Nicholas Piggin 2023-02-03 5317 * kernel -> user switch + mmdrop_lazy_tlb() active 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5318 * user -> user switch 223baf9d17f25e kernel/sched/core.c Mathieu Desnoyers 2023-04-20 5319 * 223baf9d17f25e kernel/sched/core.c Mathieu Desnoyers 2023-04-20 5320 * switch_mm_cid() needs to be updated if the barriers provided 223baf9d17f25e kernel/sched/core.c Mathieu Desnoyers 2023-04-20 5321 * by context_switch() are modified. 306e060435d7a3 kernel/sched/core.c Mathieu Desnoyers 2018-01-29 5322 */ 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5323 if (!next->mm) { // to kernel 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5324 enter_lazy_tlb(prev->active_mm, next); ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5325 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5326 next->active_mm = prev->active_mm; 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5327 if (prev->mm) // from user aa464ba9a1e444 kernel/sched/core.c Nicholas Piggin 2023-02-03 5328 mmgrab_lazy_tlb(prev->active_mm); 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5329 else 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5330 prev->active_mm = NULL; 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5331 } else { // to user 227a4aadc75ba2 kernel/sched/core.c Mathieu Desnoyers 2019-09-19 5332 membarrier_switch_mm(rq, prev->active_mm, next->mm); 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5333 /* 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5334 * sys_membarrier() requires an smp_mb() between setting 227a4aadc75ba2 kernel/sched/core.c Mathieu Desnoyers 2019-09-19 5335 * rq->curr / membarrier_switch_mm() and returning to userspace. 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5336 * 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5337 * The below provides this either through switch_mm(), or in 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5338 * case 'prev->active_mm == next->mm' through 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5339 * finish_task_switch()'s mmdrop(). 306e060435d7a3 kernel/sched/core.c Mathieu Desnoyers 2018-01-29 5340 */ 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5341 switch_mm_irqs_off(prev->active_mm, next->mm, next); bd74fdaea14602 kernel/sched/core.c Yu Zhao 2022-09-18 5342 lru_gen_use_mm(next->mm); 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5343 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5344 if (!prev->mm) { // from kernel aa464ba9a1e444 kernel/sched/core.c Nicholas Piggin 2023-02-03 5345 /* will mmdrop_lazy_tlb() in finish_task_switch(). */ 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5346 rq->prev_mm = prev->active_mm; ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5347 prev->active_mm = NULL; 139d025cda1da5 kernel/sched/core.c Peter Zijlstra 2019-07-29 5348 } ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5349 } 92509b732baf14 kernel/sched/core.c Matt Fleming 2016-09-21 5350 223baf9d17f25e kernel/sched/core.c Mathieu Desnoyers 2023-04-20 5351 /* switch_mm_cid() requires the memory barriers above. */ 223baf9d17f25e kernel/sched/core.c Mathieu Desnoyers 2023-04-20 5352 switch_mm_cid(rq, prev, next); 223baf9d17f25e kernel/sched/core.c Mathieu Desnoyers 2023-04-20 5353 269d599271fa60 kernel/sched/core.c Peter Zijlstra 2018-02-06 5354 prepare_lock_switch(rq, next, rf); ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5355 ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5356 /* Here we just switch the register state and the stack. */ ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 @5357 switch_to(prev, next, prev); dd41f596cda0d7 kernel/sched.c Ingo Molnar 2007-07-09 5358 barrier(); dfa50b605c2a93 kernel/sched/core.c Oleg Nesterov 2014-10-09 5359 dfa50b605c2a93 kernel/sched/core.c Oleg Nesterov 2014-10-09 5360 return finish_task_switch(prev); ^1da177e4c3f41 kernel/sched.c Linus Torvalds 2005-04-16 5361 } f711f6090a81cb kernel/sched.c Gautham R Shenoy 2009-04-14 5362 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
On Tue, Sep 16, 2025 at 11:55:39PM +0800, kernel test robot wrote: > Hi Drew, > > kernel test robot noticed the following build errors: > > [auto build test ERROR on 76eeb9b8de9880ca38696b2fb56ac45ac0a25c6c] > > url: https://github.com/intel-lab-lkp/linux/commits/Drew-Fustini/dt-bindings-riscv-Add-Ssqosid-extension-description/20250916-131818 > base: 76eeb9b8de9880ca38696b2fb56ac45ac0a25c6c > patch link: https://lore.kernel.org/r/20250915-ssqosid-v6-17-rc5-v2-3-2d4b0254dfd6%40kernel.org > patch subject: [PATCH v2 3/3] RISC-V: Add support for srmcfg CSR from Ssqosid ext > config: riscv-allnoconfig (https://download.01.org/0day-ci/archive/20250916/202509162355.wByessnb-lkp@intel.com/config) > compiler: riscv64-linux-gcc (GCC) 15.1.0 > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250916/202509162355.wByessnb-lkp@intel.com/reproduce) > > If you fix the issue in a separate patch/commit (i.e. not just a new version of > the same patch/commit), kindly add following tags > | Reported-by: kernel test robot <lkp@intel.com> > | Closes: https://lore.kernel.org/oe-kbuild-all/202509162355.wByessnb-lkp@intel.com/ > > All errors (new ones prefixed by >>): > > kernel/sched/core.c: In function 'context_switch': > >> kernel/sched/core.c:5357:35: error: macro '__switch_to_srmcfg' passed 1 arguments, but takes just 0 > 5357 | switch_to(prev, next, prev); > | ^ It seems I had incorrectly defined __switch_to_srmcfg() in the case where CONFIG_RISCV_ISA_SSQOSID is not defined. I was able to reproduce the error locally and this change seems to resolve it: diff --git a/arch/riscv/include/asm/qos.h b/arch/riscv/include/asm/qos.h index 7371e53e9e91..84830d7c6dc4 100644 --- a/arch/riscv/include/asm/qos.h +++ b/arch/riscv/include/asm/qos.h @@ -35,7 +35,7 @@ static __always_inline bool has_srmcfg(void) #else /* ! CONFIG_RISCV_ISA_SSQOSID */ static __always_inline bool has_srmcfg(void) { return false; } -#define __switch_to_srmcfg() do { } while (0) +#define __switch_to_srmcfg(__next) do { } while (0) #endif /* CONFIG_RISCV_ISA_SSQOSID */ #endif /* _ASM_RISCV_QOS_H */ I'll include this change in the next revision. Thanks, Drew
© 2016 - 2025 Red Hat, Inc.