diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:58:17 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:58:17 -0800 |
commit | b94c7a4b07f96f24ae7411780abf874416549f7b (patch) | |
tree | b94ca015e49392f52e5abf1209ee184fcf874db4 /pk/pk.c | |
parent | f5a96732cb81571a3ba6b081b8556187d564f678 (diff) | |
download | riscv-pk-b94c7a4b07f96f24ae7411780abf874416549f7b.zip riscv-pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.gz riscv-pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.bz2 |
Refactor pk, bbl, machine into separate libraries
Yuck.
Diffstat (limited to 'pk/pk.c')
-rw-r--r-- | pk/pk.c | 95 |
1 files changed, 82 insertions, 13 deletions
@@ -1,24 +1,66 @@ #include "pk.h" +#include "mmap.h" #include "boot.h" -#include "vm.h" #include "elf.h" +#include "mtrap.h" +#include "frontend.h" -void run_loaded_program(size_t argc, char** argv) +elf_info current; + +int uarch_counters_enabled; +long uarch_counters[NUM_COUNTERS]; +char* uarch_counter_names[NUM_COUNTERS]; + +static void handle_option(const char* s) { - if (current.is_supervisor) - panic("pk can't run kernel binaries; try using bbl instead"); + switch (s[1]) + { + case 's': // print cycle count upon termination + current.t0 = 1; + break; - uintptr_t kernel_stack_top = pk_vm_init(); + case 'c': // print uarch counters upon termination + // If your HW doesn't support uarch counters, then don't use this flag! + uarch_counters_enabled = 1; + break; - extern char trap_entry; - write_csr(stvec, &trap_entry); - write_csr(sscratch, 0); - clear_csr(sie, SIP_STIP | SIP_SSIP); + default: + panic("unrecognized option: `%c'", s[1]); + break; + } +} - // enter supervisor mode - prepare_supervisor_mode(); - asm volatile("la t0, 1f; csrw mepc, t0; eret; 1:" ::: "t0"); +#define MAX_ARGS 64 +typedef union { + uint64_t buf[MAX_ARGS]; + char* argv[MAX_ARGS]; +} arg_buf; + +static size_t parse_args(arg_buf* args) +{ + long r = frontend_syscall(SYS_getmainvars, (uintptr_t)args, sizeof(*args), 0, 0, 0, 0, 0); + kassert(r == 0); + uint64_t* pk_argv = &args->buf[1]; + // pk_argv[0] is the proxy kernel itself. skip it and any flags. + size_t pk_argc = args->buf[0], arg = 1; + for ( ; arg < pk_argc && *(char*)(uintptr_t)pk_argv[arg] == '-'; arg++) + handle_option((const char*)(uintptr_t)pk_argv[arg]); + + for (size_t i = 0; arg + i < pk_argc; i++) + args->argv[i] = (char*)(uintptr_t)pk_argv[arg + i]; + return pk_argc - arg; +} + +static void init_tf(trapframe_t* tf, long pc, long sp) +{ + memset(tf, 0, sizeof(*tf)); + tf->status = (read_csr(sstatus) &~ SSTATUS_SPP &~ SSTATUS_SIE) | SSTATUS_SPIE; + tf->gpr[2] = sp; + tf->epc = pc; +} +static void run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top) +{ // copy phdrs to user stack size_t stack_top = current.stack_top - current.phdr_size; memcpy((void*)stack_top, (void*)current.phdr, current.phdr_size); @@ -94,10 +136,37 @@ void run_loaded_program(size_t argc, char** argv) trapframe_t tf; init_tf(&tf, current.entry, stack_top); __clear_cache(0, 0); - write_csr(sscratch, kernel_stack_top); + write_csr(sscratch, kstack_top); start_user(&tf); } +static void rest_of_boot_loader(uintptr_t kstack_top) +{ + arg_buf args; + size_t argc = parse_args(&args); + if (!argc) + panic("tell me what ELF to load!"); + + // load program named by argv[0] + long phdrs[128]; + current.phdr = (uintptr_t)phdrs; + current.phdr_size = sizeof(phdrs); + load_elf(args.argv[0], ¤t); + + run_loaded_program(argc, args.argv, kstack_top); +} + +void boot_loader() +{ + extern char trap_entry; + write_csr(stvec, &trap_entry); + write_csr(sscratch, 0); + write_csr(sie, 0); + + file_init(); + enter_supervisor_mode(rest_of_boot_loader, pk_vm_init()); +} + void boot_other_hart() { // stall all harts besides hart 0 |