aboutsummaryrefslogtreecommitdiff
path: root/bbl/bbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'bbl/bbl.c')
-rw-r--r--bbl/bbl.c76
1 files changed, 76 insertions, 0 deletions
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);
+}