aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Horne <mhorne@FreeBSD.org>2021-01-27 21:27:15 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2021-02-04 16:17:31 +0000
commitb680dba47653451aeda9292dd6dcda2f79b905e7 (patch)
treeb7c0526f56f17207e4d6d22d9e232abbcc367b6d
parent620455079f47a9d7361b46b965abf273ac6787de (diff)
downloadsrc-b680dba47653451aeda9292dd6dcda2f79b905e7.tar.gz
src-b680dba47653451aeda9292dd6dcda2f79b905e7.zip
riscv: add SBI system reset extension
(cherry picked from commit 9bae4ce661c59be88fec89b2531148e36dd1a23e) (cherry picked from commit a6405133b7e14929f8e8e61cf30d7152b1410e59)
-rw-r--r--sys/riscv/include/sbi.h28
-rw-r--r--sys/riscv/riscv/sbi.c34
-rw-r--r--sys/riscv/riscv/vm_machdep.c2
3 files changed, 48 insertions, 16 deletions
diff --git a/sys/riscv/include/sbi.h b/sys/riscv/include/sbi.h
index 50cacb3e6e5a..9d3f4076dcb2 100644
--- a/sys/riscv/include/sbi.h
+++ b/sys/riscv/include/sbi.h
@@ -99,6 +99,15 @@
#define SBI_HSM_STATUS_START_PENDING 2
#define SBI_HSM_STATUS_STOP_PENDING 3
+/* System Reset (SRST) Extension */
+#define SBI_EXT_ID_SRST 0x53525354
+#define SBI_SRST_SYSTEM_RESET 0
+#define SBI_SRST_TYPE_SHUTDOWN 0
+#define SBI_SRST_TYPE_COLD_REBOOT 1
+#define SBI_SRST_TYPE_WARM_REBOOT 2
+#define SBI_SRST_REASON_NONE 0
+#define SBI_SRST_REASON_SYSTEM_FAILURE 1
+
/* Legacy Extensions */
#define SBI_SET_TIMER 0
#define SBI_CONSOLE_PUTCHAR 1
@@ -199,6 +208,18 @@ void sbi_hsm_hart_stop(void);
*/
int sbi_hsm_hart_status(u_long hart);
+/* System Reset extension functions. */
+
+/*
+ * Reset the system based on the following 'type' and 'reason' chosen from:
+ * - SBI_SRST_TYPE_SHUTDOWN
+ * - SBI_SRST_TYPE_COLD_REBOOT
+ * - SBI_SRST_TYPE_WARM_REBOOT
+ * - SBI_SRST_REASON_NONE
+ * - SBI_SRST_REASON_SYSTEM_FAILURE
+ */
+void sbi_system_reset(u_long reset_type, u_long reset_reason);
+
/* Legacy extension functions. */
static __inline void
sbi_console_putchar(int ch)
@@ -218,13 +239,6 @@ sbi_console_getchar(void)
return (SBI_CALL0(SBI_CONSOLE_GETCHAR, 0).error);
}
-static __inline void
-sbi_shutdown(void)
-{
-
- (void)SBI_CALL0(SBI_SHUTDOWN, 0);
-}
-
void sbi_print_version(void);
void sbi_init(void);
diff --git a/sys/riscv/riscv/sbi.c b/sys/riscv/riscv/sbi.c
index d529d2d08351..6897fce9cad3 100644
--- a/sys/riscv/riscv/sbi.c
+++ b/sys/riscv/riscv/sbi.c
@@ -49,6 +49,7 @@ u_long sbi_impl_version;
static bool has_time_extension = false;
static bool has_ipi_extension = false;
static bool has_rfnc_extension = false;
+static bool has_srst_extension = false;
static struct sbi_ret
sbi_get_spec_version(void)
@@ -90,7 +91,18 @@ static void
sbi_shutdown_final(void *dummy __unused, int howto)
{
if ((howto & RB_POWEROFF) != 0)
- sbi_shutdown();
+ sbi_system_reset(SBI_SRST_TYPE_SHUTDOWN, SBI_SRST_REASON_NONE);
+}
+
+void
+sbi_system_reset(u_long reset_type, u_long reset_reason)
+{
+ /* Use the SRST extension, if available. */
+ if (has_srst_extension) {
+ (void)SBI_CALL2(SBI_EXT_ID_SRST, SBI_SRST_SYSTEM_RESET,
+ reset_type, reset_reason);
+ }
+ (void)SBI_CALL0(SBI_SHUTDOWN, 0);
}
void
@@ -111,10 +123,12 @@ sbi_print_version(void)
printf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version);
break;
case (SBI_IMPL_ID_XVISOR):
- printf("SBI: eXtensible Versatile hypervISOR %lu\n", sbi_impl_version);
+ printf("SBI: eXtensible Versatile hypervISOR %lu\n",
+ sbi_impl_version);
break;
case (SBI_IMPL_ID_KVM):
- printf("SBI: Kernel-based Virtual Machine %lu\n", sbi_impl_version);
+ printf("SBI: Kernel-based Virtual Machine %lu\n",
+ sbi_impl_version);
break;
case (SBI_IMPL_ID_RUSTSBI):
printf("SBI: RustSBI %lu\n", sbi_impl_version);
@@ -206,8 +220,9 @@ sbi_remote_sfence_vma_asid(const u_long *hart_mask, u_long start, u_long size,
/* Use the RFENCE legacy replacement extension, if available. */
if (has_rfnc_extension) {
- ret = SBI_CALL5(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA_ASID,
- *hart_mask, 0, start, size, asid);
+ ret = SBI_CALL5(SBI_EXT_ID_RFNC,
+ SBI_RFNC_REMOTE_SFENCE_VMA_ASID, *hart_mask, 0, start,
+ size, asid);
MPASS(ret.error == SBI_SUCCESS);
} else {
(void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0,
@@ -220,7 +235,8 @@ sbi_hsm_hart_start(u_long hart, u_long start_addr, u_long priv)
{
struct sbi_ret ret;
- ret = SBI_CALL3(SBI_EXT_ID_HSM, SBI_HSM_HART_START, hart, start_addr, priv);
+ ret = SBI_CALL3(SBI_EXT_ID_HSM, SBI_HSM_HART_START, hart, start_addr,
+ priv);
return (ret.error != 0 ? (int)ret.error : 0);
}
@@ -273,6 +289,8 @@ sbi_init(void)
has_ipi_extension = true;
if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0)
has_rfnc_extension = true;
+ if (sbi_probe_extension(SBI_EXT_ID_SRST) != 0)
+ has_srst_extension = true;
/*
* Probe for legacy extensions. We still rely on many of them to be
@@ -295,8 +313,8 @@ sbi_init(void)
KASSERT(has_rfnc_extension ||
sbi_probe_extension(SBI_REMOTE_SFENCE_VMA_ASID) != 0,
("SBI doesn't implement sbi_remote_sfence_vma_asid()"));
- KASSERT(sbi_probe_extension(SBI_SHUTDOWN) != 0,
- ("SBI doesn't implement sbi_shutdown()"));
+ KASSERT(has_srst_extension || sbi_probe_extension(SBI_SHUTDOWN) != 0,
+ ("SBI doesn't implement a shutdown or reset extension"));
}
static void
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
index f38f1c04caa8..094662413f4e 100644
--- a/sys/riscv/riscv/vm_machdep.c
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -110,7 +110,7 @@ void
cpu_reset(void)
{
- sbi_shutdown();
+ sbi_system_reset(SBI_SRST_TYPE_COLD_REBOOT, SBI_SRST_REASON_NONE);
while(1);
}