Skip to content

Commit 51f1b16

Browse files
Merge patch series "riscv: add SBI FWFT misaligned exception delegation support"
Clément Léger <[email protected]> says: The SBI Firmware Feature extension allows the S-mode to request some specific features (either hardware or software) to be enabled. This series uses this extension to request misaligned access exception delegation to S-mode in order to let the kernel handle it. It also adds support for the KVM FWFT SBI extension based on the misaligned access handling infrastructure. FWFT SBI extension is part of the SBI V3.0 specifications [1]. It can be tested using the qemu provided at [2] which contains the series from [3]. Upstream kvm-unit-tests can be used inside kvm to tests the correct delegation of misaligned exceptions. Upstream OpenSBI can be used. The tests can be run using the kselftest from series [4]. $ qemu-system-riscv64 \ -cpu rv64,trap-misaligned-access=true,v=true \ -M virt \ -m 1024M \ -bios fw_dynamic.bin \ -kernel Image ... # ./misaligned TAP version 13 1..23 # Starting 23 tests from 1 test cases. # RUN global.gp_load_lh ... # OK global.gp_load_lh ok 1 global.gp_load_lh # RUN global.gp_load_lhu ... # OK global.gp_load_lhu ok 2 global.gp_load_lhu # RUN global.gp_load_lw ... # OK global.gp_load_lw ok 3 global.gp_load_lw # RUN global.gp_load_lwu ... # OK global.gp_load_lwu ok 4 global.gp_load_lwu # RUN global.gp_load_ld ... # OK global.gp_load_ld ok 5 global.gp_load_ld # RUN global.gp_load_c_lw ... # OK global.gp_load_c_lw ok 6 global.gp_load_c_lw # RUN global.gp_load_c_ld ... # OK global.gp_load_c_ld ok 7 global.gp_load_c_ld # RUN global.gp_load_c_ldsp ... # OK global.gp_load_c_ldsp ok 8 global.gp_load_c_ldsp # RUN global.gp_load_sh ... # OK global.gp_load_sh ok 9 global.gp_load_sh # RUN global.gp_load_sw ... # OK global.gp_load_sw ok 10 global.gp_load_sw # RUN global.gp_load_sd ... # OK global.gp_load_sd ok 11 global.gp_load_sd # RUN global.gp_load_c_sw ... # OK global.gp_load_c_sw ok 12 global.gp_load_c_sw # RUN global.gp_load_c_sd ... # OK global.gp_load_c_sd ok 13 global.gp_load_c_sd # RUN global.gp_load_c_sdsp ... # OK global.gp_load_c_sdsp ok 14 global.gp_load_c_sdsp # RUN global.fpu_load_flw ... # OK global.fpu_load_flw ok 15 global.fpu_load_flw # RUN global.fpu_load_fld ... # OK global.fpu_load_fld ok 16 global.fpu_load_fld # RUN global.fpu_load_c_fld ... # OK global.fpu_load_c_fld ok 17 global.fpu_load_c_fld # RUN global.fpu_load_c_fldsp ... # OK global.fpu_load_c_fldsp ok 18 global.fpu_load_c_fldsp # RUN global.fpu_store_fsw ... # OK global.fpu_store_fsw ok 19 global.fpu_store_fsw # RUN global.fpu_store_fsd ... # OK global.fpu_store_fsd ok 20 global.fpu_store_fsd # RUN global.fpu_store_c_fsd ... # OK global.fpu_store_c_fsd ok 21 global.fpu_store_c_fsd # RUN global.fpu_store_c_fsdsp ... # OK global.fpu_store_c_fsdsp ok 22 global.fpu_store_c_fsdsp # RUN global.gen_sigbus ... [12797.988647] misaligned[618]: unhandled signal 7 code 0x1 at 0x0000000000014dc0 in misaligned[4dc0,10000+76000] [12797.988990] CPU: 0 UID: 0 PID: 618 Comm: misaligned Not tainted 6.13.0-rc6-00008-g4ec4468967c9-dirty #51 [12797.989169] Hardware name: riscv-virtio,qemu (DT) [12797.989264] epc : 0000000000014dc0 ra : 0000000000014d00 sp : 00007fffe165d100 [12797.989407] gp : 000000000008f6e8 tp : 0000000000095760 t0 : 0000000000000008 [12797.989544] t1 : 00000000000965d8 t2 : 000000000008e830 s0 : 00007fffe165d160 [12797.989692] s1 : 000000000000001a a0 : 0000000000000000 a1 : 0000000000000002 [12797.989831] a2 : 0000000000000000 a3 : 0000000000000000 a4 : ffffffffdeadbeef [12797.989964] a5 : 000000000008ef61 a6 : 626769735f6e0000 a7 : fffffffffffff000 [12797.990094] s2 : 0000000000000001 s3 : 00007fffe165d838 s4 : 00007fffe165d848 [12797.990238] s5 : 000000000000001a s6 : 0000000000010442 s7 : 0000000000010200 [12797.990391] s8 : 000000000000003a s9 : 0000000000094508 s10: 0000000000000000 [12797.990526] s11: 0000555567460668 t3 : 00007fffe165d070 t4 : 00000000000965d0 [12797.990656] t5 : fefefefefefefeff t6 : 0000000000000073 [12797.990756] status: 0000000200004020 badaddr: 000000000008ef61 cause: 0000000000000006 [12797.990911] Code: 8793 8791 3423 fcf4 3783 fc84 c737 dead 0713 eef7 (c398) 0001 # OK global.gen_sigbus ok 23 global.gen_sigbus # PASSED: 23 / 23 tests passed. # Totals: pass:23 fail:0 xfail:0 xpass:0 skip:0 error:0 With kvm-tools: # lkvm run -k sbi.flat -m 128 Info: # lkvm run -k sbi.flat -m 128 -c 1 --name guest-97 Info: Removed ghost socket file "/root/.lkvm//guest-97.sock". ########################################################################## # kvm-unit-tests ########################################################################## ... [test messages elided] PASS: sbi: fwft: FWFT extension probing no error PASS: sbi: fwft: get/set reserved feature 0x6 error == SBI_ERR_DENIED PASS: sbi: fwft: get/set reserved feature 0x3fffffff error == SBI_ERR_DENIED PASS: sbi: fwft: get/set reserved feature 0x80000000 error == SBI_ERR_DENIED PASS: sbi: fwft: get/set reserved feature 0xbfffffff error == SBI_ERR_DENIED PASS: sbi: fwft: misaligned_deleg: Get misaligned deleg feature no error PASS: sbi: fwft: misaligned_deleg: Set misaligned deleg feature invalid value error PASS: sbi: fwft: misaligned_deleg: Set misaligned deleg feature invalid value error PASS: sbi: fwft: misaligned_deleg: Set misaligned deleg feature value no error PASS: sbi: fwft: misaligned_deleg: Set misaligned deleg feature value 0 PASS: sbi: fwft: misaligned_deleg: Set misaligned deleg feature value no error PASS: sbi: fwft: misaligned_deleg: Set misaligned deleg feature value 1 PASS: sbi: fwft: misaligned_deleg: Verify misaligned load exception trap in supervisor SUMMARY: 50 tests, 2 unexpected failures, 12 skipped This series is available at [5]. [Palmer: slighyt commit text modification, as SBI-3.0 is merged now. Also drop the KVM patches, as they're too late.] * b4-shazam-merge: riscv: misaligned: add a function to check misalign trap delegability riscv: misaligned: move emulated access uniformity check in a function riscv: misaligned: declare misaligned_access_speed under CONFIG_RISCV_MISALIGNED riscv: misaligned: use on_each_cpu() for scalar misaligned access probing riscv: misaligned: request misaligned exception from SBI riscv: sbi: add SBI FWFT extension calls riscv: sbi: add FWFT extension interface riscv: sbi: add new SBI error mappings riscv: sbi: remove useless parenthesis riscv: sbi: add Firmware Feature (FWFT) SBI extensions definitions Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents a921f07 + 7977448 commit 51f1b16

File tree

5 files changed

+257
-18
lines changed

5 files changed

+257
-18
lines changed

arch/riscv/include/asm/cpufeature.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,28 @@ void __init riscv_user_isa_enable(void);
6767
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
6868

6969
bool __init check_unaligned_access_emulated_all_cpus(void);
70+
void unaligned_access_init(void);
71+
int cpu_online_unaligned_access_init(unsigned int cpu);
7072
#if defined(CONFIG_RISCV_SCALAR_MISALIGNED)
71-
void check_unaligned_access_emulated(struct work_struct *work __always_unused);
7273
void unaligned_emulation_finish(void);
7374
bool unaligned_ctl_available(void);
74-
DECLARE_PER_CPU(long, misaligned_access_speed);
7575
#else
7676
static inline bool unaligned_ctl_available(void)
7777
{
7878
return false;
7979
}
8080
#endif
8181

82+
#if defined(CONFIG_RISCV_MISALIGNED)
83+
DECLARE_PER_CPU(long, misaligned_access_speed);
84+
bool misaligned_traps_can_delegate(void);
85+
#else
86+
static inline bool misaligned_traps_can_delegate(void)
87+
{
88+
return false;
89+
}
90+
#endif
91+
8292
bool __init check_vector_unaligned_access_emulated_all_cpus(void);
8393
#if defined(CONFIG_RISCV_VECTOR_MISALIGNED)
8494
void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused);

arch/riscv/include/asm/sbi.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum sbi_ext_id {
3535
SBI_EXT_DBCN = 0x4442434E,
3636
SBI_EXT_STA = 0x535441,
3737
SBI_EXT_NACL = 0x4E41434C,
38+
SBI_EXT_FWFT = 0x46574654,
3839

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

406+
/* SBI function IDs for FW feature extension */
407+
#define SBI_EXT_FWFT_SET 0x0
408+
#define SBI_EXT_FWFT_GET 0x1
409+
410+
enum sbi_fwft_feature_t {
411+
SBI_FWFT_MISALIGNED_EXC_DELEG = 0x0,
412+
SBI_FWFT_LANDING_PAD = 0x1,
413+
SBI_FWFT_SHADOW_STACK = 0x2,
414+
SBI_FWFT_DOUBLE_TRAP = 0x3,
415+
SBI_FWFT_PTE_AD_HW_UPDATING = 0x4,
416+
SBI_FWFT_POINTER_MASKING_PMLEN = 0x5,
417+
SBI_FWFT_LOCAL_RESERVED_START = 0x6,
418+
SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff,
419+
SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000,
420+
SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff,
421+
422+
SBI_FWFT_GLOBAL_RESERVED_START = 0x80000000,
423+
SBI_FWFT_GLOBAL_RESERVED_END = 0xbfffffff,
424+
SBI_FWFT_GLOBAL_PLATFORM_START = 0xc0000000,
425+
SBI_FWFT_GLOBAL_PLATFORM_END = 0xffffffff,
426+
};
427+
428+
#define SBI_FWFT_PLATFORM_FEATURE_BIT BIT(30)
429+
#define SBI_FWFT_GLOBAL_FEATURE_BIT BIT(31)
430+
431+
#define SBI_FWFT_SET_FLAG_LOCK BIT(0)
432+
405433
/* SBI spec version fields */
406434
#define SBI_SPEC_VERSION_DEFAULT 0x1
407435
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
@@ -419,6 +447,11 @@ enum sbi_ext_nacl_feature {
419447
#define SBI_ERR_ALREADY_STARTED -7
420448
#define SBI_ERR_ALREADY_STOPPED -8
421449
#define SBI_ERR_NO_SHMEM -9
450+
#define SBI_ERR_INVALID_STATE -10
451+
#define SBI_ERR_BAD_RANGE -11
452+
#define SBI_ERR_TIMEOUT -12
453+
#define SBI_ERR_IO -13
454+
#define SBI_ERR_DENIED_LOCKED -14
422455

423456
extern unsigned long sbi_spec_version;
424457
struct sbiret {
@@ -470,6 +503,23 @@ int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask,
470503
unsigned long asid);
471504
long sbi_probe_extension(int ext);
472505

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+
473523
/* Check if current SBI specification version is 0.1 or not */
474524
static inline int sbi_spec_is_0_1(void)
475525
{
@@ -503,11 +553,21 @@ static inline int sbi_err_map_linux_errno(int err)
503553
case SBI_SUCCESS:
504554
return 0;
505555
case SBI_ERR_DENIED:
556+
case SBI_ERR_DENIED_LOCKED:
506557
return -EPERM;
507558
case SBI_ERR_INVALID_PARAM:
559+
case SBI_ERR_INVALID_STATE:
508560
return -EINVAL;
561+
case SBI_ERR_BAD_RANGE:
562+
return -ERANGE;
509563
case SBI_ERR_INVALID_ADDRESS:
510564
return -EFAULT;
565+
case SBI_ERR_NO_SHMEM:
566+
return -ENOMEM;
567+
case SBI_ERR_TIMEOUT:
568+
return -ETIMEDOUT;
569+
case SBI_ERR_IO:
570+
return -EIO;
511571
case SBI_ERR_NOT_SUPPORTED:
512572
case SBI_ERR_FAILURE:
513573
default:

arch/riscv/kernel/sbi.c

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

302+
static bool sbi_fwft_supported;
303+
304+
struct fwft_set_req {
305+
u32 feature;
306+
unsigned long value;
307+
unsigned long flags;
308+
atomic_t error;
309+
};
310+
311+
static void cpu_sbi_fwft_set(void *arg)
312+
{
313+
struct fwft_set_req *req = arg;
314+
int ret;
315+
316+
ret = sbi_fwft_set(req->feature, req->value, req->flags);
317+
if (ret)
318+
atomic_set(&req->error, ret);
319+
}
320+
321+
/**
322+
* sbi_fwft_set() - Set a feature on the local hart
323+
* @feature: The feature ID to be set
324+
* @value: The feature value to be set
325+
* @flags: FWFT feature set flags
326+
*
327+
* Return: 0 on success, appropriate linux error code otherwise.
328+
*/
329+
int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
330+
{
331+
struct sbiret ret;
332+
333+
if (!sbi_fwft_supported)
334+
return -EOPNOTSUPP;
335+
336+
ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
337+
feature, value, flags, 0, 0, 0);
338+
339+
return sbi_err_map_linux_errno(ret.error);
340+
}
341+
342+
/**
343+
* sbi_fwft_set_cpumask() - Set a feature for the specified cpumask
344+
* @mask: CPU mask of cpus that need the feature to be set
345+
* @feature: The feature ID to be set
346+
* @value: The feature value to be set
347+
* @flags: FWFT feature set flags
348+
*
349+
* Return: 0 on success, appropriate linux error code otherwise.
350+
*/
351+
int sbi_fwft_set_cpumask(const cpumask_t *mask, u32 feature,
352+
unsigned long value, unsigned long flags)
353+
{
354+
struct fwft_set_req req = {
355+
.feature = feature,
356+
.value = value,
357+
.flags = flags,
358+
.error = ATOMIC_INIT(0),
359+
};
360+
361+
if (!sbi_fwft_supported)
362+
return -EOPNOTSUPP;
363+
364+
if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
365+
return -EINVAL;
366+
367+
on_each_cpu_mask(mask, cpu_sbi_fwft_set, &req, 1);
368+
369+
return atomic_read(&req.error);
370+
}
371+
302372
/**
303373
* sbi_set_timer() - Program the timer for next timer event.
304374
* @stime_value: The value after which next timer event should fire.
@@ -609,19 +679,24 @@ void __init sbi_init(void)
609679
} else {
610680
__sbi_rfence = __sbi_rfence_v01;
611681
}
612-
if ((sbi_spec_version >= sbi_mk_version(0, 3)) &&
682+
if (sbi_spec_version >= sbi_mk_version(0, 3) &&
613683
sbi_probe_extension(SBI_EXT_SRST)) {
614684
pr_info("SBI SRST extension detected\n");
615685
pm_power_off = sbi_srst_power_off;
616686
sbi_srst_reboot_nb.notifier_call = sbi_srst_reboot;
617687
sbi_srst_reboot_nb.priority = 192;
618688
register_restart_handler(&sbi_srst_reboot_nb);
619689
}
620-
if ((sbi_spec_version >= sbi_mk_version(2, 0)) &&
621-
(sbi_probe_extension(SBI_EXT_DBCN) > 0)) {
690+
if (sbi_spec_version >= sbi_mk_version(2, 0) &&
691+
sbi_probe_extension(SBI_EXT_DBCN) > 0) {
622692
pr_info("SBI DBCN extension detected\n");
623693
sbi_debug_console_available = true;
624694
}
695+
if (sbi_spec_version >= sbi_mk_version(3, 0) &&
696+
sbi_probe_extension(SBI_EXT_FWFT)) {
697+
pr_info("SBI FWFT extension detected\n");
698+
sbi_fwft_supported = true;
699+
}
625700
} else {
626701
__sbi_set_timer = __sbi_set_timer_v01;
627702
__sbi_send_ipi = __sbi_send_ipi_v01;

0 commit comments

Comments
 (0)