Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
db42d68
dt-bindings: riscv: Add Ssqosid extension description
pdp7 Jun 1, 2026
5661b9d
riscv: detect the Ssqosid extension
pdp7 Jun 1, 2026
9b303b4
riscv: add support for srmcfg CSR from Ssqosid extension
pdp7 Jun 1, 2026
08fb588
fs/resctrl: Add resctrl_is_membw() helper
pdp7 Jun 1, 2026
7376b80
fs/resctrl: Add RDT_RESOURCE_MB_MIN and RDT_RESOURCE_MB_WGHT
pdp7 Jun 1, 2026
e291163
fs/resctrl: Let bandwidth resources default to min_bw at reset
pdp7 Jun 1, 2026
34641a9
riscv_cbqri: Add capacity controller probe and allocation device ops
pdp7 Jun 1, 2026
dbf9d07
riscv_cbqri: Add capacity controller monitoring device ops
pdp7 Jun 1, 2026
ea9281a
riscv_cbqri: Add bandwidth controller probe and allocation device ops
pdp7 Jun 1, 2026
9b602cd
riscv_cbqri: Add bandwidth controller monitoring device ops
pdp7 Jun 1, 2026
a8fccc4
riscv_cbqri: resctrl: Add cache allocation via capacity block mask
pdp7 Jun 1, 2026
3fe7e97
riscv_cbqri: resctrl: Add L3 cache occupancy monitoring
pdp7 Jun 1, 2026
d3979c7
riscv_cbqri: resctrl: Add MB_MIN bandwidth allocation via Rbwb
pdp7 Jun 1, 2026
c5c5a1b
riscv_cbqri: resctrl: Add MB_WGHT bandwidth allocation via Mweight
pdp7 Jun 1, 2026
ba94af6
riscv_cbqri: resctrl: Add mbm_total_bytes bandwidth monitoring
pdp7 Jun 1, 2026
00a698d
ACPI: RISC-V: Parse RISC-V Quality of Service Controller (RQSC) table
pdp7 Jun 1, 2026
5fab83a
ACPI: RISC-V: Add support for RISC-V Quality of Service Controller (R…
pdp7 Jun 1, 2026
baa96f8
riscv: enable resctrl filesystem for Ssqosid
pdp7 Jun 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Documentation/devicetree/bindings/riscv/extensions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ properties:
ratified at commit d70011dde6c2 ("Update to ratified state")
of riscv-j-extension.

- const: ssqosid
description: |
The standard Ssqosid extension for Quality of Service ID is
ratified as v1.0 in commit d9c616497fde ("Merge pull
request #7 from ved-rivos/Ratified") of riscv-ssqosid.

- const: ssstateen
description: |
The standard Ssstateen extension for supervisor-mode view of the
Expand Down
15 changes: 15 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -23017,6 +23017,21 @@ 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>
R: yunhui cui <cuiyunhui@bytedance.com>
L: linux-riscv@lists.infradead.org
S: Supported
F: arch/riscv/include/asm/qos.h
F: arch/riscv/include/asm/resctrl.h
F: arch/riscv/kernel/qos.c
F: drivers/acpi/riscv/rqsc.c
F: drivers/acpi/riscv/rqsc.h
F: drivers/resctrl/cbqri_devices.c
F: drivers/resctrl/cbqri_internal.h
F: drivers/resctrl/cbqri_resctrl.c
F: include/linux/riscv_cbqri.h

RISC-V RPMI AND MPXY DRIVERS
M: Rahul Pathak <rahul@summations.net>
M: Anup Patel <anup@brainfault.org>
Expand Down
20 changes: 20 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,26 @@ 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"
depends on 64BIT
default n
select ARCH_HAS_CPU_RESCTRL
select RISCV_CBQRI_DRIVER
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
Expand Down
10 changes: 10 additions & 0 deletions arch/riscv/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ int acpi_get_riscv_isa(struct acpi_table_header *table,

void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_size,
u32 *cboz_size, u32 *cbop_size);

#ifdef CONFIG_RISCV_CBQRI_DRIVER
int __init acpi_parse_rqsc(struct acpi_table_header *table);
#else
static inline int acpi_parse_rqsc(struct acpi_table_header *table)
{
return -EINVAL;
}
#endif /* CONFIG_RISCV_CBQRI_DRIVER */

#else
static inline void acpi_init_rintc_map(void) { }
static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
Expand Down
5 changes: 5 additions & 0 deletions arch/riscv/include/asm/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
#define SATP_ASID_MASK _AC(0xFFFF, UL)
#endif

/* SRMCFG fields */
#define SRMCFG_RCID_MASK GENMASK(11, 0)
#define SRMCFG_MCID_MASK GENMASK(27, 16)

/* Exception cause high bit - is an interrupt if set */
#define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1))

Expand Down Expand Up @@ -328,6 +332,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
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
#define RISCV_ISA_EXT_ZCLSD 103
#define RISCV_ISA_EXT_ZICFILP 104
#define RISCV_ISA_EXT_ZICFISS 105
#define RISCV_ISA_EXT_SSQOSID 106

#define RISCV_ISA_EXT_XLINUXENVCFG 127

Expand Down
3 changes: 3 additions & 0 deletions arch/riscv/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,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 */
Expand Down
87 changes: 87 additions & 0 deletions arch/riscv/include/asm/qos.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_RISCV_QOS_H
#define _ASM_RISCV_QOS_H

#include <linux/percpu-defs.h>

#ifdef CONFIG_RISCV_ISA_SSQOSID

#include <linux/bitfield.h>
#include <linux/cpufeature.h>
#include <linux/sched.h>

#include <asm/csr.h>
#include <asm/fence.h>
#include <asm/hwcap.h>

/* cached value of srmcfg csr for each cpu */
DECLARE_PER_CPU(u32, cpu_srmcfg);

/* default srmcfg value for each cpu, set via resctrl cpu assignment */
DECLARE_PER_CPU(u32, cpu_srmcfg_default);

static inline void __switch_to_srmcfg(struct task_struct *next)
{
u32 thread_srmcfg, default_srmcfg;

thread_srmcfg = READ_ONCE(next->thread.srmcfg);
default_srmcfg = __this_cpu_read(cpu_srmcfg_default);

/*
* RCID and MCID inherit from cpu_srmcfg_default independently.
* RESCTRL_RESERVED_CLOSID and RESCTRL_RESERVED_RMID are both 0,
* so a per-field zero means "no task assignment for this
* dimension" and the CPU default supplies that field. Matches
* x86 RDT's __resctrl_sched_in() per-field logic. The fully
* unassigned (thread.srmcfg == 0) and fully assigned (both
* fields non-zero) cases short-circuit the field math.
*/
if (thread_srmcfg == 0) {
thread_srmcfg = default_srmcfg;
} else {
u32 rcid = FIELD_GET(SRMCFG_RCID_MASK, thread_srmcfg);
u32 mcid = FIELD_GET(SRMCFG_MCID_MASK, thread_srmcfg);

if (rcid == 0 || mcid == 0) {
if (rcid == 0)
rcid = FIELD_GET(SRMCFG_RCID_MASK, default_srmcfg);
if (mcid == 0)
mcid = FIELD_GET(SRMCFG_MCID_MASK, default_srmcfg);
thread_srmcfg = FIELD_PREP(SRMCFG_RCID_MASK, rcid) |
FIELD_PREP(SRMCFG_MCID_MASK, mcid);
}
}

if (thread_srmcfg != __this_cpu_read(cpu_srmcfg)) {
/*
* Drain stores from the outgoing task before the CSR write
* so they retain the previous RCID/MCID tag at the cache
* interconnect.
*/
RISCV_FENCE(rw, o);

__this_cpu_write(cpu_srmcfg, thread_srmcfg);
csr_write(CSR_SRMCFG, thread_srmcfg);
/*
* Order the csrw before the new task's loads/stores so they
* pick up the new tag. Zicsr 6.1.1 makes CSR writes weakly
* ordered (device-output) vs memory ops. Ssqosid v1.0 is
* silent so honor the general CSR rule.
*/
RISCV_FENCE(o, rw);
}
}

static __always_inline bool has_srmcfg(void)
{
return riscv_has_extension_unlikely(RISCV_ISA_EXT_SSQOSID);
}

#else /* ! CONFIG_RISCV_ISA_SSQOSID */

struct task_struct;
static __always_inline bool has_srmcfg(void) { return false; }
static inline void __switch_to_srmcfg(struct task_struct *next) { }

#endif /* CONFIG_RISCV_ISA_SSQOSID */
#endif /* _ASM_RISCV_QOS_H */
152 changes: 152 additions & 0 deletions arch/riscv/include/asm/resctrl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ASM_RISCV_RESCTRL_H
#define _ASM_RISCV_RESCTRL_H

#include <linux/resctrl_types.h>
#include <linux/sched.h>
#include <linux/types.h>

#include <asm/qos.h>

struct rdt_resource;

/*
* Sentinel "no CLOSID assigned" used by resctrl_arch_rmid_idx_decode().
* fs/resctrl treats this opaquely. CBQRI uses MCID directly as the linear
* rmid index, so closid is unused on decode.
*/
#define RISCV_RESCTRL_EMPTY_CLOSID ((u32)~0)

/*
* Terminology mapping between x86 (Intel RDT/AMD QoS) and RISC-V:
*
* CLOSID on x86 is RCID on RISC-V
* RMID on x86 is MCID on RISC-V
* CDP on x86 is AT (access type) on RISC-V
*
* Each fast-path arch entry point below is the RISC-V realization of the
* generic contract documented in <linux/resctrl.h>. Comments here describe
* only the RISC-V-specific behavior (srmcfg encoding, CBQRI controller
* lookup, MCID-as-index policy).
*/

/**
* resctrl_arch_alloc_capable() - any CBQRI controller exposes resctrl alloc
*
* Returns true once at least one CBQRI controller has successfully probed for
* a resctrl-exposed allocation feature (cache capacity or memory bandwidth).
* Only meaningful after cbqri_resctrl_setup() runs at late_initcall.
*/
bool resctrl_arch_alloc_capable(void);

/**
* resctrl_arch_mon_capable() - any CBQRI controller exposes resctrl monitoring
*
* Returns true once at least one CBQRI controller has successfully probed a
* monitoring event wired through resctrl (L3 occupancy or L3 mbm_total_bytes).
*/
bool resctrl_arch_mon_capable(void);

/**
* resctrl_arch_rmid_idx_encode() - encode (RCID, MCID) into a linear index
* @closid: RCID (resource control id)
* @rmid: MCID (monitoring counter id)
*
* RISC-V uses MCID directly as the linear index into per-RMID arrays
* managed by fs/resctrl, since CBQRI controllers admit any MCID for any
* RCID. closid is unused here. CDP is encoded via the AT field on each
* CBQRI op rather than via the index.
*/
u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid);

/**
* resctrl_arch_rmid_idx_decode() - inverse of resctrl_arch_rmid_idx_encode()
* @idx: linear index
* @closid: out: always RISCV_RESCTRL_EMPTY_CLOSID
* @rmid: out: the MCID that @idx encodes
*/
void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid);

/**
* resctrl_arch_set_cpu_default_closid_rmid() - install per-CPU srmcfg default
* @cpu: CPU number
* @closid: RCID to use when no task is matched
* @rmid: MCID to use when no task is matched
*
* Sets the per-CPU cpu_srmcfg_default so __switch_to_srmcfg() can fall back
* to the CPU's default RCID/MCID for default-group tasks (those whose
* thread.srmcfg encodes to 0, i.e. closid == RESCTRL_RESERVED_CLOSID and
* rmid == RESCTRL_RESERVED_RMID). Implements resctrl allocation rule 2
* ("CPU default") on RISC-V.
*/
void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid);

/**
* resctrl_arch_sched_in() - context-switch hook to install task RCID/MCID
* @tsk: the task being scheduled in
*
* Called from finish_task_switch() to write tsk->thread.srmcfg into the
* srmcfg CSR. Tasks tagged with RISCV_RESCTRL_EMPTY_CLOSID inherit the
* per-CPU default set via resctrl_arch_set_cpu_default_closid_rmid().
*/
void resctrl_arch_sched_in(struct task_struct *tsk);

/**
* resctrl_arch_set_closid_rmid() - tag a task with an RCID/MCID
* @tsk: task to tag
* @closid: RCID to install
* @rmid: MCID to install
*
* Updates tsk->thread.srmcfg with the encoded (RCID, MCID) pair. The new
* value takes effect on the next resctrl_arch_sched_in() for this task.
*/
void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid);

/**
* resctrl_arch_match_closid() - test whether a task carries a given RCID
* @tsk: task
* @closid: RCID
*/
bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid);

/**
* resctrl_arch_match_rmid() - test whether a task carries a given (RCID, MCID)
* @tsk: task
* @closid: RCID
* @rmid: MCID
*/
bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid);

/**
* resctrl_arch_mon_ctx_alloc() - allocate per-monitor-event arch context
* @r: resctrl resource being monitored
* @evtid: which monitor event needs context
*
* Returns an opaque pointer that resctrl_arch_rmid_read() can use to find the
* CBQRI controller backing this event. CBQRI's BC bandwidth context is
* keyed off the resource's L3 monitoring domain rather than per-event state,
* so this implementation returns NULL.
*/
void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, enum resctrl_event_id evtid);

/**
* resctrl_arch_mon_ctx_free() - release context returned by mon_ctx_alloc()
* @r: resctrl resource
* @evtid: monitor event id
* @arch_mon_ctx: pointer returned by resctrl_arch_mon_ctx_alloc()
*/
void resctrl_arch_mon_ctx_free(struct rdt_resource *r, enum resctrl_event_id evtid,
void *arch_mon_ctx);

static inline unsigned int resctrl_arch_round_mon_val(unsigned int val)
{
return val;
}

/* Not needed for RISC-V */
static inline void resctrl_arch_enable_mon(void) { }
static inline void resctrl_arch_disable_mon(void) { }
static inline void resctrl_arch_enable_alloc(void) { }
static inline void resctrl_arch_disable_alloc(void) { }

#endif /* _ASM_RISCV_RESCTRL_H */
3 changes: 3 additions & 0 deletions arch/riscv/include/asm/switch_to.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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); \
Expand Down
2 changes: 2 additions & 0 deletions arch/riscv/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,5 @@ obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o

obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += bugs.o
obj-$(CONFIG_RISCV_USER_CFI) += usercfi.o

obj-$(CONFIG_RISCV_ISA_SSQOSID) += qos.o
1 change: 1 addition & 0 deletions arch/riscv/kernel/cpufeature.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
__RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts),
__RISCV_ISA_EXT_DATA(ssqosid, RISCV_ISA_EXT_SSQOSID),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
__RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE),
__RISCV_ISA_EXT_DATA_VALIDATE(svadu, RISCV_ISA_EXT_SVADU, riscv_ext_svadu_validate),
Expand Down
Loading