aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2016-03-01 16:43:59 -0800
committerAndrew Waterman <waterman@cs.berkeley.edu>2016-03-01 16:46:08 -0800
commit5e29b5ccff5958ce4e8ddfd9feefdb6d562843f9 (patch)
tree32d1708f7fab5c2d3c592600cc8eddc9a2ca3920
parentdea1fa15f2712b7f6540c41832322c813591315f (diff)
downloadriscv-pk-5e29b5ccff5958ce4e8ddfd9feefdb6d562843f9.zip
riscv-pk-5e29b5ccff5958ce4e8ddfd9feefdb6d562843f9.tar.gz
riscv-pk-5e29b5ccff5958ce4e8ddfd9feefdb6d562843f9.tar.bz2
Use RV configuration string instead of device tree
-rw-r--r--pk/configstring.c199
-rw-r--r--pk/devicetree.c96
-rw-r--r--pk/devicetree.h37
-rw-r--r--pk/minit.c3
-rw-r--r--pk/pk.h1
-rw-r--r--pk/pk.mk.in2
6 files changed, 202 insertions, 136 deletions
diff --git a/pk/configstring.c b/pk/configstring.c
new file mode 100644
index 0000000..b7d443f
--- /dev/null
+++ b/pk/configstring.c
@@ -0,0 +1,199 @@
+#include "encoding.h"
+#include "mtrap.h"
+
+static const char* skip_whitespace(const char* str)
+{
+ while (*str && *str <= ' ')
+ str++;
+ return str;
+}
+
+static const char* skip_string(const char* str)
+{
+ while (*str && *str++ != '"')
+ ;
+ return str;
+}
+
+static int is_hex(char ch)
+{
+ return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F');
+}
+
+static int parse_hex(char ch)
+{
+ return (ch >= '0' && ch <= '9') ? ch - '0' :
+ (ch >= 'a' && ch <= 'f') ? ch - 'a' + 10 :
+ ch - 'A' + 10;
+}
+
+static const char* skip_key(const char* str)
+{
+ while (*str >= 35 && *str <= 122 && *str != ';')
+ str++;
+ return str;
+}
+
+typedef struct {
+ const char* start;
+ const char* end;
+} query_result;
+
+static query_result query_config_string(const char* str, const char* k)
+{
+ size_t ksize = 0;
+ while (k[ksize] && k[ksize] != '{')
+ ksize++;
+ int last = !k[ksize];
+
+ query_result res = {0, 0};
+ while (1) {
+ const char* key_start = str = skip_whitespace(str);
+ const char* key_end = str = skip_key(str);
+ int match = (key_end - key_start) == ksize;
+ if (match)
+ for (size_t i = 0; i < ksize; i++)
+ if (key_start[i] != k[i])
+ match = 0;
+ const char* value_start = str = skip_whitespace(str);
+ while (*str != ';') {
+ if (!*str) {
+ return res;
+ } else if (*str == '"') {
+ str = skip_string(str+1);
+ } else if (*str == '{') {
+ const char* search_key = match && !last ? k + ksize + 1 : "";
+ query_result inner_res = query_config_string(str + 1, search_key);
+ if (inner_res.start)
+ return inner_res;
+ str = inner_res.end + 1;
+ } else {
+ str = skip_key(str);
+ }
+ str = skip_whitespace(str);
+ }
+ res.end = str;
+ if (match && last) {
+ res.start = value_start;
+ return res;
+ }
+ str = skip_whitespace(str+1);
+ if (*str == '}') {
+ res.end = str;
+ return res;
+ }
+ }
+}
+
+static void parse_string(query_result r, char* buf)
+{
+ if (r.start < r.end) {
+ if (*r.start == '"') {
+ for (const char* p = r.start + 1; p < r.end && *p != '"'; p++) {
+ char ch = p[0];
+ if (ch == '\\' && p[1] == 'x' && is_hex(p[2])) {
+ ch = parse_hex(p[2]);
+ if (is_hex(p[3])) {
+ ch = (ch << 4) + parse_hex(p[3]);
+ p++;
+ }
+ p += 2;
+ }
+ *buf++ = ch;
+ }
+ } else {
+ for (const char* p = r.start; p < r.end && *p > ' '; p++)
+ *buf++ = *p;
+ }
+ }
+ *buf = 0;
+}
+
+#define get_string(name, search_res) \
+ char name[(search_res).end - (search_res).start + 1]; \
+ parse_string(search_res, name)
+
+static unsigned long __get_uint_hex(const char* s)
+{
+ unsigned long res = 0;
+ while (*s) {
+ if (is_hex(*s))
+ res = (res << 4) + parse_hex(*s);
+ else if (*s != '_')
+ break;
+ s++;
+ }
+ return res;
+}
+
+static unsigned long __get_uint_dec(const char* s)
+{
+ unsigned long res = 0;
+ while (*s) {
+ if (*s >= '0' && *s <= '9')
+ res = res * 10 + (*s - '0');
+ else
+ break;
+ s++;
+ }
+ return res;
+}
+
+static unsigned long __get_uint(const char* s)
+{
+ if (s[0] == '0' && s[1] == 'x')
+ return __get_uint_hex(s+2);
+ return __get_uint_dec(s);
+}
+
+static unsigned long get_uint(query_result res)
+{
+ get_string(s, res);
+ return __get_uint(s);
+}
+
+static long get_sint(query_result res)
+{
+ get_string(s, res);
+ if (s[0] == '-')
+ return -__get_uint(s+1);
+ return __get_uint(s);
+}
+
+static void query_mem(const char* config_string)
+{
+ query_result res = query_config_string(config_string, "ram{0{addr");
+ kassert(res.start);
+ uintptr_t base = get_uint(res);
+ res = query_config_string(config_string, "ram{0{size");
+ mem_size = get_uint(res);
+ debug_printk("at %p, found %d MiB of memory\n", base, (int)(mem_size >> 20));
+}
+
+static void query_harts(const char* config_string)
+{
+ for (int core = 0, hart; ; core++) {
+ for (hart = 0; ; hart++) {
+ char buf[32];
+ snprintf(buf, sizeof buf, "core{%d{%d{addr", core, hart);
+ query_result res = query_config_string(config_string, buf);
+ if (!res.start)
+ break;
+ uintptr_t* base = (uintptr_t*)get_uint(res);
+ uintptr_t hart_id = base[CSR_MHARTID];
+ hls_init(hart_id, base);
+ debug_printk("at %p, found hart %ld\n", base, hart_id);
+ kassert(num_harts++ == hart_id);
+ }
+ if (!hart)
+ break;
+ }
+}
+
+void parse_config_string()
+{
+ const char* s = (const char*)read_csr(mcfgaddr);
+ debug_printk("%s\n", s);
+ query_mem(s);
+ query_harts(s);
+}
diff --git a/pk/devicetree.c b/pk/devicetree.c
deleted file mode 100644
index 2c236a5..0000000
--- a/pk/devicetree.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "devicetree.h"
-#include "encoding.h"
-#include "mtrap.h"
-#include <stdbool.h>
-
-#define ntohl(x) __builtin_bswap32(x)
-
-static uintptr_t max_hart_id;
-
-static uint64_t fdt_read_uint64(uint32_t* addr) {
- return ((uint64_t)ntohl(addr[0]) << 32) | ntohl(addr[1]);
-}
-
-static void fdt_handle_cpu(const char* isa, uint32_t* reg_addr, uint32_t reg_len)
-{
- int xlen = sizeof(long) * 8;
- kassert(reg_len == 8);
- kassert(isa && isa[0]=='r' && isa[1]=='v' && isa[2]=='0'+(xlen/10));
-
- uintptr_t* base_addr = (uintptr_t*)(uintptr_t)fdt_read_uint64(reg_addr);
- debug_printk("at %p, ", base_addr);
- uintptr_t hart_id = *(uintptr_t*)(base_addr + CSR_MHARTID);
- kassert(hart_id < MAX_HARTS);
- debug_printk("found hart %ld\n", hart_id);
- hls_init(hart_id, base_addr);
- num_harts++;
- max_hart_id = MAX(max_hart_id, hart_id);
-}
-
-static void fdt_handle_mem(uint32_t* reg_addr, uint32_t reg_len)
-{
- kassert(reg_len == 16);
- uint64_t base = fdt_read_uint64(reg_addr);
- uint64_t size = fdt_read_uint64(reg_addr+2);
- debug_printk("at %p, found %d MiB of memory\n", base, (int)(size >> 20));
- kassert(base == 0);
- mem_size = size;
-}
-
-// This code makes the following assumptions about FDTs:
-// - They are trusted and don't need to be sanitized
-// - All addresses and sizes are 64 bits (we don't parse #address-cells etc)
-
-static uint32_t* parse_node(uint32_t* token, char* strings)
-{
- const char* nodename = (const char*)token, *s, *dev_type = 0, *isa = 0;
- uint32_t reg_len = 0, *reg_addr = 0;
- token = (uint32_t*)nodename + strlen(nodename)/4+1;
-
- while (1) switch (ntohl(*token)) {
- case FDT_PROP: {
- token++;
- uint32_t len = ntohl(*token++);
- const char* name = strings + ntohl(*token++);
- if (strcmp(name, "device_type") == 0) {
- dev_type = (char*)token;
- } else if (strcmp(name, "isa") == 0) {
- isa = (char*)token;
- } else if (strcmp(name, "reg") == 0) {
- reg_len = len;
- reg_addr = token;
- }
- token += (len+3)/4;
- continue;
- }
- case FDT_BEGIN_NODE:
- token = parse_node(token+1, strings);
- continue;
- case FDT_END_NODE:
- goto out;
- case FDT_NOP:
- continue;
- default:
- kassert(0);
- }
-
-out:
- if (dev_type && strcmp(dev_type, "cpu") == 0)
- fdt_handle_cpu(isa, reg_addr, reg_len);
- else if (dev_type && strcmp(dev_type, "memory") == 0)
- fdt_handle_mem(reg_addr, reg_len);
-
- return token+1;
-}
-
-void parse_device_tree()
-{
- struct fdt_header* hdr = (struct fdt_header*)read_csr(mcfgaddr);
- debug_printk("reading device tree at %p\n", hdr);
- kassert(ntohl(hdr->magic) == FDT_MAGIC);
- char* strings = (char*)hdr + ntohl(hdr->off_dt_strings);
- uint32_t* root = (uint32_t*)((char*)hdr + ntohl(hdr->off_dt_struct));
- while (ntohl(*root++) != FDT_BEGIN_NODE);
- parse_node(root, strings);
- kassert(max_hart_id == num_harts-1);
-}
diff --git a/pk/devicetree.h b/pk/devicetree.h
deleted file mode 100644
index 1daab89..0000000
--- a/pk/devicetree.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// See LICENSE for license details.
-
-#ifndef _PK_DEVICETREE_H
-#define _PK_DEVICETREE_H
-
-#include <stdint.h>
-
-#define FDT_MAGIC 0xd00dfeedU
-#define FDT_VERSION 17
-#define FDT_COMP_VERSION 16
-#define FDT_BEGIN_NODE 1
-#define FDT_END_NODE 2
-#define FDT_PROP 3
-#define FDT_NOP 4
-#define FDT_END 9
-
-struct fdt_header {
- uint32_t magic;
- uint32_t totalsize;
- uint32_t off_dt_struct;
- uint32_t off_dt_strings;
- uint32_t off_rsvmap;
- uint32_t version;
- uint32_t last_comp_version;
- uint32_t boot_cpuid_phys;
- uint32_t size_dt_strings;
- uint32_t size_dt_struct;
-};
-
-struct fdt_reserve_entry {
- uint64_t address;
- uint64_t size;
-};
-
-void parse_device_tree();
-
-#endif
diff --git a/pk/minit.c b/pk/minit.c
index 4784e75..f899864 100644
--- a/pk/minit.c
+++ b/pk/minit.c
@@ -1,6 +1,5 @@
#include "vm.h"
#include "mtrap.h"
-#include "devicetree.h"
volatile uint32_t booted_harts_mask;
uintptr_t mem_size;
@@ -100,7 +99,7 @@ void init_first_hart()
hart_init();
memset(HLS(), 0, sizeof(*HLS()));
- parse_device_tree();
+ parse_config_string();
struct mainvars arg_buffer;
struct mainvars *args = parse_args(&arg_buffer);
diff --git a/pk/pk.h b/pk/pk.h
index 88c5881..98738bf 100644
--- a/pk/pk.h
+++ b/pk/pk.h
@@ -74,6 +74,7 @@ void handle_fault_store(trapframe_t*);
void prepare_supervisor_mode();
void boot_loader(struct mainvars*);
void run_loaded_program(struct mainvars*);
+void parse_config_string();
void boot_other_hart();
typedef struct {
diff --git a/pk/pk.mk.in b/pk/pk.mk.in
index 6a7830d..7ada789 100644
--- a/pk/pk.mk.in
+++ b/pk/pk.mk.in
@@ -25,7 +25,7 @@ pk_c_srcs = \
vm.c \
string.c \
logo.c \
- devicetree.c \
+ configstring.c \
pk_asm_srcs = \
mentry.S \