summaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorPrashanth Mundkur2018-10-10 12:36:49 -0700
committerPrashanth Mundkur2018-10-23 15:32:15 -0700
commit5be50269f940be8cc155d30843abfcc657ced54c (patch)
tree9a71b4cf909812c493a5ee4a52c5a73497e90efe /riscv
parent1f0716a98c3758675ab18e76d69ffac1e8d6a694 (diff)
RISC-V: Allow the C platform to get the DTB from a file, so that OS boot is possible without linking to Spike.
When linked with Spike, ensure that the DTBs being used are identical.
Diffstat (limited to 'riscv')
-rw-r--r--riscv/riscv_sim.c122
1 files changed, 100 insertions, 22 deletions
diff --git a/riscv/riscv_sim.c b/riscv/riscv_sim.c
index 305c61f8..276c7b1b 100644
--- a/riscv/riscv_sim.c
+++ b/riscv/riscv_sim.c
@@ -5,6 +5,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <fcntl.h>
#include "elf.h"
@@ -14,6 +15,7 @@
#include "riscv_platform_impl.h"
#include "riscv_sail.h"
+//#define SPIKE 1
#ifdef SPIKE
#include "tv_spike_intf.h"
#else
@@ -40,12 +42,19 @@ struct tv_spike_t;
static bool do_dump_dts = false;
struct tv_spike_t *s = NULL;
char *term_log = NULL;
+char *dtb_file = NULL;
+unsigned char *dtb = NULL;
+size_t dtb_len = 0;
+
+unsigned char *spike_dtb = NULL;
+size_t spike_dtb_len = 0;
static struct option options[] = {
{"enable-dirty", no_argument, 0, 'd'},
{"enable-misaligned", no_argument, 0, 'm'},
{"mtval-has-illegal-inst-bits", no_argument, 0, 'i'},
{"dump-dts", no_argument, 0, 's'},
+ {"device-tree-blob", required_argument, 0, 'b'},
{"terminal-log", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
@@ -80,11 +89,41 @@ static void dump_dts(void)
exit(0);
}
+static void read_dtb(const char *path)
+{
+ int fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Unable to read DTB file %s: %s\n", path, strerror(errno));
+ exit(1);
+ }
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "Unable to stat DTB file %s: %s\n", path, strerror(errno));
+ exit(1);
+ }
+ char *m = (char *)mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (m == MAP_FAILED) {
+ fprintf(stderr, "Unable to map DTB file %s: %s\n", path, strerror(errno));
+ exit(1);
+ }
+ dtb = (unsigned char *)malloc(st.st_size);
+ if (dtb == NULL) {
+ fprintf(stderr, "Cannot allocate DTB from file %s!\n", path);
+ exit(1);
+ }
+ memcpy(dtb, m, st.st_size);
+ dtb_len = st.st_size;
+ munmap(m, st.st_size);
+ close(fd);
+
+ fprintf(stdout, "Read %ld bytes of DTB from %s.\n", dtb_len, path);
+}
+
char *process_args(int argc, char **argv)
{
int c, idx = 1;
while(true) {
- c = getopt_long(argc, argv, "dmst:v:h", options, &idx);
+ c = getopt_long(argc, argv, "dmsb:t:v:h", options, &idx);
if (c == -1) break;
switch (c) {
case 'd':
@@ -93,9 +132,14 @@ char *process_args(int argc, char **argv)
case 'm':
rv_enable_misaligned = true;
break;
+ case 'i':
+ rv_mtval_has_illegal_inst_bits = true;
case 's':
do_dump_dts = true;
break;
+ case 'b':
+ dtb_file = strdup(optarg);
+ break;
case 't':
term_log = strdup(optarg);
break;
@@ -110,7 +154,10 @@ char *process_args(int argc, char **argv)
if (do_dump_dts) dump_dts();
if (idx >= argc) print_usage(argv[0], 0);
if (term_log == NULL) term_log = strdup("term.log");
- return argv[idx];
+ if (dtb_file) read_dtb(dtb_file);
+
+ fprintf(stdout, "Running file %s.\n", argv[optind]);
+ return argv[optind];
}
uint64_t load_sail(char *f)
@@ -135,18 +182,43 @@ uint64_t load_sail(char *f)
void init_spike(const char *f, uint64_t entry)
{
#ifdef SPIKE
+ /* The initialization order below matters. */
s = tv_init("RV64IMAC", 1);
tv_set_verbose(s, 1);
tv_set_dtb_in_rom(s, 1);
tv_load_elf(s, f);
tv_reset(s);
+
/* sync the insns per tick */
rv_insns_per_tick = tv_get_insns_per_tick(s);
+
+ /* get DTB from spike */
+ tv_get_dtb(s, NULL, &spike_dtb_len);
+ if (spike_dtb_len > 0) {
+ spike_dtb = (unsigned char *)malloc(spike_dtb_len + 1);
+ dtb[spike_dtb_len] = '\0';
+ if (!tv_get_dtb(s, spike_dtb, &spike_dtb_len)) {
+ fprintf(stderr, "Got %ld bytes of dtb at %p\n", spike_dtb_len, spike_dtb);
+ } else {
+ fprintf(stderr, "Error getting DTB from Spike.\n");
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "No DTB available from Spike.\n");
+ }
#else
s = NULL;
#endif
}
+void tick_spike()
+{
+#ifdef SPIKE
+ tv_tick_clock(s);
+ tv_step_io(s);
+#endif
+}
+
void init_sail_reset_vector(uint64_t entry)
{
#define RST_VEC_SIZE 8
@@ -167,25 +239,33 @@ void init_sail_reset_vector(uint64_t entry)
uint64_t addr = rv_rom_base;
for (int i = 0; i < sizeof(reset_vec); i++)
write_mem(addr++, (uint64_t)((char *)reset_vec)[i]);
+
+ if (dtb && dtb_len) {
+ for (size_t i = 0; i < dtb_len; i++)
+ write_mem(addr++, dtb[i]);
+ }
+
#ifdef SPIKE
- unsigned char *dtb = NULL;
- size_t dtb_len = 0;
- tv_get_dtb(s, NULL, &dtb_len);
- if (dtb_len > 0) {
- dtb = (unsigned char *)malloc(dtb_len + 1);
- dtb[dtb_len] = '\0';
- if (!tv_get_dtb(s, dtb, &dtb_len)) {
- fprintf(stderr, "Got %ld bytes of dtb at %p\n", dtb_len, dtb);
+ if (dtb && dtb_len) {
+ // Ensure that Spike's DTB matches the one provided.
+ bool matched = dtb_len == spike_dtb_len;
+ if (matched) {
for (size_t i = 0; i < dtb_len; i++)
- write_mem(addr++, dtb[i]);
- } else {
- fprintf(stderr, "Error getting DTB!\n");
+ matched = matched && (dtb[i] == spike_dtb[i]);
+ }
+ if (!matched) {
+ fprintf(stderr, "Provided DTB does not match Spike's!\n");
exit(1);
}
+ } else {
+ if (spike_dtb_len > 0) {
+ // Use the DTB from Spike.
+ for (size_t i = 0; i < spike_dtb_len; i++)
+ write_mem(addr++, spike_dtb[i]);
+ } else {
+ fprintf(stderr, "Running without rom device tree.\n");
+ }
}
-#else
- fprintf(stderr, "Running without rom device tree.\n");
- /* TODO: write DTB */
#endif
/* zero-fill to page boundary */
@@ -353,10 +433,8 @@ void run_sail(void)
insn_cnt = 0;
ztick_clock(UNIT);
ztick_platform(UNIT);
-#ifdef SPIKE
- tv_tick_clock(s);
- tv_step_io(s);
-#endif
+
+ tick_spike();
}
}
@@ -376,16 +454,16 @@ void init_logs()
#ifdef SPIKE
// The Spike interface uses stdout for terminal output, and stderr for logs.
// Do the same here.
- int logfd;
if (dup2(1, 2) < 0) {
fprintf(stderr, "Unable to dup 1 -> 2: %s\n", strerror(errno));
exit(1);
}
+#endif
+
if ((term_fd = open(term_log, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR)) < 0) {
fprintf(stderr, "Cannot create terminal log '%s': %s\n", term_log, strerror(errno));
exit(1);
}
-#endif
}
int main(int argc, char **argv)