aboutsummaryrefslogtreecommitdiff
path: root/pk/pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'pk/pk.c')
-rw-r--r--pk/pk.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/pk/pk.c b/pk/pk.c
new file mode 100644
index 0000000..cc2a761
--- /dev/null
+++ b/pk/pk.c
@@ -0,0 +1,99 @@
+#include "pk.h"
+#include "vm.h"
+#include "elf.h"
+
+void run_loaded_program(struct mainvars* args)
+{
+ if (current.is_supervisor)
+ panic("pk can't run kernel binaries; try using bbl instead");
+
+ uintptr_t kernel_stack_top = pk_vm_init();
+
+ extern char trap_entry;
+ write_csr(stvec, &trap_entry);
+ write_csr(sscratch, 0);
+
+ // enter supervisor mode
+ asm volatile("la t0, 1f; csrw mepc, t0; eret; 1:" ::: "t0");
+
+ // 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);
+ current.phdr = stack_top;
+
+ // copy argv to user stack
+ for (size_t i = 0; i < args->argc; i++) {
+ size_t len = strlen((char*)(uintptr_t)args->argv[i])+1;
+ stack_top -= len;
+ memcpy((void*)stack_top, (void*)(uintptr_t)args->argv[i], len);
+ args->argv[i] = stack_top;
+ }
+ stack_top &= -sizeof(void*);
+
+ struct {
+ long key;
+ long value;
+ } aux[] = {
+ {AT_ENTRY, current.entry},
+ {AT_PHNUM, current.phnum},
+ {AT_PHENT, current.phent},
+ {AT_PHDR, current.phdr},
+ {AT_PAGESZ, RISCV_PGSIZE},
+ {AT_SECURE, 0},
+ {AT_RANDOM, stack_top},
+ {AT_NULL, 0}
+ };
+
+ // place argc, argv, envp, auxp on stack
+ #define PUSH_ARG(type, value) do { \
+ *((type*)sp) = value; \
+ sp += sizeof(type); \
+ } while (0)
+
+ #define STACK_INIT(type) do { \
+ unsigned naux = sizeof(aux)/sizeof(aux[0]); \
+ stack_top -= (1 + args->argc + 1 + 1 + 2*naux) * sizeof(type); \
+ stack_top &= -16; \
+ long sp = stack_top; \
+ PUSH_ARG(type, args->argc); \
+ for (unsigned i = 0; i < args->argc; i++) \
+ PUSH_ARG(type, args->argv[i]); \
+ PUSH_ARG(type, 0); /* argv[argc] = NULL */ \
+ PUSH_ARG(type, 0); /* envp[0] = NULL */ \
+ for (unsigned i = 0; i < naux; i++) { \
+ PUSH_ARG(type, aux[i].key); \
+ PUSH_ARG(type, aux[i].value); \
+ } \
+ } while (0)
+
+ if (current.elf64)
+ STACK_INIT(uint64_t);
+ else
+ STACK_INIT(uint32_t);
+
+ if (current.t0) // start timer if so requested
+ current.t0 = rdcycle();
+
+ if (uarch_counters_enabled) { // start tracking the uarch counters if requested
+ size_t i = 0;
+ #define READ_CTR_INIT(name) do { \
+ while (i >= NUM_COUNTERS) ; \
+ long csr = read_csr(name); \
+ uarch_counters[i++] = csr; \
+ } while (0)
+ READ_CTR_INIT(cycle); READ_CTR_INIT(instret);
+ READ_CTR_INIT(uarch0); READ_CTR_INIT(uarch1); READ_CTR_INIT(uarch2);
+ READ_CTR_INIT(uarch3); READ_CTR_INIT(uarch4); READ_CTR_INIT(uarch5);
+ READ_CTR_INIT(uarch6); READ_CTR_INIT(uarch7); READ_CTR_INIT(uarch8);
+ READ_CTR_INIT(uarch9); READ_CTR_INIT(uarch10); READ_CTR_INIT(uarch11);
+ READ_CTR_INIT(uarch12); READ_CTR_INIT(uarch13); READ_CTR_INIT(uarch14);
+ READ_CTR_INIT(uarch15);
+ #undef READ_CTR_INIT
+ }
+
+ trapframe_t tf;
+ init_tf(&tf, current.entry, stack_top, current.elf64);
+ __clear_cache(0, 0);
+ write_csr(sscratch, kernel_stack_top);
+ start_user(&tf);
+}