Skip to content

Commit 6d6d064

Browse files
clementlegerpalmer-dabbelt
authored andcommitted
riscv: sbi: add FWFT extension interface
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 <[email protected]> Reviewed-by: Andrew Jones <[email protected]> Reviewed-by: Atish Patra <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 99cf5b7 commit 6d6d064

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

arch/riscv/include/asm/sbi.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,23 @@ int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask,
503503
unsigned long asid);
504504
long sbi_probe_extension(int ext);
505505

506+
int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags);
507+
int sbi_fwft_set_cpumask(const cpumask_t *mask, u32 feature,
508+
unsigned long value, unsigned long flags);
509+
/**
510+
* sbi_fwft_set_online_cpus() - Set a feature on all online cpus
511+
* @feature: The feature to be set
512+
* @value: The feature value to be set
513+
* @flags: FWFT feature set flags
514+
*
515+
* Return: 0 on success, appropriate linux error code otherwise.
516+
*/
517+
static inline int sbi_fwft_set_online_cpus(u32 feature, unsigned long value,
518+
unsigned long flags)
519+
{
520+
return sbi_fwft_set_cpumask(cpu_online_mask, feature, value, flags);
521+
}
522+
506523
/* Check if current SBI specification version is 0.1 or not */
507524
static inline int sbi_spec_is_0_1(void)
508525
{

arch/riscv/kernel/sbi.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,63 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
299299
return 0;
300300
}
301301

302+
struct fwft_set_req {
303+
u32 feature;
304+
unsigned long value;
305+
unsigned long flags;
306+
atomic_t error;
307+
};
308+
309+
static void cpu_sbi_fwft_set(void *arg)
310+
{
311+
struct fwft_set_req *req = arg;
312+
int ret;
313+
314+
ret = sbi_fwft_set(req->feature, req->value, req->flags);
315+
if (ret)
316+
atomic_set(&req->error, ret);
317+
}
318+
319+
/**
320+
* sbi_fwft_set() - Set a feature on the local hart
321+
* @feature: The feature ID to be set
322+
* @value: The feature value to be set
323+
* @flags: FWFT feature set flags
324+
*
325+
* Return: 0 on success, appropriate linux error code otherwise.
326+
*/
327+
int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
328+
{
329+
return -EOPNOTSUPP;
330+
}
331+
332+
/**
333+
* sbi_fwft_set_cpumask() - Set a feature for the specified cpumask
334+
* @mask: CPU mask of cpus that need the feature to be set
335+
* @feature: The feature ID to be set
336+
* @value: The feature value to be set
337+
* @flags: FWFT feature set flags
338+
*
339+
* Return: 0 on success, appropriate linux error code otherwise.
340+
*/
341+
int sbi_fwft_set_cpumask(const cpumask_t *mask, u32 feature,
342+
unsigned long value, unsigned long flags)
343+
{
344+
struct fwft_set_req req = {
345+
.feature = feature,
346+
.value = value,
347+
.flags = flags,
348+
.error = ATOMIC_INIT(0),
349+
};
350+
351+
if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
352+
return -EINVAL;
353+
354+
on_each_cpu_mask(mask, cpu_sbi_fwft_set, &req, 1);
355+
356+
return atomic_read(&req.error);
357+
}
358+
302359
/**
303360
* sbi_set_timer() - Program the timer for next timer event.
304361
* @stime_value: The value after which next timer event should fire.

0 commit comments

Comments
 (0)