1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_RISCV_QOS_H 3 #define _ASM_RISCV_QOS_H 4 5 #include <linux/percpu-defs.h> 6 7 #ifdef CONFIG_RISCV_ISA_SSQOSID 8 9 #include <linux/bitfield.h> 10 #include <linux/cpufeature.h> 11 #include <linux/sched.h> 12 13 #include <asm/csr.h> 14 #include <asm/hwcap.h> 15 16 /* cached value of srmcfg csr for each cpu */ 17 DECLARE_PER_CPU(u32, cpu_srmcfg); 18 19 /* default srmcfg value for each cpu, set via resctrl cpu assignment */ 20 DECLARE_PER_CPU(u32, cpu_srmcfg_default); 21 22 static inline void __switch_to_srmcfg(struct task_struct *next) 23 { 24 u32 thread_srmcfg, default_srmcfg; 25 26 thread_srmcfg = READ_ONCE(next->thread.srmcfg); 27 default_srmcfg = __this_cpu_read(cpu_srmcfg_default); 28 29 /* 30 * RCID and MCID inherit from cpu_srmcfg_default independently. 31 * RESCTRL_RESERVED_CLOSID and RESCTRL_RESERVED_RMID are both 0, so a 32 * zero field means "unassigned" and takes the CPU default. 33 */ 34 if (thread_srmcfg == 0) { 35 thread_srmcfg = default_srmcfg; 36 } else { 37 u32 rcid = FIELD_GET(SRMCFG_RCID_MASK, thread_srmcfg); 38 u32 mcid = FIELD_GET(SRMCFG_MCID_MASK, thread_srmcfg); 39 40 if (rcid == 0 || mcid == 0) { 41 if (rcid == 0) 42 rcid = FIELD_GET(SRMCFG_RCID_MASK, default_srmcfg); 43 if (mcid == 0) 44 mcid = FIELD_GET(SRMCFG_MCID_MASK, default_srmcfg); 45 thread_srmcfg = FIELD_PREP(SRMCFG_RCID_MASK, rcid) | 46 FIELD_PREP(SRMCFG_MCID_MASK, mcid); 47 } 48 } 49 50 if (thread_srmcfg != __this_cpu_read(cpu_srmcfg)) { 51 /* 52 * No fence around the csrw. Ssqosid is silent on srmcfg 53 * ordering versus memory accesses, so a few accesses at the 54 * switch boundary may carry the previous RCID/MCID. The 55 * tagging inaccuracy is bounded and acceptable for QoS. 56 */ 57 __this_cpu_write(cpu_srmcfg, thread_srmcfg); 58 csr_write(CSR_SRMCFG, thread_srmcfg); 59 } 60 } 61 62 static __always_inline bool has_srmcfg(void) 63 { 64 return riscv_has_extension_unlikely(RISCV_ISA_EXT_SSQOSID); 65 } 66 67 #else /* ! CONFIG_RISCV_ISA_SSQOSID */ 68 69 struct task_struct; 70 static __always_inline bool has_srmcfg(void) { return false; } 71 static inline void __switch_to_srmcfg(struct task_struct *next) { } 72 73 #endif /* CONFIG_RISCV_ISA_SSQOSID */ 74 #endif /* _ASM_RISCV_QOS_H */ 75