aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWesley W. Terpstra <wesley@sifive.com>2017-08-14 17:55:31 -0700
committerGitHub <noreply@github.com>2017-08-14 17:55:31 -0700
commit3f20915effa623e11b139ba431841c7af2689cdd (patch)
treeb70fd9c21448c077e6d521c8c2038445f0844640
parent2dcae927fd6cc4493de0f77434a7f191157ba8b7 (diff)
downloadriscv-pk-3f20915effa623e11b139ba431841c7af2689cdd.zip
riscv-pk-3f20915effa623e11b139ba431841c7af2689cdd.tar.gz
riscv-pk-3f20915effa623e11b139ba431841c7af2689cdd.tar.bz2
finisher: support terminating sifive devices simulation (#61)
-rw-r--r--machine/finisher.c58
-rw-r--r--machine/finisher.h13
-rw-r--r--machine/machine.mk.in2
-rw-r--r--machine/minit.c4
-rw-r--r--machine/mtrap.c7
-rw-r--r--machine/mtrap.h4
6 files changed, 84 insertions, 4 deletions
diff --git a/machine/finisher.c b/machine/finisher.c
new file mode 100644
index 0000000..d113096
--- /dev/null
+++ b/machine/finisher.c
@@ -0,0 +1,58 @@
+#include <string.h>
+#include "finisher.h"
+#include "fdt.h"
+
+volatile uint32_t* finisher;
+
+void finisher_exit(uint16_t code)
+{
+ if (!finisher) return;
+ if (code == 0) {
+ *finisher = FINISHER_PASS;
+ } else {
+ *finisher = code << 16 | FINISHER_FAIL;
+ }
+}
+
+struct finisher_scan
+{
+ int compat;
+ uint64_t reg;
+};
+
+static void finisher_open(const struct fdt_scan_node *node, void *extra)
+{
+ struct finisher_scan *scan = (struct finisher_scan *)extra;
+ memset(scan, 0, sizeof(*scan));
+}
+
+static void finisher_prop(const struct fdt_scan_prop *prop, void *extra)
+{
+ struct finisher_scan *scan = (struct finisher_scan *)extra;
+ if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "sifive,test0")) {
+ scan->compat = 1;
+ } else if (!strcmp(prop->name, "reg")) {
+ fdt_get_address(prop->node->parent, prop->value, &scan->reg);
+ }
+}
+
+static void finisher_done(const struct fdt_scan_node *node, void *extra)
+{
+ struct finisher_scan *scan = (struct finisher_scan *)extra;
+ if (!scan->compat || !scan->reg || finisher) return;
+ finisher = (uint32_t*)(uintptr_t)scan->reg;
+}
+
+void query_finisher(uintptr_t fdt)
+{
+ struct fdt_cb cb;
+ struct finisher_scan scan;
+
+ memset(&cb, 0, sizeof(cb));
+ cb.open = finisher_open;
+ cb.prop = finisher_prop;
+ cb.done = finisher_done;
+ cb.extra = &scan;
+
+ fdt_scan(fdt, &cb);
+}
diff --git a/machine/finisher.h b/machine/finisher.h
new file mode 100644
index 0000000..60d10b4
--- /dev/null
+++ b/machine/finisher.h
@@ -0,0 +1,13 @@
+#ifndef _RISCV_FINISHER_H
+#define _RISCV_FINISHER_H
+
+#include <stdint.h>
+
+#define FINISHER_REG_FINISH 0
+#define FINISHER_FAIL 0x3333
+#define FINISHER_PASS 0x5555
+
+void finisher_exit(uint16_t code);
+void query_finisher(uintptr_t fdt);
+
+#endif
diff --git a/machine/machine.mk.in b/machine/machine.mk.in
index 76e02d9..59d0eb4 100644
--- a/machine/machine.mk.in
+++ b/machine/machine.mk.in
@@ -13,6 +13,7 @@ machine_hdrs = \
mcall.h \
mtrap.h \
uart.h \
+ finisher.h \
unprivileged_memory.h \
vm.h \
@@ -26,6 +27,7 @@ machine_c_srcs = \
fp_emulation.c \
fp_ldst.c \
uart.c \
+ finisher.c \
misaligned_ldst.c \
machine_asm_srcs = \
diff --git a/machine/minit.c b/machine/minit.c
index 0fb5f21..187bef7 100644
--- a/machine/minit.c
+++ b/machine/minit.c
@@ -4,6 +4,7 @@
#include "fp_emulation.h"
#include "fdt.h"
#include "uart.h"
+#include "finisher.h"
#include "platform_interface.h"
#include <string.h>
#include <limits.h>
@@ -136,6 +137,9 @@ void init_first_hart(uintptr_t hartid, uintptr_t dtb)
// Confirm console as early as possible
query_uart(dtb);
+ // Find the power button early as well so die() works
+ query_finisher(dtb);
+
query_mem(dtb);
query_harts(dtb);
query_clint(dtb);
diff --git a/machine/mtrap.c b/machine/mtrap.c
index a72b373..e5faae3 100644
--- a/machine/mtrap.c
+++ b/machine/mtrap.c
@@ -5,6 +5,7 @@
#include "bits.h"
#include "vm.h"
#include "uart.h"
+#include "finisher.h"
#include "fdt.h"
#include "unprivileged_memory.h"
#include "platform_interface.h"
@@ -27,8 +28,10 @@ static uintptr_t mcall_console_putchar(uint8_t ch)
return 0;
}
-void poweroff()
+void poweroff(uint16_t code)
{
+ printm("Power off\n");
+ finisher_exit(code);
if (platform__use_htif()) {
htif_poweroff();
} else {
@@ -84,7 +87,7 @@ static uintptr_t mcall_clear_ipi()
static uintptr_t mcall_shutdown()
{
- poweroff();
+ poweroff(0);
}
static uintptr_t mcall_set_timer(uint64_t when)
diff --git a/machine/mtrap.h b/machine/mtrap.h
index a15b265..eafdb14 100644
--- a/machine/mtrap.h
+++ b/machine/mtrap.h
@@ -56,12 +56,12 @@ typedef struct {
hls_t* hls_init(uintptr_t hart_id);
void parse_config_string();
-void poweroff(void) __attribute((noreturn));
+void poweroff(uint16_t code) __attribute((noreturn));
void printm(const char* s, ...);
void vprintm(const char *s, va_list args);
void putstring(const char* s);
#define assert(x) ({ if (!(x)) die("assertion failed: %s", #x); })
-#define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(); })
+#define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(-1); })
void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1)
__attribute__((noreturn));