From 5e29b5ccff5958ce4e8ddfd9feefdb6d562843f9 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 1 Mar 2016 16:43:59 -0800 Subject: Use RV configuration string instead of device tree --- pk/configstring.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ pk/devicetree.c | 96 -------------------------- pk/devicetree.h | 37 ---------- pk/minit.c | 3 +- pk/pk.h | 1 + pk/pk.mk.in | 2 +- 6 files changed, 202 insertions(+), 136 deletions(-) create mode 100644 pk/configstring.c delete mode 100644 pk/devicetree.c delete mode 100644 pk/devicetree.h 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 - -#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 - -#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 \ -- cgit v1.1