lib: sbi: Implement System Reset (SRST) SBI extension

The SBI SRST extension has been accepted and merged in the latest
SBI v0.3-draft specification.
(Refer, https://github.com/riscv/riscv-sbi-doc)

It allows to S-mode software to request system shutdown, cold reboot,
and warm reboot.

This patch implements SBI SRST extension as a replacement of the
legacy sbi_shutdown() call of SBI v0.1 specification.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
This commit is contained in:
Anup Patel
2020-11-24 14:20:19 +05:30
committed by Anup Patel
parent 5c429ae213
commit 548d03e577
3 changed files with 64 additions and 0 deletions

View File

@@ -37,6 +37,7 @@ extern struct sbi_ecall_extension ecall_rfence;
extern struct sbi_ecall_extension ecall_ipi; extern struct sbi_ecall_extension ecall_ipi;
extern struct sbi_ecall_extension ecall_vendor; extern struct sbi_ecall_extension ecall_vendor;
extern struct sbi_ecall_extension ecall_hsm; extern struct sbi_ecall_extension ecall_hsm;
extern struct sbi_ecall_extension ecall_srst;
u16 sbi_ecall_version_major(void); u16 sbi_ecall_version_major(void);

View File

@@ -167,6 +167,9 @@ int sbi_ecall_init(void)
if (ret) if (ret)
return ret; return ret;
ret = sbi_ecall_register_extension(&ecall_hsm); ret = sbi_ecall_register_extension(&ecall_hsm);
if (ret)
return ret;
ret = sbi_ecall_register_extension(&ecall_srst);
if (ret) if (ret)
return ret; return ret;
ret = sbi_ecall_register_extension(&ecall_legacy); ret = sbi_ecall_register_extension(&ecall_legacy);

View File

@@ -14,6 +14,7 @@
#include <sbi/sbi_error.h> #include <sbi/sbi_error.h>
#include <sbi/sbi_hart.h> #include <sbi/sbi_hart.h>
#include <sbi/sbi_ipi.h> #include <sbi/sbi_ipi.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_timer.h> #include <sbi/sbi_timer.h>
#include <sbi/sbi_tlb.h> #include <sbi/sbi_tlb.h>
@@ -127,3 +128,62 @@ struct sbi_ecall_extension ecall_ipi = {
.extid_end = SBI_EXT_IPI, .extid_end = SBI_EXT_IPI,
.handle = sbi_ecall_ipi_handler, .handle = sbi_ecall_ipi_handler,
}; };
static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid,
unsigned long *args, unsigned long *out_val,
struct sbi_trap_info *out_trap)
{
if (funcid == SBI_EXT_SRST_RESET) {
if ((((u32)-1U) <= ((u64)args[0])) ||
(((u32)-1U) <= ((u64)args[1])))
return SBI_EINVAL;
switch (args[0]) {
case SBI_SRST_RESET_TYPE_SHUTDOWN:
case SBI_SRST_RESET_TYPE_COLD_REBOOT:
case SBI_SRST_RESET_TYPE_WARM_REBOOT:
break;
default:
return SBI_ENOTSUPP;
}
switch (args[1]) {
case SBI_SRST_RESET_REASON_NONE:
case SBI_SRST_RESET_REASON_SYSFAIL:
break;
default:
return SBI_ENOTSUPP;
}
if (sbi_system_reset_supported(args[0], args[1]))
sbi_system_reset(args[0], args[1]);
}
return SBI_ENOTSUPP;
}
static int sbi_ecall_srst_probe(unsigned long extid, unsigned long *out_val)
{
u32 type, count = 0;
/*
* At least one standard reset types should be supported by
* the platform for SBI SRST extension to be usable.
*/
for (type = 0; type <= SBI_SRST_RESET_TYPE_LAST; type++) {
if (sbi_system_reset_supported(type,
SBI_SRST_RESET_REASON_NONE))
count++;
}
*out_val = (count) ? 1 : 0;
return 0;
}
struct sbi_ecall_extension ecall_srst = {
.extid_start = SBI_EXT_SRST,
.extid_end = SBI_EXT_SRST,
.handle = sbi_ecall_srst_handler,
.probe = sbi_ecall_srst_probe,
};