Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion arch/riscv/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ void __init riscv_user_isa_enable(void);
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)

bool __init check_unaligned_access_emulated_all_cpus(void);
void unaligned_access_init(void);
int cpu_online_unaligned_access_init(unsigned int cpu);
#if defined(CONFIG_RISCV_SCALAR_MISALIGNED)
void check_unaligned_access_emulated(struct work_struct *work __always_unused);
void unaligned_emulation_finish(void);
bool unaligned_ctl_available(void);
DECLARE_PER_CPU(long, misaligned_access_speed);
Expand All @@ -79,6 +80,15 @@ static inline bool unaligned_ctl_available(void)
}
#endif

#ifdef CONFIG_RISCV_MISALIGNED
bool misaligned_traps_can_delegate(void);
#else
static inline bool misaligned_traps_can_delegate(void)
{
return false;
}
#endif

bool __init check_vector_unaligned_access_emulated_all_cpus(void);
#if defined(CONFIG_RISCV_VECTOR_MISALIGNED)
void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused);
Expand Down
5 changes: 4 additions & 1 deletion arch/riscv/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <asm/kvm_vcpu_fp.h>
#include <asm/kvm_vcpu_insn.h>
#include <asm/kvm_vcpu_sbi.h>
#include <asm/kvm_vcpu_sbi_fwft.h>
#include <asm/kvm_vcpu_timer.h>
#include <asm/kvm_vcpu_pmu.h>

Expand Down Expand Up @@ -281,6 +282,9 @@ struct kvm_vcpu_arch {
/* Performance monitoring context */
struct kvm_pmu pmu_context;

/* Firmware feature SBI extension context */
struct kvm_sbi_fwft fwft_context;

/* 'static' configurations which are set only once */
struct kvm_vcpu_config cfg;

Expand Down Expand Up @@ -407,7 +411,6 @@ void __kvm_riscv_vcpu_power_on(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_power_on(struct kvm_vcpu *vcpu);
bool kvm_riscv_vcpu_stopped(struct kvm_vcpu *vcpu);

void kvm_riscv_vcpu_sbi_sta_reset(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu);

#endif /* __RISCV_KVM_HOST_H__ */
12 changes: 12 additions & 0 deletions arch/riscv/include/asm/kvm_vcpu_sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ struct kvm_vcpu_sbi_extension {

/* Extension specific probe function */
unsigned long (*probe)(struct kvm_vcpu *vcpu);

/*
* Init/deinit function called once during VCPU init/destroy. These
* might be use if the SBI extensions need to allocate or do specific
* init time only configuration.
*/
int (*init)(struct kvm_vcpu *vcpu);
void (*deinit)(struct kvm_vcpu *vcpu);
void (*reset)(struct kvm_vcpu *vcpu);
};

void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run);
Expand All @@ -69,6 +78,8 @@ const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx);
int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_sbi_reset(struct kvm_vcpu *vcpu);

int kvm_riscv_vcpu_get_reg_sbi_sta(struct kvm_vcpu *vcpu, unsigned long reg_num,
unsigned long *reg_val);
Expand All @@ -87,6 +98,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_sta;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_fwft;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;

Expand Down
29 changes: 29 additions & 0 deletions arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2025 Rivos Inc.
*
* Authors:
* Clément Léger <cleger@rivosinc.com>
*/

#ifndef __KVM_VCPU_RISCV_FWFT_H
#define __KVM_VCPU_RISCV_FWFT_H

#include <asm/sbi.h>

struct kvm_sbi_fwft_feature;

struct kvm_sbi_fwft_config {
const struct kvm_sbi_fwft_feature *feature;
bool supported;
unsigned long flags;
};

/* FWFT data structure per vcpu */
struct kvm_sbi_fwft {
struct kvm_sbi_fwft_config *configs;
};

#define vcpu_to_fwft(vcpu) (&(vcpu)->arch.fwft_context)

#endif /* !__KVM_VCPU_RISCV_FWFT_H */
60 changes: 60 additions & 0 deletions arch/riscv/include/asm/sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum sbi_ext_id {
SBI_EXT_DBCN = 0x4442434E,
SBI_EXT_STA = 0x535441,
SBI_EXT_NACL = 0x4E41434C,
SBI_EXT_FWFT = 0x46574654,

/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
Expand Down Expand Up @@ -402,6 +403,33 @@ enum sbi_ext_nacl_feature {
#define SBI_NACL_SHMEM_SRET_X(__i) ((__riscv_xlen / 8) * (__i))
#define SBI_NACL_SHMEM_SRET_X_LAST 31

/* SBI function IDs for FW feature extension */
#define SBI_EXT_FWFT_SET 0x0
#define SBI_EXT_FWFT_GET 0x1

enum sbi_fwft_feature_t {
SBI_FWFT_MISALIGNED_EXC_DELEG = 0x0,
SBI_FWFT_LANDING_PAD = 0x1,
SBI_FWFT_SHADOW_STACK = 0x2,
SBI_FWFT_DOUBLE_TRAP = 0x3,
SBI_FWFT_PTE_AD_HW_UPDATING = 0x4,
SBI_FWFT_POINTER_MASKING_PMLEN = 0x5,
SBI_FWFT_LOCAL_RESERVED_START = 0x6,
SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff,
SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000,
SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff,

SBI_FWFT_GLOBAL_RESERVED_START = 0x80000000,
SBI_FWFT_GLOBAL_RESERVED_END = 0xbfffffff,
SBI_FWFT_GLOBAL_PLATFORM_START = 0xc0000000,
SBI_FWFT_GLOBAL_PLATFORM_END = 0xffffffff,
};

#define SBI_FWFT_PLATFORM_FEATURE_BIT BIT(30)
#define SBI_FWFT_GLOBAL_FEATURE_BIT BIT(31)

#define SBI_FWFT_SET_FLAG_LOCK BIT(0)

/* SBI spec version fields */
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
Expand All @@ -419,6 +447,11 @@ enum sbi_ext_nacl_feature {
#define SBI_ERR_ALREADY_STARTED -7
#define SBI_ERR_ALREADY_STOPPED -8
#define SBI_ERR_NO_SHMEM -9
#define SBI_ERR_INVALID_STATE -10
#define SBI_ERR_BAD_RANGE -11
#define SBI_ERR_TIMEOUT -12
#define SBI_ERR_IO -13
#define SBI_ERR_DENIED_LOCKED -14

extern unsigned long sbi_spec_version;
struct sbiret {
Expand Down Expand Up @@ -470,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)
{
Expand Down Expand Up @@ -503,11 +553,21 @@ static inline int sbi_err_map_linux_errno(int err)
case SBI_SUCCESS:
return 0;
case SBI_ERR_DENIED:
case SBI_ERR_DENIED_LOCKED:
return -EPERM;
case SBI_ERR_INVALID_PARAM:
case SBI_ERR_INVALID_STATE:
return -EINVAL;
case SBI_ERR_BAD_RANGE:
return -ERANGE;
case SBI_ERR_INVALID_ADDRESS:
return -EFAULT;
case SBI_ERR_NO_SHMEM:
return -ENOMEM;
case SBI_ERR_TIMEOUT:
return -ETIMEDOUT;
case SBI_ERR_IO:
return -EIO;
case SBI_ERR_NOT_SUPPORTED:
case SBI_ERR_FAILURE:
default:
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ enum KVM_RISCV_SBI_EXT_ID {
KVM_RISCV_SBI_EXT_DBCN,
KVM_RISCV_SBI_EXT_STA,
KVM_RISCV_SBI_EXT_SUSP,
KVM_RISCV_SBI_EXT_FWFT,
KVM_RISCV_SBI_EXT_MAX,
};

Expand Down
81 changes: 78 additions & 3 deletions arch/riscv/kernel/sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,76 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
return 0;
}

static bool sbi_fwft_supported;

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)
{
struct sbiret ret;

if (!sbi_fwft_supported)
return -EOPNOTSUPP;

ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
feature, value, flags, 0, 0, 0);

return sbi_err_map_linux_errno(ret.error);
}

/**
* 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 (!sbi_fwft_supported)
return -EOPNOTSUPP;

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.
Expand Down Expand Up @@ -609,19 +679,24 @@ void __init sbi_init(void)
} else {
__sbi_rfence = __sbi_rfence_v01;
}
if ((sbi_spec_version >= sbi_mk_version(0, 3)) &&
if (sbi_spec_version >= sbi_mk_version(0, 3) &&
sbi_probe_extension(SBI_EXT_SRST)) {
pr_info("SBI SRST extension detected\n");
pm_power_off = sbi_srst_power_off;
sbi_srst_reboot_nb.notifier_call = sbi_srst_reboot;
sbi_srst_reboot_nb.priority = 192;
register_restart_handler(&sbi_srst_reboot_nb);
}
if ((sbi_spec_version >= sbi_mk_version(2, 0)) &&
(sbi_probe_extension(SBI_EXT_DBCN) > 0)) {
if (sbi_spec_version >= sbi_mk_version(2, 0) &&
sbi_probe_extension(SBI_EXT_DBCN) > 0) {
pr_info("SBI DBCN extension detected\n");
sbi_debug_console_available = true;
}
if (sbi_spec_version >= sbi_mk_version(3, 0) &&
sbi_probe_extension(SBI_EXT_FWFT)) {
pr_info("SBI FWFT extension detected\n");
sbi_fwft_supported = true;
}
} else {
__sbi_set_timer = __sbi_set_timer_v01;
__sbi_send_ipi = __sbi_send_ipi_v01;
Expand Down
Loading
Loading