Skip to content

Commit b579dfe

Browse files
avpatelpalmer-dabbelt
authored andcommitted
RISC-V: Use SBI SRST extension when available
The SBI SRST extension provides a standard way to poweroff and reboot the system irrespective to whether Linux RISC-V S-mode is running natively (HS-mode) or inside Guest/VM (VS-mode). The SBI SRST extension is available in the SBI v0.3 specification. (Refer, https://github.com/riscv/riscv-sbi-doc/releases/tag/v0.3.0-rc1) This patch extends Linux RISC-V SBI implementation to detect and use SBI SRST extension. Signed-off-by: Anup Patel <[email protected]> Reviewed-by: Atish Patra <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent b0fd4b1 commit b579dfe

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

arch/riscv/include/asm/sbi.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ enum sbi_ext_id {
2727
SBI_EXT_IPI = 0x735049,
2828
SBI_EXT_RFENCE = 0x52464E43,
2929
SBI_EXT_HSM = 0x48534D,
30+
SBI_EXT_SRST = 0x53525354,
3031
};
3132

3233
enum sbi_ext_base_fid {
@@ -70,6 +71,21 @@ enum sbi_hsm_hart_status {
7071
SBI_HSM_HART_STATUS_STOP_PENDING,
7172
};
7273

74+
enum sbi_ext_srst_fid {
75+
SBI_EXT_SRST_RESET = 0,
76+
};
77+
78+
enum sbi_srst_reset_type {
79+
SBI_SRST_RESET_TYPE_SHUTDOWN = 0,
80+
SBI_SRST_RESET_TYPE_COLD_REBOOT,
81+
SBI_SRST_RESET_TYPE_WARM_REBOOT,
82+
};
83+
84+
enum sbi_srst_reset_reason {
85+
SBI_SRST_RESET_REASON_NONE = 0,
86+
SBI_SRST_RESET_REASON_SYS_FAILURE,
87+
};
88+
7389
#define SBI_SPEC_VERSION_DEFAULT 0x1
7490
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
7591
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
@@ -148,6 +164,14 @@ static inline unsigned long sbi_minor_version(void)
148164
return sbi_spec_version & SBI_SPEC_VERSION_MINOR_MASK;
149165
}
150166

167+
/* Make SBI version */
168+
static inline unsigned long sbi_mk_version(unsigned long major,
169+
unsigned long minor)
170+
{
171+
return ((major & SBI_SPEC_VERSION_MAJOR_MASK) <<
172+
SBI_SPEC_VERSION_MAJOR_SHIFT) | minor;
173+
}
174+
151175
int sbi_err_map_linux_errno(int err);
152176
#else /* CONFIG_RISCV_SBI */
153177
static inline int sbi_remote_fence_i(const unsigned long *hart_mask) { return -1; }

arch/riscv/kernel/sbi.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <linux/init.h>
99
#include <linux/pm.h>
10+
#include <linux/reboot.h>
1011
#include <asm/sbi.h>
1112
#include <asm/smp.h>
1213

@@ -501,6 +502,32 @@ int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask,
501502
}
502503
EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid);
503504

505+
static void sbi_srst_reset(unsigned long type, unsigned long reason)
506+
{
507+
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason,
508+
0, 0, 0, 0);
509+
pr_warn("%s: type=0x%lx reason=0x%lx failed\n",
510+
__func__, type, reason);
511+
}
512+
513+
static int sbi_srst_reboot(struct notifier_block *this,
514+
unsigned long mode, void *cmd)
515+
{
516+
sbi_srst_reset((mode == REBOOT_WARM || mode == REBOOT_SOFT) ?
517+
SBI_SRST_RESET_TYPE_WARM_REBOOT :
518+
SBI_SRST_RESET_TYPE_COLD_REBOOT,
519+
SBI_SRST_RESET_REASON_NONE);
520+
return NOTIFY_DONE;
521+
}
522+
523+
static struct notifier_block sbi_srst_reboot_nb;
524+
525+
static void sbi_srst_power_off(void)
526+
{
527+
sbi_srst_reset(SBI_SRST_RESET_TYPE_SHUTDOWN,
528+
SBI_SRST_RESET_REASON_NONE);
529+
}
530+
504531
/**
505532
* sbi_probe_extension() - Check if an SBI extension ID is supported or not.
506533
* @extid: The extension ID to be probed.
@@ -608,6 +635,14 @@ void __init sbi_init(void)
608635
} else {
609636
__sbi_rfence = __sbi_rfence_v01;
610637
}
638+
if ((sbi_spec_version >= sbi_mk_version(0, 3)) &&
639+
(sbi_probe_extension(SBI_EXT_SRST) > 0)) {
640+
pr_info("SBI SRST extension detected\n");
641+
pm_power_off = sbi_srst_power_off;
642+
sbi_srst_reboot_nb.notifier_call = sbi_srst_reboot;
643+
sbi_srst_reboot_nb.priority = 192;
644+
register_restart_handler(&sbi_srst_reboot_nb);
645+
}
611646
} else {
612647
__sbi_set_timer = __sbi_set_timer_v01;
613648
__sbi_send_ipi = __sbi_send_ipi_v01;

0 commit comments

Comments
 (0)