On 4/24/25 10:31 AM, Clément Léger wrote:
This SBI extensions enables supervisor mode to control feature that are under M-mode control (For instance, Svadu menvcfg ADUE bit, Ssdbltrp DTE, etc). Add an interface to set local features for a specific cpu mask as well as for the online cpu mask.
Signed-off-by: Clément Léger cleger@rivosinc.com Reviewed-by: Andrew Jones ajones@ventanamicro.com
arch/riscv/include/asm/sbi.h | 17 +++++++++++ arch/riscv/kernel/sbi.c | 57 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+)
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 7ec249fea880..3bbef56bcefc 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -503,6 +503,23 @@ int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask, unsigned long asid); long sbi_probe_extension(int ext); +int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags); +int sbi_fwft_set_cpumask(const cpumask_t *mask, u32 feature,
unsigned long value, unsigned long flags);
+/**
- sbi_fwft_set_online_cpus() - Set a feature on all online cpus
- @feature: The feature to be set
- @value: The feature value to be set
- @flags: FWFT feature set flags
- Return: 0 on success, appropriate linux error code otherwise.
- */
+static inline int sbi_fwft_set_online_cpus(u32 feature, unsigned long value,
unsigned long flags)
+{
- return sbi_fwft_set_cpumask(cpu_online_mask, feature, value, flags);
+}
- /* Check if current SBI specification version is 0.1 or not */ static inline int sbi_spec_is_0_1(void) {
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index 1d44c35305a9..d57e4dae7dac 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -299,6 +299,63 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask, return 0; } +/**
- sbi_fwft_set() - Set a feature on the local hart
- @feature: The feature ID to be set
- @value: The feature value to be set
- @flags: FWFT feature set flags
- Return: 0 on success, appropriate linux error code otherwise.
- */
+int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags) +{
- return -EOPNOTSUPP;
+}
+struct fwft_set_req {
- u32 feature;
- unsigned long value;
- unsigned long flags;
- atomic_t error;
+};
+static void cpu_sbi_fwft_set(void *arg) +{
- struct fwft_set_req *req = arg;
- int ret;
- ret = sbi_fwft_set(req->feature, req->value, req->flags);
- if (ret)
atomic_set(&req->error, ret);
+}
+/**
- sbi_fwft_set_cpumask() - Set a feature for the specified cpumask
- @mask: CPU mask of cpus that need the feature to be set
- @feature: The feature ID to be set
- @value: The feature value to be set
- @flags: FWFT feature set flags
- Return: 0 on success, appropriate linux error code otherwise.
- */
+int sbi_fwft_set_cpumask(const cpumask_t *mask, u32 feature,
unsigned long value, unsigned long flags)
+{
- struct fwft_set_req req = {
.feature = feature,
.value = value,
.flags = flags,
.error = ATOMIC_INIT(0),
- };
- if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
return -EINVAL;
- on_each_cpu_mask(mask, cpu_sbi_fwft_set, &req, 1);
- return atomic_read(&req.error);
+}
- /**
- sbi_set_timer() - Program the timer for next timer event.
- @stime_value: The value after which next timer event should fire.
LGTM. Reviewed-by: Atish Patra atishp@rivosinc.com