62 changed files with 960 additions and 559 deletions
@ -0,0 +1,8 @@ |
|||
AC_ARG_ENABLE([logo], AS_HELP_STRING([--disable-logo], [Disable boot logo])) |
|||
AS_IF([test "x$enable_logo" != "xno"], [ |
|||
AC_DEFINE([PK_ENABLE_LOGO],,[Define if the RISC-V logo is to be displayed]) |
|||
]) |
|||
|
|||
AC_ARG_WITH([payload], AS_HELP_STRING([--with-payload], [Set ELF payload for bbl]), |
|||
[AC_SUBST([BBL_PAYLOAD], $with_payload, [Kernel payload for bbl])], |
|||
[AC_SUBST([BBL_PAYLOAD], [dummy_payload], [Kernel payload for bbl])]) |
|||
@ -0,0 +1,76 @@ |
|||
#include "bbl.h" |
|||
#include "mtrap.h" |
|||
#include "atomic.h" |
|||
#include "vm.h" |
|||
#include "bits.h" |
|||
#include "config.h" |
|||
#include <string.h> |
|||
|
|||
static kernel_elf_info info; |
|||
static volatile int elf_loaded; |
|||
|
|||
static void supervisor_vm_init() |
|||
{ |
|||
uintptr_t highest_va = -first_free_paddr; |
|||
mem_size = MIN(mem_size, highest_va - info.first_user_vaddr) & -MEGAPAGE_SIZE; |
|||
|
|||
pte_t* sbi_pt = (pte_t*)(info.first_vaddr_after_user + info.load_offset); |
|||
memset(sbi_pt, 0, RISCV_PGSIZE); |
|||
pte_t* middle_pt = (void*)sbi_pt + RISCV_PGSIZE; |
|||
#ifndef __riscv64 |
|||
size_t num_middle_pts = 1; |
|||
pte_t* root_pt = middle_pt; |
|||
memset(root_pt, 0, RISCV_PGSIZE); |
|||
#else |
|||
size_t num_middle_pts = (-info.first_user_vaddr - 1) / GIGAPAGE_SIZE + 1; |
|||
pte_t* root_pt = (void*)middle_pt + num_middle_pts * RISCV_PGSIZE; |
|||
memset(middle_pt, 0, (num_middle_pts + 1) * RISCV_PGSIZE); |
|||
for (size_t i = 0; i < num_middle_pts; i++) |
|||
root_pt[(1<<RISCV_PGLEVEL_BITS)-num_middle_pts+i] = ptd_create(((uintptr_t)middle_pt >> RISCV_PGSHIFT) + i); |
|||
#endif |
|||
|
|||
for (uintptr_t vaddr = info.first_user_vaddr, paddr = vaddr + info.load_offset, end = info.first_vaddr_after_user; |
|||
paddr < mem_size; vaddr += MEGAPAGE_SIZE, paddr += MEGAPAGE_SIZE) { |
|||
int l2_shift = RISCV_PGLEVEL_BITS + RISCV_PGSHIFT; |
|||
size_t l2_idx = (info.first_user_vaddr >> l2_shift) & ((1 << RISCV_PGLEVEL_BITS)-1); |
|||
l2_idx += ((vaddr - info.first_user_vaddr) >> l2_shift); |
|||
middle_pt[l2_idx] = pte_create(paddr >> RISCV_PGSHIFT, PTE_TYPE_SRWX_GLOBAL); |
|||
} |
|||
|
|||
// map SBI at top of vaddr space
|
|||
extern char _sbi_end; |
|||
uintptr_t num_sbi_pages = ((uintptr_t)&_sbi_end - 1) / RISCV_PGSIZE + 1; |
|||
assert(num_sbi_pages <= (1 << RISCV_PGLEVEL_BITS)); |
|||
for (uintptr_t i = 0; i < num_sbi_pages; i++) { |
|||
uintptr_t idx = (1 << RISCV_PGLEVEL_BITS) - num_sbi_pages + i; |
|||
sbi_pt[idx] = pte_create(i, PTE_TYPE_SRX_GLOBAL); |
|||
} |
|||
pte_t* sbi_pte = middle_pt + ((num_middle_pts << RISCV_PGLEVEL_BITS)-1); |
|||
assert(!*sbi_pte); |
|||
*sbi_pte = ptd_create((uintptr_t)sbi_pt >> RISCV_PGSHIFT); |
|||
|
|||
mb(); |
|||
root_page_table = root_pt; |
|||
write_csr(sptbr, (uintptr_t)root_pt >> RISCV_PGSHIFT); |
|||
} |
|||
|
|||
void boot_loader() |
|||
{ |
|||
extern char _payload_start, _payload_end; |
|||
load_kernel_elf(&_payload_start, &_payload_end - &_payload_start, &info); |
|||
supervisor_vm_init(); |
|||
#ifdef PK_ENABLE_LOGO |
|||
print_logo(); |
|||
#endif |
|||
mb(); |
|||
elf_loaded = 1; |
|||
enter_supervisor_mode((void *)info.entry, 0); |
|||
} |
|||
|
|||
void boot_other_hart() |
|||
{ |
|||
while (!elf_loaded) |
|||
; |
|||
mb(); |
|||
enter_supervisor_mode((void *)info.entry, 0); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// See LICENSE for license details.
|
|||
|
|||
#ifndef _BBL_H |
|||
#define _BBL_H |
|||
|
|||
#ifndef __ASSEMBLER__ |
|||
|
|||
#include <stdint.h> |
|||
#include <stddef.h> |
|||
|
|||
typedef struct { |
|||
uintptr_t entry; |
|||
uintptr_t first_user_vaddr; |
|||
uintptr_t first_vaddr_after_user; |
|||
uintptr_t load_offset; |
|||
} kernel_elf_info; |
|||
|
|||
void load_kernel_elf(void* blob, size_t size, kernel_elf_info* info); |
|||
void print_logo(); |
|||
|
|||
#endif // !__ASSEMBLER__
|
|||
|
|||
#endif |
|||
@ -0,0 +1,100 @@ |
|||
OUTPUT_ARCH( "riscv" ) |
|||
|
|||
ENTRY( reset_vector ) |
|||
|
|||
SECTIONS |
|||
{ |
|||
|
|||
/*--------------------------------------------------------------------*/ |
|||
/* Code and read-only segment */ |
|||
/*--------------------------------------------------------------------*/ |
|||
|
|||
/* Begining of code and text segment */ |
|||
. = 0; |
|||
_ftext = .; |
|||
PROVIDE( eprol = . ); |
|||
|
|||
.text : |
|||
{ |
|||
*(.text.init) |
|||
} |
|||
|
|||
/* text: Program code section */ |
|||
.text : |
|||
{ |
|||
*(.text) |
|||
*(.text.*) |
|||
*(.gnu.linkonce.t.*) |
|||
} |
|||
|
|||
/* rodata: Read-only data */ |
|||
.rodata : |
|||
{ |
|||
*(.rdata) |
|||
*(.rodata) |
|||
*(.rodata.*) |
|||
*(.gnu.linkonce.r.*) |
|||
} |
|||
|
|||
/* End of code and read-only segment */ |
|||
PROVIDE( etext = . ); |
|||
_etext = .; |
|||
|
|||
/*--------------------------------------------------------------------*/ |
|||
/* Initialized data segment */ |
|||
/*--------------------------------------------------------------------*/ |
|||
|
|||
/* Start of initialized data segment */ |
|||
. = ALIGN(16); |
|||
_fdata = .; |
|||
|
|||
/* data: Writable data */ |
|||
.data : |
|||
{ |
|||
*(.data) |
|||
*(.data.*) |
|||
*(.srodata*) |
|||
*(.gnu.linkonce.d.*) |
|||
*(.comment) |
|||
} |
|||
|
|||
/* End of initialized data segment */ |
|||
. = ALIGN(4); |
|||
PROVIDE( edata = . ); |
|||
_edata = .; |
|||
|
|||
/*--------------------------------------------------------------------*/ |
|||
/* Uninitialized data segment */ |
|||
/*--------------------------------------------------------------------*/ |
|||
|
|||
/* Start of uninitialized data segment */ |
|||
. = .; |
|||
_fbss = .; |
|||
|
|||
/* sbss: Uninitialized writeable small data section */ |
|||
. = .; |
|||
|
|||
/* bss: Uninitialized writeable data section */ |
|||
. = .; |
|||
_bss_start = .; |
|||
.bss : |
|||
{ |
|||
*(.bss) |
|||
*(.bss.*) |
|||
*(.sbss*) |
|||
*(.gnu.linkonce.b.*) |
|||
*(COMMON) |
|||
} |
|||
|
|||
.sbi : |
|||
{ |
|||
*(.sbi) |
|||
} |
|||
|
|||
.payload : |
|||
{ |
|||
*(.payload) |
|||
} |
|||
|
|||
_end = .; |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
bbl_subproject_deps = \
|
|||
util \
|
|||
softfloat \
|
|||
machine \
|
|||
dummy_payload \
|
|||
|
|||
bbl_hdrs = \
|
|||
bbl.h \
|
|||
|
|||
bbl_c_srcs = \
|
|||
kernel_elf.c \
|
|||
logo.c \
|
|||
|
|||
bbl_asm_srcs = \
|
|||
payload.S \
|
|||
|
|||
payload.o: $(bbl_payload) |
|||
|
|||
bbl_test_srcs = |
|||
|
|||
bbl_install_prog_srcs = \
|
|||
bbl.c \
|
|||
@ -0,0 +1,54 @@ |
|||
// See LICENSE for license details.
|
|||
|
|||
#include "mtrap.h" |
|||
#include "bbl.h" |
|||
#include "bits.h" |
|||
#include "vm.h" |
|||
#include <elf.h> |
|||
#include <string.h> |
|||
|
|||
void load_kernel_elf(void* blob, size_t size, kernel_elf_info* info) |
|||
{ |
|||
Elf_Ehdr* eh = blob; |
|||
if (sizeof(*eh) > size || |
|||
!(eh->e_ident[0] == '\177' && eh->e_ident[1] == 'E' && |
|||
eh->e_ident[2] == 'L' && eh->e_ident[3] == 'F')) |
|||
goto fail; |
|||
|
|||
if (IS_ELF64(*eh) != (sizeof(uintptr_t) == 8)) |
|||
goto fail; |
|||
|
|||
uintptr_t min_vaddr = -1, max_vaddr = 0; |
|||
size_t phdr_size = eh->e_phnum * sizeof(Elf_Ehdr); |
|||
Elf_Phdr* ph = blob + eh->e_phoff; |
|||
if (eh->e_phoff + phdr_size > size) |
|||
goto fail; |
|||
first_free_paddr = ROUNDUP(first_free_paddr, MEGAPAGE_SIZE); |
|||
for (int i = 0; i < eh->e_phnum; i++) |
|||
if (ph[i].p_type == PT_LOAD && ph[i].p_memsz && ph[i].p_vaddr < min_vaddr) |
|||
min_vaddr = ph[i].p_vaddr; |
|||
min_vaddr = ROUNDDOWN(min_vaddr, MEGAPAGE_SIZE); |
|||
uintptr_t bias = first_free_paddr - min_vaddr; |
|||
for (int i = eh->e_phnum - 1; i >= 0; i--) { |
|||
if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { |
|||
uintptr_t prepad = ph[i].p_vaddr % RISCV_PGSIZE; |
|||
uintptr_t vaddr = ph[i].p_vaddr + bias; |
|||
if (vaddr + ph[i].p_memsz > max_vaddr) |
|||
max_vaddr = vaddr + ph[i].p_memsz; |
|||
if (ph[i].p_offset + ph[i].p_filesz > size) |
|||
goto fail; |
|||
memcpy((void*)vaddr, blob + ph[i].p_offset, ph[i].p_filesz); |
|||
memset((void*)vaddr - prepad, 0, prepad); |
|||
memset((void*)vaddr + ph[i].p_filesz, 0, ph[i].p_memsz - ph[i].p_filesz); |
|||
} |
|||
} |
|||
|
|||
info->entry = eh->e_entry; |
|||
info->load_offset = bias; |
|||
info->first_user_vaddr = min_vaddr; |
|||
info->first_vaddr_after_user = ROUNDUP(max_vaddr - bias, RISCV_PGSIZE); |
|||
return; |
|||
|
|||
fail: |
|||
die("failed to load payload"); |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
.section ".payload","a",@progbits |
|||
.align 3 |
|||
|
|||
.globl _payload_start, _payload_end |
|||
_payload_start: |
|||
.incbin BBL_PAYLOAD |
|||
_payload_end: |
|||
@ -0,0 +1,21 @@ |
|||
#include <stdint.h> |
|||
#include "sbi.h" |
|||
|
|||
asm (".globl _start\n\
|
|||
_start: la sp, stack\n\ |
|||
j entry\n\ |
|||
.pushsection .rodata\n\ |
|||
.align 4\n\ |
|||
.skip 4096\n\ |
|||
stack:\n\ |
|||
.popsection"); |
|||
|
|||
void entry() |
|||
{ |
|||
const char* message = |
|||
"This is bbl's dummy_payload. To boot a real kernel, reconfigure\n\
|
|||
bbl with the flag --with-payload=PATH, then rebuild bbl.\n"; |
|||
while (*message) |
|||
sbi_console_putchar(*message++); |
|||
sbi_shutdown(); |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
SECTIONS { |
|||
. = -0x80000000; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
dummy_payload_subproject_deps = \
|
|||
|
|||
dummy_payload_hdrs = \
|
|||
|
|||
dummy_payload_c_srcs = \
|
|||
|
|||
dummy_payload_asm_srcs = \
|
|||
dummy_sbi.S \
|
|||
|
|||
dummy_payload_test_srcs = |
|||
|
|||
dummy_payload_install_prog_srcs = \
|
|||
dummy_payload.c \
|
|||
@ -0,0 +1 @@ |
|||
../machine/sbi.S |
|||
@ -0,0 +1,33 @@ |
|||
#ifndef _RISCV_BITS_H |
|||
#define _RISCV_BITS_H |
|||
|
|||
#define likely(x) __builtin_expect((x), 1) |
|||
#define unlikely(x) __builtin_expect((x), 0) |
|||
|
|||
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) |
|||
#define ROUNDDOWN(a, b) ((a)/(b)*(b)) |
|||
|
|||
#define MAX(a, b) ((a) > (b) ? (a) : (b)) |
|||
#define MIN(a, b) ((a) < (b) ? (a) : (b)) |
|||
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) |
|||
|
|||
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) |
|||
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) |
|||
|
|||
#define STR(x) XSTR(x) |
|||
#define XSTR(x) #x |
|||
|
|||
#ifdef __riscv64 |
|||
# define SLL32 sllw |
|||
# define STORE sd |
|||
# define LOAD ld |
|||
# define LOG_REGBYTES 3 |
|||
#else |
|||
# define SLL32 sll |
|||
# define STORE sw |
|||
# define LOAD lw |
|||
# define LOG_REGBYTES 2 |
|||
#endif |
|||
#define REGBYTES (1 << LOG_REGBYTES) |
|||
|
|||
#endif |
|||
@ -0,0 +1,18 @@ |
|||
#ifndef _RISCV_HTIF_H |
|||
#define _RISCV_HTIF_H |
|||
|
|||
#include <stdint.h> |
|||
|
|||
#ifdef __riscv64 |
|||
# define TOHOST_CMD(dev, cmd, payload) \ |
|||
(((uint64_t)(dev) << 56) | ((uint64_t)(cmd) << 48) | (uint64_t)(payload)) |
|||
#else |
|||
# define TOHOST_CMD(dev, cmd, payload) ({ \ |
|||
if ((dev) || (cmd)) __builtin_trap(); \ |
|||
(payload); }) |
|||
#endif |
|||
#define FROMHOST_DEV(fromhost_value) ((uint64_t)(fromhost_value) >> 56) |
|||
#define FROMHOST_CMD(fromhost_value) ((uint64_t)(fromhost_value) << 8 >> 56) |
|||
#define FROMHOST_DATA(fromhost_value) ((uint64_t)(fromhost_value) << 16 >> 16) |
|||
|
|||
#endif |
|||
@ -0,0 +1,4 @@ |
|||
AC_ARG_ENABLE([fp-emulation], AS_HELP_STRING([--disable-fp-emulation], [Disable floating-point emulation])) |
|||
AS_IF([test "x$enable_fp_emulation" != "xno"], [ |
|||
AC_DEFINE([PK_ENABLE_FP_EMULATION],,[Define if floating-point emulation is enabled]) |
|||
]) |
|||
@ -0,0 +1,29 @@ |
|||
machine_subproject_deps = \
|
|||
softfloat \
|
|||
|
|||
machine_hdrs = \
|
|||
atomic.h \
|
|||
bits.h \
|
|||
emulation.h \
|
|||
encoding.h \
|
|||
fp_emulation.h \
|
|||
htif.h \
|
|||
mcall.h \
|
|||
mtrap.h \
|
|||
sbi.h \
|
|||
unprivileged_memory.h \
|
|||
vm.h \
|
|||
|
|||
machine_c_srcs = \
|
|||
mtrap.c \
|
|||
minit.c \
|
|||
emulation.c \
|
|||
fp_emulation.c \
|
|||
sbi_impl.c \
|
|||
configstring.c \
|
|||
|
|||
machine_asm_srcs = \
|
|||
mentry.S \
|
|||
fp_asm.S \
|
|||
sbi_entry.S \
|
|||
sbi.S \
|
|||
@ -1,5 +1,5 @@ |
|||
#ifndef _PK_MCALL_H |
|||
#define _PK_MCALL_H |
|||
#ifndef _RISCV_MCALL_H |
|||
#define _RISCV_MCALL_H |
|||
|
|||
#define MCALL_HART_ID 0 |
|||
#define MCALL_CONSOLE_PUTCHAR 1 |
|||
@ -1,6 +1,7 @@ |
|||
// See LICENSE for license details. |
|||
|
|||
#include "mtrap.h" |
|||
#include "bits.h" |
|||
|
|||
.data |
|||
.align 6 |
|||
@ -1,11 +1,10 @@ |
|||
#include "mtrap.h" |
|||
#include "sbi.h" |
|||
#include "boot.h" |
|||
|
|||
uintptr_t __sbi_query_memory(uintptr_t id, memory_block_info *p) |
|||
{ |
|||
if (id == 0) { |
|||
p->base = current.first_free_paddr; |
|||
p->base = first_free_paddr; |
|||
p->size = mem_size - p->base; |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
#ifndef _VM_H |
|||
#define _VM_H |
|||
|
|||
#include "encoding.h" |
|||
#include <stdint.h> |
|||
|
|||
#define MEGAPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS)) |
|||
#ifdef __riscv64 |
|||
# define VM_CHOICE VM_SV39 |
|||
# define VA_BITS 39 |
|||
# define GIGAPAGE_SIZE (MEGAPAGE_SIZE << RISCV_PGLEVEL_BITS) |
|||
#else |
|||
# define VM_CHOICE VM_SV32 |
|||
# define VA_BITS 32 |
|||
#endif |
|||
|
|||
typedef uintptr_t pte_t; |
|||
extern pte_t* root_page_table; |
|||
|
|||
static inline void flush_tlb() |
|||
{ |
|||
asm volatile("sfence.vm"); |
|||
} |
|||
|
|||
static inline pte_t pte_create(uintptr_t ppn, int type) |
|||
{ |
|||
return (ppn << PTE_PPN_SHIFT) | PTE_V | type; |
|||
} |
|||
|
|||
static inline pte_t ptd_create(uintptr_t ppn) |
|||
{ |
|||
return pte_create(ppn, PTE_TYPE_TABLE); |
|||
} |
|||
|
|||
#endif |
|||
@ -1,36 +0,0 @@ |
|||
#include "boot.h" |
|||
#include "mtrap.h" |
|||
#include "vm.h" |
|||
#include "config.h" |
|||
|
|||
static volatile int elf_loaded; |
|||
|
|||
static void enter_entry_point() |
|||
{ |
|||
prepare_supervisor_mode(); |
|||
write_csr(mepc, current.entry); |
|||
asm volatile("eret"); |
|||
__builtin_unreachable(); |
|||
} |
|||
|
|||
void run_loaded_program(size_t argc, char** argv) |
|||
{ |
|||
if (!current.is_supervisor) |
|||
die("bbl can't run user binaries; try using pk instead"); |
|||
|
|||
supervisor_vm_init(); |
|||
#ifdef PK_ENABLE_LOGO |
|||
print_logo(); |
|||
#endif |
|||
mb(); |
|||
elf_loaded = 1; |
|||
enter_entry_point(); |
|||
} |
|||
|
|||
void boot_other_hart() |
|||
{ |
|||
while (!elf_loaded) |
|||
; |
|||
mb(); |
|||
enter_entry_point(); |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
#ifndef PK_BITS_H |
|||
#define PK_BITS_H |
|||
|
|||
#define likely(x) __builtin_expect((x), 1) |
|||
#define unlikely(x) __builtin_expect((x), 0) |
|||
|
|||
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) |
|||
#define ROUNDDOWN(a, b) ((a)/(b)*(b)) |
|||
|
|||
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) |
|||
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) |
|||
|
|||
#define CONST_POPCOUNT2(x) ((((x) >> 0) & 1) + (((x) >> 1) & 1)) |
|||
#define CONST_POPCOUNT4(x) (CONST_POPCOUNT2(x) + CONST_POPCOUNT2((x)>>2)) |
|||
#define CONST_POPCOUNT8(x) (CONST_POPCOUNT4(x) + CONST_POPCOUNT4((x)>>4)) |
|||
#define CONST_POPCOUNT16(x) (CONST_POPCOUNT8(x) + CONST_POPCOUNT8((x)>>8)) |
|||
#define CONST_POPCOUNT32(x) (CONST_POPCOUNT16(x) + CONST_POPCOUNT16((x)>>16)) |
|||
#define CONST_POPCOUNT64(x) (CONST_POPCOUNT32(x) + CONST_POPCOUNT32((x)>>32)) |
|||
#define CONST_POPCOUNT(x) CONST_POPCOUNT64(x) |
|||
|
|||
#define CONST_CTZ2(x) CONST_POPCOUNT2(((x) & -(x))-1) |
|||
#define CONST_CTZ4(x) CONST_POPCOUNT4(((x) & -(x))-1) |
|||
#define CONST_CTZ8(x) CONST_POPCOUNT8(((x) & -(x))-1) |
|||
#define CONST_CTZ16(x) CONST_POPCOUNT16(((x) & -(x))-1) |
|||
#define CONST_CTZ32(x) CONST_POPCOUNT32(((x) & -(x))-1) |
|||
#define CONST_CTZ64(x) CONST_POPCOUNT64(((x) & -(x))-1) |
|||
#define CONST_CTZ(x) CONST_CTZ64(x) |
|||
|
|||
#define STR(x) XSTR(x) |
|||
#define XSTR(x) #x |
|||
|
|||
#ifdef __riscv64 |
|||
# define SLL32 sllw |
|||
# define STORE sd |
|||
# define LOAD ld |
|||
# define LOG_REGBYTES 3 |
|||
#else |
|||
# define SLL32 sll |
|||
# define STORE sw |
|||
# define LOAD lw |
|||
# define LOG_REGBYTES 2 |
|||
#endif |
|||
#define REGBYTES (1 << LOG_REGBYTES) |
|||
|
|||
#endif |
|||
@ -1,82 +0,0 @@ |
|||
// See LICENSE for license details.
|
|||
|
|||
#include "pk.h" |
|||
#include "boot.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) |
|||
{ |
|||
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 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; |
|||
|
|||
default: |
|||
panic("unrecognized option: `%c'", s[1]); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
#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; |
|||
} |
|||
|
|||
void boot_loader() |
|||
{ |
|||
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); |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
util_subproject_deps = \
|
|||
|
|||
util_hdrs = \
|
|||
|
|||
util_c_srcs = \
|
|||
snprintf.c \
|
|||
string.c \
|
|||
|
|||
util_asm_srcs = \
|
|||
Loading…
Reference in new issue