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 |
#ifndef _RISCV_MCALL_H |
||||
#define _PK_MCALL_H |
#define _RISCV_MCALL_H |
||||
|
|
||||
#define MCALL_HART_ID 0 |
#define MCALL_HART_ID 0 |
||||
#define MCALL_CONSOLE_PUTCHAR 1 |
#define MCALL_CONSOLE_PUTCHAR 1 |
||||
@ -1,6 +1,7 @@ |
|||||
// See LICENSE for license details. |
// See LICENSE for license details. |
||||
|
|
||||
#include "mtrap.h" |
#include "mtrap.h" |
||||
|
#include "bits.h" |
||||
|
|
||||
.data |
.data |
||||
.align 6 |
.align 6 |
||||
@ -1,11 +1,10 @@ |
|||||
#include "mtrap.h" |
#include "mtrap.h" |
||||
#include "sbi.h" |
#include "sbi.h" |
||||
#include "boot.h" |
|
||||
|
|
||||
uintptr_t __sbi_query_memory(uintptr_t id, memory_block_info *p) |
uintptr_t __sbi_query_memory(uintptr_t id, memory_block_info *p) |
||||
{ |
{ |
||||
if (id == 0) { |
if (id == 0) { |
||||
p->base = current.first_free_paddr; |
p->base = first_free_paddr; |
||||
p->size = mem_size - p->base; |
p->size = mem_size - p->base; |
||||
return 0; |
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