diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:58:17 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2016-03-09 23:58:17 -0800 |
commit | b94c7a4b07f96f24ae7411780abf874416549f7b (patch) | |
tree | b94ca015e49392f52e5abf1209ee184fcf874db4 /bbl | |
parent | f5a96732cb81571a3ba6b081b8556187d564f678 (diff) | |
download | pk-b94c7a4b07f96f24ae7411780abf874416549f7b.zip pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.gz pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.bz2 |
Refactor pk, bbl, machine into separate libraries
Yuck.
Diffstat (limited to 'bbl')
-rw-r--r-- | bbl/bbl.ac | 8 | ||||
-rw-r--r-- | bbl/bbl.c | 76 | ||||
-rw-r--r-- | bbl/bbl.h | 23 | ||||
-rw-r--r-- | bbl/bbl.lds | 100 | ||||
-rw-r--r-- | bbl/bbl.mk.in | 22 | ||||
-rw-r--r-- | bbl/kernel_elf.c | 54 | ||||
-rw-r--r-- | bbl/logo.c | 32 | ||||
-rw-r--r-- | bbl/payload.S | 7 |
8 files changed, 322 insertions, 0 deletions
diff --git a/bbl/bbl.ac b/bbl/bbl.ac new file mode 100644 index 0000000..51dcf01 --- /dev/null +++ b/bbl/bbl.ac @@ -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])]) diff --git a/bbl/bbl.c b/bbl/bbl.c new file mode 100644 index 0000000..cd52fc1 --- /dev/null +++ b/bbl/bbl.c @@ -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); +} diff --git a/bbl/bbl.h b/bbl/bbl.h new file mode 100644 index 0000000..e9e1dab --- /dev/null +++ b/bbl/bbl.h @@ -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 diff --git a/bbl/bbl.lds b/bbl/bbl.lds new file mode 100644 index 0000000..5ccdf22 --- /dev/null +++ b/bbl/bbl.lds @@ -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 = .; +} diff --git a/bbl/bbl.mk.in b/bbl/bbl.mk.in new file mode 100644 index 0000000..1bb4cd1 --- /dev/null +++ b/bbl/bbl.mk.in @@ -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 \ diff --git a/bbl/kernel_elf.c b/bbl/kernel_elf.c new file mode 100644 index 0000000..e22c35c --- /dev/null +++ b/bbl/kernel_elf.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"); +} diff --git a/bbl/logo.c b/bbl/logo.c new file mode 100644 index 0000000..673899d --- /dev/null +++ b/bbl/logo.c @@ -0,0 +1,32 @@ +#include <string.h> +#include "mtrap.h" + +static const char logo[] = +" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" +" vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv\n" +"rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" +"rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv \n" +"rr vvvvvvvvvvvvvvvvvvvvvv \n" +"rr vvvvvvvvvvvvvvvvvvvvvvvv rr\n" +"rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr\n" +"rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr\n" +"rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr\n" +"rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr\n" +"rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr\n" +"rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr\n" +"rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr\n" +"\n" +" INSTRUCTION SETS WANT TO BE FREE\n"; + +void print_logo() +{ + putstring(logo); +} diff --git a/bbl/payload.S b/bbl/payload.S new file mode 100644 index 0000000..7ff1e58 --- /dev/null +++ b/bbl/payload.S @@ -0,0 +1,7 @@ +.section ".payload","a",@progbits +.align 3 + +.globl _payload_start, _payload_end +_payload_start: +.incbin BBL_PAYLOAD +_payload_end: |