Unverified Commit 6d6d0641 authored by Clément Léger's avatar Clément Léger Committed by Palmer Dabbelt
Browse files

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: default avatarClément Léger <cleger@rivosinc.com>
Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Reviewed-by: default avatarAtish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20250523101932.1594077-5-cleger@rivosinc.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@dabbelt.com>
parent 99cf5b7c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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)
{
+57 −0
Original line number Diff line number Diff line
@@ -299,6 +299,63 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
	return 0;
}

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() - 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;
}

/**
 * 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.