aboutsummaryrefslogtreecommitdiff
path: root/bbl
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2016-03-09 23:58:17 -0800
committerAndrew Waterman <waterman@cs.berkeley.edu>2016-03-09 23:58:17 -0800
commitb94c7a4b07f96f24ae7411780abf874416549f7b (patch)
treeb94ca015e49392f52e5abf1209ee184fcf874db4 /bbl
parentf5a96732cb81571a3ba6b081b8556187d564f678 (diff)
downloadriscv-pk-b94c7a4b07f96f24ae7411780abf874416549f7b.zip
riscv-pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.gz
riscv-pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.bz2
Refactor pk, bbl, machine into separate libraries
Yuck.
Diffstat (limited to 'bbl')
-rw-r--r--bbl/bbl.ac8
-rw-r--r--bbl/bbl.c76
-rw-r--r--bbl/bbl.h23
-rw-r--r--bbl/bbl.lds100
-rw-r--r--bbl/bbl.mk.in22
-rw-r--r--bbl/kernel_elf.c54
-rw-r--r--bbl/logo.c32
-rw-r--r--bbl/payload.S7
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: