aboutsummaryrefslogtreecommitdiff
path: root/pk/init.c
blob: 851e8782d81855eb030420aaa39bb0ab1840e90e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// See LICENSE for license details.

#include "pk.h"
#include "file.h"
#include "vm.h"
#include "frontend.h"
#include "elf.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

elf_info current;
int have_vm = 1; // unless -p flag is given

int uarch_counters_enabled;
long uarch_counters[NUM_COUNTERS];
char* uarch_counter_names[NUM_COUNTERS];

void init_tf(trapframe_t* tf, long pc, long sp, int user64)
{
  memset(tf, 0, sizeof(*tf));
#ifdef __riscv64
  if (!user64)
    panic("can't run 32-bit ELF on 64-bit pk");
#else
  if (user64)
    panic("can't run 64-bit ELF on 32-bit pk");
#endif
  tf->status = read_csr(sstatus);
  tf->gpr[2] = sp;
  tf->epc = pc;
}

static void handle_option(const char* s)
{
  switch (s[1])
  {
    case 's': // print cycle count upon termination
      current.t0 = 1;
      break;

    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;

    case 'm': // memory capacity in MiB
    {
      uintptr_t mem_mb = atol(&s[2]);
      if (!mem_mb)
        goto need_nonzero_int;
      mem_size = mem_mb << 20;
      if ((mem_size >> 20) < mem_mb)
        mem_size = (typeof(mem_size))-1 & -RISCV_PGSIZE;
      break;
    }

    case 'p': // number of harts
      num_harts = atol(&s[2]);
      if (!num_harts)
        goto need_nonzero_int;
      break;

    default:
      panic("unrecognized option: `%c'", s[1]);
      break;
  }
  return;

need_nonzero_int:
  panic("the -%c flag requires a nonzero argument", s[1]);
}

struct mainvars* parse_args(struct mainvars* args)
{
  long r = frontend_syscall(SYS_getmainvars, (uintptr_t)args, sizeof(*args), 0, 0, 0, 0, 0);
  kassert(r == 0);

  // argv[0] is the proxy kernel itself.  skip it and any flags.
  unsigned a0 = 1;
  for ( ; a0 < args->argc && *(char*)(uintptr_t)args->argv[a0] == '-'; a0++)
    handle_option((const char*)(uintptr_t)args->argv[a0]);
  args->argv[a0-1] = args->argc - a0;
  return (struct mainvars*)&args->argv[a0-1];
}

void boot_loader(struct mainvars* args)
{
  // load program named by argv[0]
  long phdrs[128];
  current.phdr = (uintptr_t)phdrs;
  current.phdr_size = sizeof(phdrs);
  if (!args->argc)
    panic("tell me what ELF to load!");
  load_elf((char*)(uintptr_t)args->argv[0], &current);

  run_loaded_program(args);
}