aboutsummaryrefslogtreecommitdiff
path: root/pk/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'pk/init.c')
-rw-r--r--pk/init.c220
1 files changed, 64 insertions, 156 deletions
diff --git a/pk/init.c b/pk/init.c
index 6ee4154..48667c3 100644
--- a/pk/init.c
+++ b/pk/init.c
@@ -3,189 +3,97 @@
#include "pcr.h"
#include "pk.h"
#include "file.h"
+#include "vm.h"
#include "frontend.h"
-#include <stdarg.h>
+#include "elf.h"
#include <stdint.h>
-#include <stdbool.h>
#include <string.h>
-static void vsprintk(char* out, const char* s, va_list vl)
-{
- bool format = false;
- bool longarg = false;
- for( ; *s; s++)
- {
- if(format)
- {
- switch(*s)
- {
- case 'l':
- longarg = true;
- break;
- case 'x':
- {
- long n = longarg ? va_arg(vl,long) : va_arg(vl,int);
- for(int i = 2*(longarg ? sizeof(long) : sizeof(int))-1; i >= 0; i--)
- {
- int d = (n >> (4*i)) & 0xF;
- *out++ = (d < 10 ? '0'+d : 'a'+d-10);
- }
- longarg = false;
- format = false;
- break;
- }
- case 'd':
- {
- long n = longarg ? va_arg(vl,long) : va_arg(vl,int);
- if(n < 0)
- {
- n = -n;
- *out++ = '-';
- }
- long digits = 1;
- for(long nn = n ; nn /= 10; digits++);
- for(int i = digits-1; i >= 0; i--)
- {
- out[i] = '0' + n%10;
- n /= 10;
- }
- out += digits;
- longarg = false;
- format = false;
- break;
- }
- case 's':
- {
- const char* s2 = va_arg(vl,const char*);
- while(*s2)
- *out++ = *s2++;
- longarg = false;
- format = false;
- break;
- }
- case 'c':
- {
- *out++ = (char)va_arg(vl,int);
- longarg = false;
- format = false;
- break;
- }
- default:
- panic("bad fmt");
- }
- }
- else if(*s == '%')
- format = true;
- else
- *out++ = *s;
- }
- *out++ = '\0';
-}
-
-void printk(const char* s, ...)
-{
- va_list vl;
- va_start(vl,s);
-
- char out[1024]; // XXX
- vsprintk(out,s,vl);
- file_write(stderr,out,strlen(out));
-
- va_end(vl);
-}
-
-void sprintk(char* out, const char* s, ...)
-{
- va_list vl;
- va_start(vl,s);
-
- vsprintk(out,s,vl);
-
- va_end(vl);
-}
-
-void dump_tf(trapframe_t* tf)
-{
- static const char* regnames[] = {
- "z ", "ra", "s0", "s1", "s2", "s3", "s4", "s5",
- "s6", "s7", "s8", "s9", "sA", "sB", "sp", "tp",
- "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5",
- "a6", "a7", "a8", "a9", "aA", "aB", "aC", "aD"
- };
-
- tf->gpr[0] = 0;
-
- for(int i = 0; i < 32; i+=4)
- {
- for(int j = 0; j < 4; j++)
- printk("%s %lx%c",regnames[i+j],tf->gpr[i+j],j < 3 ? ' ' : '\n');
- }
- printk("sr %lx pc %lx va %lx insn %x\n",tf->sr,tf->epc,tf->badvaddr,
- (uint32_t)tf->insn);
-}
+elf_info current;
void init_tf(trapframe_t* tf, long pc, long sp, int user64)
{
memset(tf,0,sizeof(*tf));
if(sizeof(void*) != 8)
kassert(!user64);
- tf->sr = (mfpcr(PCR_SR) & (SR_IM | SR_S64)) | SR_S | SR_EC;
+ tf->sr = (mfpcr(PCR_SR) & (SR_IM | SR_S64 | SR_VM)) | SR_S | SR_EC;
if(user64)
tf->sr |= SR_U64;
tf->gpr[14] = sp;
tf->epc = pc;
}
-static void bss_init()
+static void user_init()
{
- // front-end server zeroes the bss automagically
-}
+ struct args {
+ uint64_t argc;
+ uint64_t argv[];
+ };
-struct args
-{
- uint64_t argc;
- uint64_t argv[];
-};
+ const int argc_argv_size = 1024;
+ size_t stack_top = current.stack_top;
+ struct args* args = (struct args*)(stack_top - argc_argv_size);
+ populate_mapping(args, argc_argv_size, PROT_WRITE);
+ sysret_t r = frontend_syscall(SYS_getmainvars, (long)args, argc_argv_size, 0, 0);
+ kassert(r.result == 0);
-static struct args* stack_init(unsigned long* stack_top)
-{
- *stack_top -= USER_MAINVARS_SIZE;
+ // argv[0] is the proxy kernel itself. skip it.
+ args->argv[0] = args->argc - 1;
+ args = (struct args*)args->argv;
+ stack_top = (uintptr_t)args;
+
+ // load program named by argv[0]
+ current.phdr_top = stack_top;
+ load_elf((char*)args->argv[0], &current);
+
+ 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_NULL, 0}
+ };
- struct args* args = (struct args*)(*stack_top - sizeof(args->argc));
- sysret_t r = frontend_syscall(SYS_getmainvars, (long)args, USER_MAINVARS_SIZE, 0, 0);
- kassert(r.result == 0);
-
- // chop off argv[0]
- args->argv[0] = args->argc-1;
- return (struct args*)args->argv;
-}
+ // 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);
-static void jump_usrstart(const char* fn, long sp)
-{
trapframe_t tf;
-
- int user64;
- long start = load_elf(fn, &user64);
+ init_tf(&tf, current.entry, stack_top, current.elf64);
__clear_cache(0, 0);
-
- init_tf(&tf, start, sp, user64);
pop_tf(&tf);
}
-uint32_t mem_mb;
-
void boot()
{
- bss_init();
file_init();
-
- // word 0 of memory contains # of MB of memory
- mem_mb = *(uint32_t*)0;
-
- unsigned long stack_top = 0x80000000;
- if (mem_mb < stack_top / (1024 * 1024))
- stack_top = mem_mb * (1024 * 1024);
-
- struct args* args = stack_init(&stack_top);
- jump_usrstart((char*)(long)args->argv[0], stack_top);
+ vm_init();
+ user_init();
}