diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c58d74235363b4ec4c4e754b4235e586259aa680..4de2ce69f9fac6b4682eee464cade640d7c24fbf 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -409,6 +409,25 @@ config RISCV_ISA_C If you don't know what to do here, say Y. +config RISCV_ISA_SSQOSID + bool "Ssqosid extension support for supervisor mode QoS ID" + default y + help + Adds support for the Ssqosid ISA extension (Supervisor-mode + Quality of Service ID). + + Ssqosid defines the sqoscfg CSR which allows the system to tag + the running process with RCID (Resource Control ID) and MCID + (Monitoring Counter ID). The RCID is used 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. + + If you don't know what to do here, say Y. + config RISCV_ISA_SVNAPOT bool "Svnapot extension support for supervisor mode NAPOT pages" depends on 64BIT && MMU diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index 7c2b8cdb7b777774b5cdde40a8b06610fd7fa468..17d04a0cacd6f030a1591243f59b68e97049a196 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -59,6 +59,13 @@ #define SATP_ASID_MASK _AC(0xFFFF, UL) #endif +/* SQOSCFG fields */ +#define SQOSCFG_RCID_MASK _AC(0x00000FFF, UL) +#define SQOSCFG_MCID_MASK SQOSCFG_RCID_MASK +#define SQOSCFG_MCID_SHIFT 16 +#define SQOSCFG_MASK ((SQOSCFG_MCID_MASK << SQOSCFG_MCID_SHIFT) | \ + SQOSCFG_RCID_MASK) + /* Exception cause high bit - is an interrupt if set */ #define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1)) @@ -245,6 +252,7 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 #define CSR_SATP 0x180 +#define CSR_SQOSCFG 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 94a0590c69710b54e2e1f7258bd6692858ce5f90..724b2aa2732d64fafdba4a7a702a3aa901b63ee4 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -39,6 +39,9 @@ struct thread_struct { unsigned long s[12]; /* s[0]: frame pointer */ struct __riscv_d_ext_state fstate; unsigned long bad_cause; +#ifdef CONFIG_RISCV_ISA_SSQOSID + u32 sqoscfg; +#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..9d0fe1ac1b34a9eb4a6f1363cff16b28d3bfb414 --- /dev/null +++ b/arch/riscv/include/asm/qos.h @@ -0,0 +1,43 @@ +/* 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 sqoscfg csr for each cpu */ +DECLARE_PER_CPU(u32, cpu_sqoscfg); + +static inline void __switch_to_sqoscfg(struct task_struct *prev, + struct task_struct *next) +{ + u32 *cpu_sqoscfg_ptr = this_cpu_ptr(&cpu_sqoscfg); + u32 thread_sqoscfg; + + thread_sqoscfg = READ_ONCE(next->thread.sqoscfg); + + if (thread_sqoscfg != *cpu_sqoscfg_ptr) { + *cpu_sqoscfg_ptr = thread_sqoscfg; + csr_write(CSR_SQOSCFG, thread_sqoscfg); + } +} + +static __always_inline bool has_sqoscfg(void) +{ + return riscv_has_extension_likely(RISCV_ISA_EXT_SSQOSID); +} + +#else /* ! CONFIG_RISCV_ISA_SSQOSID */ + +static __always_inline bool has_sqoscfg(void) { return false; } +#define __switch_to_sqoscfg(__prev, __next) 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 60f8ca01d36e4514f29ee23594f92cb29ce079c6..79e8e907d7a66204e5edef4b4cd00de544ebe6ca 100644 --- a/arch/riscv/include/asm/switch_to.h +++ b/arch/riscv/include/asm/switch_to.h @@ -12,6 +12,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); @@ -78,6 +79,8 @@ do { \ struct task_struct *__next = (next); \ if (has_fpu()) \ __switch_to_aux(__prev, __next); \ + if (has_sqoscfg()) \ + __switch_to_sqoscfg(__prev, __next); \ ((last) = __switch_to(__prev, __next)); \ } while (0) diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 0fee73a20c87acc2e172f74aa1cf56e4f6277089..22c18b9162122315127a57b1cd66c03ec8d87e6f 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -89,3 +89,4 @@ obj-$(CONFIG_COMPAT) += compat_signal.o obj-$(CONFIG_COMPAT) += compat_vdso/ obj-$(CONFIG_64BIT) += pi/ +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..a6956664dfe151e574d32d12f6bbfbeaf7f0b141 --- /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_sqoscfg);