aboutsummaryrefslogtreecommitdiff
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
parentf5a96732cb81571a3ba6b081b8556187d564f678 (diff)
downloadpk-b94c7a4b07f96f24ae7411780abf874416549f7b.zip
pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.gz
pk-b94c7a4b07f96f24ae7411780abf874416549f7b.tar.bz2
Refactor pk, bbl, machine into separate libraries
Yuck.
-rw-r--r--Makefile.in7
-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.c (renamed from pk/logo.c)4
-rw-r--r--bbl/payload.S7
-rw-r--r--config.h.in12
-rwxr-xr-xconfigure223
-rw-r--r--configure.ac2
-rw-r--r--dummy_payload/dummy_payload.ac0
-rw-r--r--dummy_payload/dummy_payload.c21
-rw-r--r--dummy_payload/dummy_payload.lds3
-rw-r--r--dummy_payload/dummy_payload.mk.in13
l---------dummy_payload/dummy_sbi.S1
-rw-r--r--machine/atomic.h (renamed from pk/atomic.h)2
-rw-r--r--machine/bits.h33
-rw-r--r--machine/configstring.c (renamed from pk/configstring.c)0
-rw-r--r--machine/emulation.c (renamed from pk/emulation.c)0
-rw-r--r--machine/emulation.h (renamed from pk/emulation.h)0
-rw-r--r--machine/encoding.h (renamed from pk/encoding.h)0
-rw-r--r--machine/fp_asm.S (renamed from pk/fp_asm.S)0
-rw-r--r--machine/fp_emulation.c (renamed from pk/fp_emulation.c)0
-rw-r--r--machine/fp_emulation.h (renamed from pk/fp_emulation.h)0
-rw-r--r--machine/htif.h18
-rw-r--r--machine/machine.ac4
-rw-r--r--machine/machine.mk.in29
-rw-r--r--machine/mcall.h (renamed from pk/mcall.h)4
-rw-r--r--machine/mentry.S (renamed from pk/mentry.S)1
-rw-r--r--machine/minit.c (renamed from pk/minit.c)38
-rw-r--r--machine/mtrap.c (renamed from pk/mtrap.c)14
-rw-r--r--machine/mtrap.h (renamed from pk/mtrap.h)20
-rw-r--r--machine/sbi.S (renamed from pk/sbi.S)0
-rw-r--r--machine/sbi.h (renamed from pk/sbi.h)0
-rw-r--r--machine/sbi_entry.S (renamed from pk/sbi_entry.S)8
-rw-r--r--machine/sbi_impl.c (renamed from pk/sbi_impl.c)3
-rw-r--r--machine/unprivileged_memory.h (renamed from pk/unprivileged_memory.h)0
-rw-r--r--machine/vm.h35
-rw-r--r--pk/bbl.c36
-rw-r--r--pk/bits.h45
-rw-r--r--pk/boot.h10
-rw-r--r--pk/elf.c137
-rw-r--r--pk/elf.h8
-rw-r--r--pk/file.c10
-rw-r--r--pk/file.h1
-rw-r--r--pk/frontend.h12
-rw-r--r--pk/handlers.c8
-rw-r--r--pk/init.c82
-rw-r--r--pk/mmap.c (renamed from pk/vm.c)186
-rw-r--r--pk/mmap.h (renamed from pk/vm.h)31
-rw-r--r--pk/pk.ac10
-rw-r--r--pk/pk.c95
-rw-r--r--pk/pk.h17
-rw-r--r--pk/pk.lds (renamed from pk/pk.ld)5
-rw-r--r--pk/pk.mk.in30
-rw-r--r--pk/syscall.c2
-rw-r--r--util/snprintf.c (renamed from pk/snprintf.c)0
-rw-r--r--util/string.c (renamed from pk/string.c)0
-rw-r--r--util/util.ac0
-rw-r--r--util/util.mk.in9
62 files changed, 960 insertions, 559 deletions
diff --git a/Makefile.in b/Makefile.in
index 108d19d..8babada 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -35,6 +35,7 @@ default : all
project_name := @PACKAGE_TARNAME@
src_dir := @srcdir@
scripts_dir := $(src_dir)/scripts
+bbl_payload := @BBL_PAYLOAD@
# If the version information is not in the configure script, then we
# assume that we are in a working directory. We use the vcs-version.sh
@@ -83,7 +84,7 @@ VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled))
# - CXXFLAGS : flags for C++ compiler (eg. -Wall,-g,-O3)
CC := @CC@
-CFLAGS := @CFLAGS@ $(CFLAGS)
+CFLAGS := @CFLAGS@ $(CFLAGS) -DBBL_PAYLOAD=\"$(bbl_payload)\"
COMPILE := $(CC) -MMD -MP $(CFLAGS) \
$(sprojs_include)
# Linker
@@ -93,7 +94,7 @@ COMPILE := $(CC) -MMD -MP $(CFLAGS) \
LD := $(CC)
LDFLAGS := @LDFLAGS@ -nostartfiles -nostdlib -static $(LDFLAGS)
LIBS := @LIBS@
-LINK := $(LD) $(LDFLAGS) -T $(src_dir)/pk/pk.ld
+LINK := $(LD) $(LDFLAGS)
# Library creation
@@ -258,7 +259,7 @@ $$($(2)_install_prog_objs) : %.o : %.c
$(COMPILE) -c $$<
$$($(2)_install_prog_exes) : % : %.o $$($(2)_prog_libnames)
- $(LINK) -o $$@ $$< $$($(2)_prog_libarg) $(LIBS)
+ $(LINK) -o $$@ $$< $$($(2)_prog_libarg) $(LIBS) -T $(src_dir)/$(2)/$(2).lds
$(2)_c_deps += $$($(2)_install_prog_deps)
$(2)_junk += \
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/pk/logo.c b/bbl/logo.c
index 2a214c5..673899d 100644
--- a/pk/logo.c
+++ b/bbl/logo.c
@@ -1,5 +1,5 @@
#include <string.h>
-#include "file.h"
+#include "mtrap.h"
static const char logo[] =
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
@@ -28,5 +28,5 @@ static const char logo[] =
void print_logo()
{
- file_write(stderr, logo, sizeof 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:
diff --git a/config.h.in b/config.h.in
index 3424ee6..bc6369e 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,5 +1,14 @@
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef BBL_ENABLED
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef DUMMY_PAYLOAD_ENABLED
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef MACHINE_ENABLED
+
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
@@ -35,3 +44,6 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef UTIL_ENABLED
diff --git a/configure b/configure
index 0cd8fe2..6386de0 100755
--- a/configure
+++ b/configure
@@ -590,6 +590,7 @@ ac_subst_vars='LTLIBOBJS
LIBOBJS
subprojects_enabled
subprojects
+BBL_PAYLOAD
EGREP
GREP
CPP
@@ -667,6 +668,8 @@ enable_option_checking
enable_stow
enable_optional_subprojects
enable_vm
+enable_logo
+with_payload
enable_fp_emulation
'
ac_precious_vars='build_alias
@@ -1303,6 +1306,11 @@ Optional Features:
--disable-logo Disable boot logo
--disable-fp-emulation Disable floating-point emulation
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-payload Set ELF payload for bbl
+
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
@@ -4046,9 +4054,53 @@ $as_echo "#define PK_ENABLE_VM /**/" >>confdefs.h
fi
-# Check whether --enable-vm was given.
-if test "${enable_vm+set}" = set; then :
- enableval=$enable_vm;
+
+
+
+
+ # Determine if this is a required or an optional subproject
+
+
+
+ # Determine if there is a group with the same name
+
+
+
+ # Create variations of the subproject name suitable for use as a CPP
+ # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+ # Add subproject to our running list
+
+ subprojects="$subprojects bbl"
+
+ # Process the subproject appropriately. If enabled add it to the
+ # $enabled_subprojects running shell variable, set a
+ # SUBPROJECT_ENABLED C define, and include the appropriate
+ # 'subproject.ac'.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : bbl" >&5
+$as_echo "$as_me: configuring default subproject : bbl" >&6;}
+ ac_config_files="$ac_config_files bbl.mk:bbl/bbl.mk.in"
+
+ enable_bbl_sproj="yes"
+ subprojects_enabled="$subprojects_enabled bbl"
+
+$as_echo "#define BBL_ENABLED /**/" >>confdefs.h
+
+ # Check whether --enable-logo was given.
+if test "${enable_logo+set}" = set; then :
+ enableval=$enable_logo;
fi
if test "x$enable_logo" != "xno"; then :
@@ -4059,16 +4111,13 @@ $as_echo "#define PK_ENABLE_LOGO /**/" >>confdefs.h
fi
-# Check whether --enable-fp-emulation was given.
-if test "${enable_fp_emulation+set}" = set; then :
- enableval=$enable_fp_emulation;
-fi
-if test "x$enable_fp_emulation" != "xno"; then :
-
-
-$as_echo "#define PK_ENABLE_FP_EMULATION /**/" >>confdefs.h
+# Check whether --with-payload was given.
+if test "${with_payload+set}" = set; then :
+ withval=$with_payload; BBL_PAYLOAD=$with_payload
+else
+ BBL_PAYLOAD=dummy_payload
fi
@@ -4076,6 +4125,7 @@ fi
+
# Determine if this is a required or an optional subproject
@@ -4121,6 +4171,153 @@ $as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h
+ # Determine if this is a required or an optional subproject
+
+
+
+ # Determine if there is a group with the same name
+
+
+
+ # Create variations of the subproject name suitable for use as a CPP
+ # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+ # Add subproject to our running list
+
+ subprojects="$subprojects dummy_payload"
+
+ # Process the subproject appropriately. If enabled add it to the
+ # $enabled_subprojects running shell variable, set a
+ # SUBPROJECT_ENABLED C define, and include the appropriate
+ # 'subproject.ac'.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : dummy_payload" >&5
+$as_echo "$as_me: configuring default subproject : dummy_payload" >&6;}
+ ac_config_files="$ac_config_files dummy_payload.mk:dummy_payload/dummy_payload.mk.in"
+
+ enable_dummy_payload_sproj="yes"
+ subprojects_enabled="$subprojects_enabled dummy_payload"
+
+$as_echo "#define DUMMY_PAYLOAD_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
+ # Determine if this is a required or an optional subproject
+
+
+
+ # Determine if there is a group with the same name
+
+
+
+ # Create variations of the subproject name suitable for use as a CPP
+ # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+ # Add subproject to our running list
+
+ subprojects="$subprojects machine"
+
+ # Process the subproject appropriately. If enabled add it to the
+ # $enabled_subprojects running shell variable, set a
+ # SUBPROJECT_ENABLED C define, and include the appropriate
+ # 'subproject.ac'.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : machine" >&5
+$as_echo "$as_me: configuring default subproject : machine" >&6;}
+ ac_config_files="$ac_config_files machine.mk:machine/machine.mk.in"
+
+ enable_machine_sproj="yes"
+ subprojects_enabled="$subprojects_enabled machine"
+
+$as_echo "#define MACHINE_ENABLED /**/" >>confdefs.h
+
+ # Check whether --enable-fp-emulation was given.
+if test "${enable_fp_emulation+set}" = set; then :
+ enableval=$enable_fp_emulation;
+fi
+
+if test "x$enable_fp_emulation" != "xno"; then :
+
+
+$as_echo "#define PK_ENABLE_FP_EMULATION /**/" >>confdefs.h
+
+
+fi
+
+
+
+
+
+ # Determine if this is a required or an optional subproject
+
+
+
+ # Determine if there is a group with the same name
+
+
+
+ # Create variations of the subproject name suitable for use as a CPP
+ # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+ # Add subproject to our running list
+
+ subprojects="$subprojects util"
+
+ # Process the subproject appropriately. If enabled add it to the
+ # $enabled_subprojects running shell variable, set a
+ # SUBPROJECT_ENABLED C define, and include the appropriate
+ # 'subproject.ac'.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : util" >&5
+$as_echo "$as_me: configuring default subproject : util" >&6;}
+ ac_config_files="$ac_config_files util.mk:util/util.mk.in"
+
+ enable_util_sproj="yes"
+ subprojects_enabled="$subprojects_enabled util"
+
+$as_echo "#define UTIL_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
# Output make variables
@@ -4838,7 +5035,11 @@ for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"pk.mk") CONFIG_FILES="$CONFIG_FILES pk.mk:pk/pk.mk.in" ;;
+ "bbl.mk") CONFIG_FILES="$CONFIG_FILES bbl.mk:bbl/bbl.mk.in" ;;
"softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;;
+ "dummy_payload.mk") CONFIG_FILES="$CONFIG_FILES dummy_payload.mk:dummy_payload/dummy_payload.mk.in" ;;
+ "machine.mk") CONFIG_FILES="$CONFIG_FILES machine.mk:machine/machine.mk.in" ;;
+ "util.mk") CONFIG_FILES="$CONFIG_FILES util.mk:util/util.mk.in" ;;
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 64ddc5f..6253228 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,7 +81,7 @@ AC_SUBST([LIBS], ["-lgcc"])
# The '*' suffix indicates an optional subproject. The '**' suffix
# indicates an optional subproject which is also the name of a group.
-MCPPBS_SUBPROJECTS([ pk, softfloat ])
+MCPPBS_SUBPROJECTS([ pk, bbl, softfloat, dummy_payload, machine, util ])
#-------------------------------------------------------------------------
# MCPPBS subproject groups
diff --git a/dummy_payload/dummy_payload.ac b/dummy_payload/dummy_payload.ac
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dummy_payload/dummy_payload.ac
diff --git a/dummy_payload/dummy_payload.c b/dummy_payload/dummy_payload.c
new file mode 100644
index 0000000..61ed59a
--- /dev/null
+++ b/dummy_payload/dummy_payload.c
@@ -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();
+}
diff --git a/dummy_payload/dummy_payload.lds b/dummy_payload/dummy_payload.lds
new file mode 100644
index 0000000..ee9410b
--- /dev/null
+++ b/dummy_payload/dummy_payload.lds
@@ -0,0 +1,3 @@
+SECTIONS {
+ . = -0x80000000;
+}
diff --git a/dummy_payload/dummy_payload.mk.in b/dummy_payload/dummy_payload.mk.in
new file mode 100644
index 0000000..b1d4ac7
--- /dev/null
+++ b/dummy_payload/dummy_payload.mk.in
@@ -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 \
diff --git a/dummy_payload/dummy_sbi.S b/dummy_payload/dummy_sbi.S
new file mode 120000
index 0000000..2978a97
--- /dev/null
+++ b/dummy_payload/dummy_sbi.S
@@ -0,0 +1 @@
+../machine/sbi.S \ No newline at end of file
diff --git a/pk/atomic.h b/machine/atomic.h
index e4610de..b23acae 100644
--- a/pk/atomic.h
+++ b/machine/atomic.h
@@ -6,7 +6,7 @@
#include "config.h"
#include "encoding.h"
-// Currently, interrupts are always disabled when in pk/bbl.
+// Currently, interrupts are always disabled in M-mode.
#define disable_irqsave() (0)
#define enable_irqrestore(flags) ((void) (flags))
diff --git a/machine/bits.h b/machine/bits.h
new file mode 100644
index 0000000..72514ae
--- /dev/null
+++ b/machine/bits.h
@@ -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
diff --git a/pk/configstring.c b/machine/configstring.c
index 847cd4d..847cd4d 100644
--- a/pk/configstring.c
+++ b/machine/configstring.c
diff --git a/pk/emulation.c b/machine/emulation.c
index 5a66997..5a66997 100644
--- a/pk/emulation.c
+++ b/machine/emulation.c
diff --git a/pk/emulation.h b/machine/emulation.h
index f1a71ec..f1a71ec 100644
--- a/pk/emulation.h
+++ b/machine/emulation.h
diff --git a/pk/encoding.h b/machine/encoding.h
index f2fab36..f2fab36 100644
--- a/pk/encoding.h
+++ b/machine/encoding.h
diff --git a/pk/fp_asm.S b/machine/fp_asm.S
index 4b8dce1..4b8dce1 100644
--- a/pk/fp_asm.S
+++ b/machine/fp_asm.S
diff --git a/pk/fp_emulation.c b/machine/fp_emulation.c
index 536967f..536967f 100644
--- a/pk/fp_emulation.c
+++ b/machine/fp_emulation.c
diff --git a/pk/fp_emulation.h b/machine/fp_emulation.h
index d2357b7..d2357b7 100644
--- a/pk/fp_emulation.h
+++ b/machine/fp_emulation.h
diff --git a/machine/htif.h b/machine/htif.h
new file mode 100644
index 0000000..e66ad06
--- /dev/null
+++ b/machine/htif.h
@@ -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
diff --git a/machine/machine.ac b/machine/machine.ac
new file mode 100644
index 0000000..65acf04
--- /dev/null
+++ b/machine/machine.ac
@@ -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])
+])
diff --git a/machine/machine.mk.in b/machine/machine.mk.in
new file mode 100644
index 0000000..a0b7ca9
--- /dev/null
+++ b/machine/machine.mk.in
@@ -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 \
diff --git a/pk/mcall.h b/machine/mcall.h
index e612628..2096d16 100644
--- a/pk/mcall.h
+++ b/machine/mcall.h
@@ -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
diff --git a/pk/mentry.S b/machine/mentry.S
index 2ded375..50ce9ca 100644
--- a/pk/mentry.S
+++ b/machine/mentry.S
@@ -1,6 +1,7 @@
// See LICENSE for license details.
#include "mtrap.h"
+#include "bits.h"
.data
.align 6
diff --git a/pk/minit.c b/machine/minit.c
index ad9598b..33b94c8 100644
--- a/pk/minit.c
+++ b/machine/minit.c
@@ -1,8 +1,11 @@
-#include "vm.h"
#include "mtrap.h"
+#include "atomic.h"
+#include "vm.h"
#include "fp_emulation.h"
-#include "boot.h"
+#include <string.h>
+pte_t* root_page_table;
+uintptr_t first_free_paddr;
uintptr_t mem_size;
uint32_t num_harts;
@@ -64,6 +67,18 @@ void hls_init(uint32_t id, csr_t* csrs)
hls->csrs = csrs;
}
+static uintptr_t sbi_top_paddr()
+{
+ extern char _end;
+ return ROUNDUP((uintptr_t)&_end, RISCV_PGSIZE);
+}
+
+static void memory_init()
+{
+ mem_size = mem_size / MEGAPAGE_SIZE * MEGAPAGE_SIZE;
+ first_free_paddr = sbi_top_paddr() + num_harts * RISCV_PGSIZE;
+}
+
static void hart_init()
{
mstatus_init();
@@ -73,12 +88,10 @@ static void hart_init()
void init_first_hart()
{
- file_init();
hart_init();
-
memset(HLS(), 0, sizeof(*HLS()));
parse_config_string();
- vm_init();
+ memory_init();
boot_loader();
}
@@ -86,23 +99,22 @@ void init_other_hart()
{
hart_init();
- // wait until virtual memory is enabled
- while (*(pte_t* volatile*)&root_page_table == NULL)
+ // wait until hart 0 discovers us
+ while (*(csr_t * volatile *)&HLS()->csrs == NULL)
;
- mb();
- write_csr(sptbr, (uintptr_t)root_page_table >> RISCV_PGSHIFT);
-
- // make sure hart 0 has discovered us
- assert(HLS()->csrs != NULL);
boot_other_hart();
}
-void prepare_supervisor_mode()
+void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack)
{
uintptr_t mstatus = read_csr(mstatus);
mstatus = INSERT_FIELD(mstatus, MSTATUS_MPP, PRV_S);
mstatus = INSERT_FIELD(mstatus, MSTATUS_MPIE, 0);
write_csr(mstatus, mstatus);
write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE);
+ write_csr(mepc, fn);
+ write_csr(sptbr, (uintptr_t)root_page_table >> RISCV_PGSHIFT);
+ asm volatile ("mv a0, %0; mv sp, %0; eret" : : "r" (stack));
+ __builtin_unreachable();
}
diff --git a/pk/mtrap.c b/machine/mtrap.c
index b64360e..6fc5476 100644
--- a/pk/mtrap.c
+++ b/machine/mtrap.c
@@ -1,7 +1,8 @@
#include "mtrap.h"
-#include "frontend.h"
#include "mcall.h"
-#include "vm.h"
+#include "htif.h"
+#include "atomic.h"
+#include "bits.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
@@ -68,6 +69,12 @@ void poweroff()
write_csr(mtohost, 1);
}
+void putstring(const char* s)
+{
+ while (*s)
+ mcall_console_putchar(*s++);
+}
+
void printm(const char* s, ...)
{
char buf[256];
@@ -77,8 +84,7 @@ void printm(const char* s, ...)
vsnprintf(buf, sizeof buf, s, vl);
va_end(vl);
- for (const char* p = buf; *p; p++)
- mcall_console_putchar(*p);
+ putstring(buf);
}
static void send_ipi(uintptr_t recipient, int event)
diff --git a/pk/mtrap.h b/machine/mtrap.h
index b6ea1df..139f359 100644
--- a/pk/mtrap.h
+++ b/machine/mtrap.h
@@ -1,7 +1,6 @@
-#ifndef _PK_MTRAP_H
-#define _PK_MTRAP_H
+#ifndef _RISCV_MTRAP_H
+#define _RISCV_MTRAP_H
-#include "bits.h"
#include "encoding.h"
#ifdef __riscv_atomic
@@ -29,6 +28,7 @@ static inline int xlen()
return read_const_csr(misa) < 0 ? 64 : 32;
}
+extern uintptr_t first_free_paddr;
extern uintptr_t mem_size;
extern uint32_t num_harts;
@@ -52,8 +52,6 @@ typedef struct {
#define IPI_FENCE_I 0x2
#define IPI_SFENCE_VM 0x4
-void hls_init(uint32_t hart_id, csr_t* csrs);
-
#define MACHINE_STACK_TOP() ({ \
register uintptr_t sp asm ("sp"); \
(void*)((sp + RISCV_PGSIZE) & -RISCV_PGSIZE); })
@@ -62,13 +60,25 @@ void hls_init(uint32_t hart_id, csr_t* csrs);
#define HLS() ((hls_t*)(MACHINE_STACK_TOP() - HLS_SIZE))
#define OTHER_HLS(id) ((hls_t*)((void*)HLS() + RISCV_PGSIZE * ((id) - read_const_csr(mhartid))))
+void hls_init(uint32_t hart_id, csr_t* csrs);
void parse_config_string();
void poweroff(void) __attribute((noreturn));
void printm(const char* s, ...);
+void putstring(const char* s);
#define assert(x) ({ if (!(x)) die("assertion failed: %s", #x); })
#define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(); })
#define printk(...) die("printk")
+void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack)
+ __attribute__((noreturn));
+void boot_loader();
+void boot_other_hart();
+
+static inline void wfi()
+{
+ asm volatile ("wfi" ::: "memory");
+}
+
#endif // !__ASSEMBLER__
#define MACHINE_STACK_SIZE RISCV_PGSIZE
diff --git a/pk/sbi.S b/machine/sbi.S
index cbea78a..cbea78a 100644
--- a/pk/sbi.S
+++ b/machine/sbi.S
diff --git a/pk/sbi.h b/machine/sbi.h
index 4e2fbd8..4e2fbd8 100644
--- a/pk/sbi.h
+++ b/machine/sbi.h
diff --git a/pk/sbi_entry.S b/machine/sbi_entry.S
index bfb0703..a37dd25 100644
--- a/pk/sbi_entry.S
+++ b/machine/sbi_entry.S
@@ -24,7 +24,7 @@ sbi_base:
# query_memory
.align 4
- j __sbi_query_memory
+ tail __sbi_query_memory
# console_putchar
.align 4
@@ -72,11 +72,11 @@ sbi_base:
# mask_interrupt
.align 4
- j __sbi_mask_interrupt
+ tail __sbi_mask_interrupt
# unmask_interrupt
.align 4
- j __sbi_unmask_interrupt
+ tail __sbi_unmask_interrupt
# remote_sfence_vm
.align 4
@@ -107,3 +107,5 @@ do_mcall:
ret
.align RISCV_PGSHIFT
+ .globl _sbi_end
+_sbi_end:
diff --git a/pk/sbi_impl.c b/machine/sbi_impl.c
index 4af0cd4..07844e0 100644
--- a/pk/sbi_impl.c
+++ b/machine/sbi_impl.c
@@ -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;
}
diff --git a/pk/unprivileged_memory.h b/machine/unprivileged_memory.h
index d03cc5e..d03cc5e 100644
--- a/pk/unprivileged_memory.h
+++ b/machine/unprivileged_memory.h
diff --git a/machine/vm.h b/machine/vm.h
new file mode 100644
index 0000000..f51c639
--- /dev/null
+++ b/machine/vm.h
@@ -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
diff --git a/pk/bbl.c b/pk/bbl.c
deleted file mode 100644
index 5ace350..0000000
--- a/pk/bbl.c
+++ /dev/null
@@ -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();
-}
diff --git a/pk/bits.h b/pk/bits.h
deleted file mode 100644
index 10f9df3..0000000
--- a/pk/bits.h
+++ /dev/null
@@ -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
diff --git a/pk/boot.h b/pk/boot.h
index d66cc11..d2a619d 100644
--- a/pk/boot.h
+++ b/pk/boot.h
@@ -5,7 +5,6 @@
#ifndef __ASSEMBLER__
-#include <stdint.h>
#include <stddef.h>
typedef struct {
@@ -14,28 +13,19 @@ typedef struct {
int is_supervisor;
size_t phdr;
size_t phdr_size;
- size_t first_free_paddr;
- size_t first_user_vaddr;
- size_t first_vaddr_after_user;
size_t bias;
size_t entry;
size_t brk_min;
size_t brk;
size_t brk_max;
size_t mmap_max;
- size_t stack_bottom;
size_t stack_top;
size_t t0;
} elf_info;
extern elf_info current;
-void prepare_supervisor_mode();
-void run_loaded_program(size_t argc, char** argv);
-void boot_loader();
-void boot_other_hart();
void load_elf(const char* fn, elf_info* info);
-void print_logo();
#endif // !__ASSEMBLER__
diff --git a/pk/elf.c b/pk/elf.c
index 7dc783a..7107d1c 100644
--- a/pk/elf.c
+++ b/pk/elf.c
@@ -1,9 +1,9 @@
// See LICENSE for license details.
-#include "file.h"
-#include "vm.h"
+#include "mmap.h"
#include "mtrap.h"
#include "boot.h"
+#include "bits.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <elf.h>
@@ -15,100 +15,55 @@ void load_elf(const char* fn, elf_info* info)
if (IS_ERR_VALUE(file))
goto fail;
- Elf64_Ehdr eh64;
- ssize_t ehdr_size = file_pread(file, &eh64, sizeof(eh64), 0);
- if (ehdr_size < (ssize_t)sizeof(eh64) ||
- !(eh64.e_ident[0] == '\177' && eh64.e_ident[1] == 'E' &&
- eh64.e_ident[2] == 'L' && eh64.e_ident[3] == 'F'))
+ Elf_Ehdr eh;
+ ssize_t ehdr_size = file_pread(file, &eh, sizeof(eh), 0);
+ if (ehdr_size < (ssize_t)sizeof(eh) ||
+ !(eh.e_ident[0] == '\177' && eh.e_ident[1] == 'E' &&
+ eh.e_ident[2] == 'L' && eh.e_ident[3] == 'F'))
goto fail;
- uintptr_t min_vaddr = -1, max_vaddr = 0;
-
- #define LOAD_ELF do { \
- eh = (typeof(eh))&eh64; \
- size_t phdr_size = eh->e_phnum*sizeof(*ph); \
- if (phdr_size > info->phdr_size) \
- goto fail; \
- ssize_t ret = file_pread(file, (void*)info->phdr, phdr_size, eh->e_phoff); \
- if (ret < (ssize_t)phdr_size) \
- goto fail; \
- info->phnum = eh->e_phnum; \
- info->phent = sizeof(*ph); \
- ph = (typeof(ph))info->phdr; \
- info->is_supervisor = (eh->e_entry >> (8*sizeof(eh->e_entry)-1)) != 0; \
- if (info->is_supervisor) \
- info->first_free_paddr = ROUNDUP(info->first_free_paddr, SUPERPAGE_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; \
- if (info->is_supervisor) \
- min_vaddr = ROUNDDOWN(min_vaddr, SUPERPAGE_SIZE); \
- else \
- min_vaddr = ROUNDDOWN(min_vaddr, RISCV_PGSIZE); \
- uintptr_t bias = 0; \
- if (info->is_supervisor || eh->e_type == ET_DYN) \
- bias = info->first_free_paddr - min_vaddr; \
- info->entry = eh->e_entry; \
- if (!info->is_supervisor) { \
- info->entry += bias; \
- min_vaddr += bias; \
- } \
- info->bias = bias; \
- int flags = MAP_FIXED | MAP_PRIVATE; \
- if (info->is_supervisor) \
- flags |= MAP_POPULATE; \
- 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 (info->is_supervisor) { \
- if (!__valid_user_range(vaddr - prepad, vaddr + ph[i].p_memsz)) \
- goto fail; \
- ret = file_pread(file, (void*)vaddr, ph[i].p_filesz, ph[i].p_offset); \
- if (ret < (ssize_t)ph[i].p_filesz) \
- goto fail; \
- memset((void*)vaddr - prepad, 0, prepad); \
- memset((void*)vaddr + ph[i].p_filesz, 0, ph[i].p_memsz - ph[i].p_filesz); \
- } else { \
- int flags2 = flags | (prepad ? MAP_POPULATE : 0); \
- if (__do_mmap(vaddr - prepad, ph[i].p_filesz + prepad, -1, flags2, file, ph[i].p_offset - prepad) != vaddr - prepad) \
- goto fail; \
- memset((void*)vaddr - prepad, 0, prepad); \
- size_t mapped = ROUNDUP(ph[i].p_filesz + prepad, RISCV_PGSIZE) - prepad; \
- if (ph[i].p_memsz > mapped) \
- if (__do_mmap(vaddr + mapped, ph[i].p_memsz - mapped, -1, flags|MAP_ANONYMOUS, 0, 0) != vaddr + mapped) \
- goto fail; \
- } \
- } \
- } \
- } while(0)
-
- if (IS_ELF64(eh64))
- {
-#ifndef __riscv64
- die("can't run 64-bit ELF on 32-bit arch");
-#endif
- Elf64_Ehdr* eh;
- Elf64_Phdr* ph;
- LOAD_ELF;
- }
- else if (IS_ELF32(eh64))
- {
#ifdef __riscv64
- die("can't run 32-bit ELF on 64-bit arch");
+ assert(IS_ELF64(eh));
+#else
+ assert(IS_ELF32(eh));
#endif
- Elf32_Ehdr* eh;
- Elf32_Phdr* ph;
- LOAD_ELF;
- }
- else
- goto fail;
- info->first_user_vaddr = min_vaddr;
- info->first_vaddr_after_user = ROUNDUP(max_vaddr - info->bias, RISCV_PGSIZE);
- info->brk_min = max_vaddr;
+ uintptr_t min_vaddr = -1;
+ size_t phdr_size = eh.e_phnum * sizeof(Elf_Phdr);
+ if (phdr_size > info->phdr_size)
+ goto fail;
+ ssize_t ret = file_pread(file, (void*)info->phdr, phdr_size, eh.e_phoff);
+ if (ret < (ssize_t)phdr_size)
+ goto fail;
+ info->phnum = eh.e_phnum;
+ info->phent = sizeof(Elf_Phdr);
+ Elf_Phdr* ph = (typeof(ph))info->phdr;
+ 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, RISCV_PGSIZE);
+ uintptr_t bias = 0;
+ if (eh.e_type == ET_DYN)
+ bias = first_free_paddr - min_vaddr;
+ min_vaddr += bias;
+ info->entry = eh.e_entry + bias;
+ int flags = MAP_FIXED | MAP_PRIVATE;
+ 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 > info->brk_min)
+ info->brk_min = vaddr + ph[i].p_memsz;
+ int flags2 = flags | (prepad ? MAP_POPULATE : 0);
+ if (__do_mmap(vaddr - prepad, ph[i].p_filesz + prepad, -1, flags2, file, ph[i].p_offset - prepad) != vaddr - prepad)
+ goto fail;
+ memset((void*)vaddr - prepad, 0, prepad);
+ size_t mapped = ROUNDUP(ph[i].p_filesz + prepad, RISCV_PGSIZE) - prepad;
+ if (ph[i].p_memsz > mapped)
+ if (__do_mmap(vaddr + mapped, ph[i].p_memsz - mapped, -1, flags|MAP_ANONYMOUS, 0, 0) != vaddr + mapped)
+ goto fail;
+ }
+ }
file_decref(file);
return;
diff --git a/pk/elf.h b/pk/elf.h
index a05ccf2..df876e9 100644
--- a/pk/elf.h
+++ b/pk/elf.h
@@ -12,6 +12,14 @@
#define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1)
#define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2)
+#ifdef __riscv64
+# define Elf_Ehdr Elf64_Ehdr
+# define Elf_Phdr Elf64_Phdr
+#else
+# define Elf_Ehdr Elf32_Ehdr
+# define Elf_Phdr Elf32_Phdr
+#endif
+
#define ET_EXEC 2
#define ET_DYN 3
diff --git a/pk/file.c b/pk/file.c
index e522685..9176f1a 100644
--- a/pk/file.c
+++ b/pk/file.c
@@ -1,11 +1,13 @@
// See LICENSE for license details.
-#include <string.h>
-#include <errno.h>
#include "file.h"
-#include "pk.h"
+#include "atomic.h"
+#include "mmap.h"
#include "frontend.h"
-#include "vm.h"
+#include "syscall.h"
+#include "pk.h"
+#include <string.h>
+#include <errno.h>
#define MAX_FDS 128
static file_t* fds[MAX_FDS];
diff --git a/pk/file.h b/pk/file.h
index c9f7ce4..3bf7f12 100644
--- a/pk/file.h
+++ b/pk/file.h
@@ -6,7 +6,6 @@
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>
-#include "atomic.h"
typedef struct file
{
diff --git a/pk/frontend.h b/pk/frontend.h
index 2cf5f81..5b9df31 100644
--- a/pk/frontend.h
+++ b/pk/frontend.h
@@ -6,18 +6,6 @@
#include <stdint.h>
#include <sys/stat.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)
-
void shutdown(int) __attribute__((noreturn));
long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4, long a5, long a6);
diff --git a/pk/handlers.c b/pk/handlers.c
index bc82b5d..1961852 100644
--- a/pk/handlers.c
+++ b/pk/handlers.c
@@ -3,7 +3,7 @@
#include "pk.h"
#include "config.h"
#include "syscall.h"
-#include "vm.h"
+#include "mmap.h"
static void handle_illegal_instruction(trapframe_t* tf)
{
@@ -31,7 +31,7 @@ static void handle_misaligned_fetch(trapframe_t* tf)
panic("Misaligned instruction access!");
}
-void handle_misaligned_store(trapframe_t* tf)
+static void handle_misaligned_store(trapframe_t* tf)
{
dump_tf(tf);
panic("Misaligned AMO!");
@@ -50,13 +50,13 @@ static void handle_fault_fetch(trapframe_t* tf)
segfault(tf, tf->badvaddr, "fetch");
}
-void handle_fault_load(trapframe_t* tf)
+static void handle_fault_load(trapframe_t* tf)
{
if (handle_page_fault(tf->badvaddr, PROT_READ) != 0)
segfault(tf, tf->badvaddr, "load");
}
-void handle_fault_store(trapframe_t* tf)
+static void handle_fault_store(trapframe_t* tf)
{
if (handle_page_fault(tf->badvaddr, PROT_WRITE) != 0)
segfault(tf, tf->badvaddr, "store");
diff --git a/pk/init.c b/pk/init.c
deleted file mode 100644
index 11e17bd..0000000
--- a/pk/init.c
+++ /dev/null
@@ -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], &current);
-
- run_loaded_program(argc, args.argv);
-}
diff --git a/pk/vm.c b/pk/mmap.c
index c29434d..2f6a202 100644
--- a/pk/vm.c
+++ b/pk/mmap.c
@@ -1,8 +1,8 @@
-#include "vm.h"
-#include "file.h"
+#include "mmap.h"
#include "atomic.h"
#include "pk.h"
#include "boot.h"
+#include "bits.h"
#include "mtrap.h"
#include <stdint.h>
#include <errno.h>
@@ -17,14 +17,15 @@ typedef struct {
} vmr_t;
#define MAX_VMR (RISCV_PGSIZE / sizeof(vmr_t))
-spinlock_t vm_lock = SPINLOCK_INIT;
+static spinlock_t vm_lock = SPINLOCK_INIT;
static vmr_t* vmrs;
-pte_t* root_page_table;
static uintptr_t first_free_page;
static size_t next_free_page;
static size_t free_pages;
+int have_vm = 1; // unless -p flag is given
+
static uintptr_t __page_alloc()
{
kassert(next_free_page != free_pages);
@@ -73,41 +74,6 @@ static size_t pte_ppn(pte_t pte)
return pte >> PTE_PPN_SHIFT;
}
-static pte_t ptd_create(uintptr_t ppn)
-{
- return (ppn << PTE_PPN_SHIFT) | PTE_V | PTE_TYPE_TABLE;
-}
-
-static inline pte_t pte_create(uintptr_t ppn, int prot, int user)
-{
- pte_t pte = (ppn << PTE_PPN_SHIFT) | PTE_V;
- prot &= PROT_READ|PROT_WRITE|PROT_EXEC;
- if (user) {
- switch (prot) {
- case PROT_NONE: pte |= PTE_TYPE_SR; break;
- case PROT_READ: pte |= PTE_TYPE_UR_SR; break;
- case PROT_WRITE: pte |= PTE_TYPE_URW_SRW; break;
- case PROT_EXEC: pte |= PTE_TYPE_URX_SRX; break;
- case PROT_READ|PROT_WRITE: pte |= PTE_TYPE_URW_SRW; break;
- case PROT_READ|PROT_EXEC: pte |= PTE_TYPE_URX_SRX; break;
- case PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_URWX_SRWX; break;
- case PROT_READ|PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_URWX_SRWX; break;
- }
- } else {
- switch (prot) {
- case PROT_NONE: kassert(0); break;
- case PROT_READ: pte |= PTE_TYPE_SR; break;
- case PROT_WRITE: pte |= PTE_TYPE_SRW; break;
- case PROT_EXEC: pte |= PTE_TYPE_SRX; break;
- case PROT_READ|PROT_WRITE: pte |= PTE_TYPE_SRW; break;
- case PROT_READ|PROT_EXEC: pte |= PTE_TYPE_SRX; break;
- case PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_SRWX; break;
- case PROT_READ|PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_SRWX; break;
- }
- }
- return pte;
-}
-
static uintptr_t ppn(uintptr_t addr)
{
return addr >> RISCV_PGSHIFT;
@@ -119,27 +85,19 @@ static size_t pt_idx(uintptr_t addr, int level)
return idx & ((1 << RISCV_PGLEVEL_BITS) - 1);
}
-static void __maybe_create_root_page_table()
+static pte_t* __maybe_create_root_page_table()
{
- if (root_page_table)
- return;
- root_page_table = (void*)__page_alloc();
- if (have_vm)
- write_csr(sptbr, (uintptr_t)root_page_table >> RISCV_PGSHIFT);
+ if (!root_page_table)
+ root_page_table = (void*)__page_alloc();
+ return root_page_table;
}
static pte_t* __walk_internal(uintptr_t addr, int create)
{
- const size_t pte_per_page = RISCV_PGSIZE/sizeof(void*);
- __maybe_create_root_page_table();
- pte_t* t = root_page_table;
- unsigned levels = (VA_BITS - RISCV_PGSHIFT) / RISCV_PGLEVEL_BITS;
-
- for (unsigned i = levels-1; i > 0; i--)
- {
+ pte_t* t = __maybe_create_root_page_table();
+ for (int i = (VA_BITS - RISCV_PGSHIFT) / RISCV_PGLEVEL_BITS - 1; i > 0; i--) {
size_t idx = pt_idx(addr, i);
- if (!(t[idx] & PTE_V))
- {
+ if (!(t[idx] & PTE_V)) {
if (!create)
return 0;
uintptr_t page = __page_alloc();
@@ -185,11 +143,40 @@ static uintptr_t __vm_alloc(size_t npage)
return 0;
}
+static inline pte_t prot_to_type(int prot, int user)
+{
+ prot &= PROT_READ|PROT_WRITE|PROT_EXEC;
+ if (user) {
+ switch (prot) {
+ case PROT_NONE: return PTE_TYPE_SR;
+ case PROT_READ: return PTE_TYPE_UR_SR;
+ case PROT_WRITE: return PTE_TYPE_URW_SRW;
+ case PROT_EXEC: return PTE_TYPE_URX_SRX;
+ case PROT_READ|PROT_WRITE: return PTE_TYPE_URW_SRW;
+ case PROT_READ|PROT_EXEC: return PTE_TYPE_URX_SRX;
+ case PROT_WRITE|PROT_EXEC: return PTE_TYPE_URWX_SRWX;
+ case PROT_READ|PROT_WRITE|PROT_EXEC: return PTE_TYPE_URWX_SRWX;
+ }
+ } else {
+ switch (prot) {
+ case PROT_NONE:
+ case PROT_READ: return PTE_TYPE_SR;
+ case PROT_WRITE: return PTE_TYPE_SRW;
+ case PROT_EXEC: return PTE_TYPE_SRX;
+ case PROT_READ|PROT_WRITE: return PTE_TYPE_SRW;
+ case PROT_READ|PROT_EXEC: return PTE_TYPE_SRX;
+ case PROT_WRITE|PROT_EXEC: return PTE_TYPE_SRWX;
+ case PROT_READ|PROT_WRITE|PROT_EXEC: return PTE_TYPE_SRWX;
+ }
+ }
+ __builtin_unreachable();
+}
+
int __valid_user_range(uintptr_t vaddr, size_t len)
{
if (vaddr + len < vaddr)
return 0;
- return vaddr >= current.first_free_paddr && vaddr + len <= current.mmap_max;
+ return vaddr >= first_free_paddr && vaddr + len <= current.mmap_max;
}
static int __handle_page_fault(uintptr_t vaddr, int prot)
@@ -206,7 +193,7 @@ static int __handle_page_fault(uintptr_t vaddr, int prot)
uintptr_t ppn = vpn;
vmr_t* v = (vmr_t*)*pte;
- *pte = pte_create(ppn, PROT_READ|PROT_WRITE, 0);
+ *pte = pte_create(ppn, prot_to_type(PROT_READ|PROT_WRITE, 0));
flush_tlb();
if (v->file)
{
@@ -219,10 +206,10 @@ static int __handle_page_fault(uintptr_t vaddr, int prot)
else
memset((void*)vaddr, 0, RISCV_PGSIZE);
__vmr_decref(v, 1);
- *pte = pte_create(ppn, v->prot, 1);
+ *pte = pte_create(ppn, prot_to_type(v->prot, 1));
}
- pte_t perms = pte_create(0, prot, 1);
+ pte_t perms = pte_create(0, prot_to_type(prot, 1));
if ((*pte & perms) != perms)
return -1;
@@ -384,7 +371,7 @@ uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot)
res = -EACCES;
break;
}
- *pte = pte_create(pte_ppn(*pte), prot, 1);
+ *pte = pte_create(pte_ppn(*pte), prot_to_type(prot, 1));
}
}
spinlock_unlock(&vm_lock);
@@ -395,11 +382,12 @@ uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot)
void __map_kernel_range(uintptr_t vaddr, uintptr_t paddr, size_t len, int prot)
{
uintptr_t n = ROUNDUP(len, RISCV_PGSIZE) / RISCV_PGSIZE;
+ uintptr_t offset = paddr - vaddr;
for (uintptr_t a = vaddr, i = 0; i < n; i++, a += RISCV_PGSIZE)
{
pte_t* pte = __walk_create(a);
kassert(pte);
- *pte = pte_create((a - vaddr + paddr) >> RISCV_PGSHIFT, prot, 0);
+ *pte = pte_create((a + offset) >> RISCV_PGSHIFT, prot_to_type(prot, 0));
}
}
@@ -415,85 +403,23 @@ void populate_mapping(const void* start, size_t size, int prot)
}
}
-static uintptr_t sbi_top_paddr()
-{
- extern char _end;
- return ROUNDUP((uintptr_t)&_end, RISCV_PGSIZE);
-}
-
-#define first_free_paddr() (sbi_top_paddr() + num_harts * RISCV_PGSIZE)
-
-void vm_init()
+uintptr_t pk_vm_init()
{
- mem_size = mem_size / SUPERPAGE_SIZE * SUPERPAGE_SIZE;
- current.first_free_paddr = first_free_paddr();
-
size_t mem_pages = mem_size >> RISCV_PGSHIFT;
free_pages = MAX(8, mem_pages >> (RISCV_PGLEVEL_BITS-1));
first_free_page = mem_size - free_pages * RISCV_PGSIZE;
- current.mmap_max = current.brk_max = first_free_page;
-}
-void supervisor_vm_init()
-{
- uintptr_t highest_va = -current.first_free_paddr;
- mem_size = MIN(mem_size, highest_va - current.first_user_vaddr) & -SUPERPAGE_SIZE;
-
- pte_t* sbi_pt = (pte_t*)(current.first_vaddr_after_user + current.bias);
- 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 = (-current.first_user_vaddr - 1) / MEGAPAGE_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 = current.first_user_vaddr, paddr = vaddr + current.bias, end = current.first_vaddr_after_user;
- paddr < mem_size; vaddr += SUPERPAGE_SIZE, paddr += SUPERPAGE_SIZE) {
- int l2_shift = RISCV_PGLEVEL_BITS + RISCV_PGSHIFT;
- size_t l2_idx = (current.first_user_vaddr >> l2_shift) & ((1 << RISCV_PGLEVEL_BITS)-1);
- l2_idx += ((vaddr - current.first_user_vaddr) >> l2_shift);
- middle_pt[l2_idx] = pte_create(paddr >> RISCV_PGSHIFT, PROT_READ|PROT_WRITE|PROT_EXEC, 0);
- }
- current.first_vaddr_after_user += (void*)root_pt + RISCV_PGSIZE - (void*)sbi_pt;
-
- // map SBI at top of vaddr space
- uintptr_t num_sbi_pages = sbi_top_paddr() / RISCV_PGSIZE;
- 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, PROT_READ|PROT_EXEC, 0);
- }
- pte_t* sbi_pte = middle_pt + ((num_middle_pts << RISCV_PGLEVEL_BITS)-1);
- kassert(!*sbi_pte);
- *sbi_pte = ptd_create((uintptr_t)sbi_pt >> RISCV_PGSHIFT);
-
- // disable our allocator
- kassert(next_free_page == 0);
- free_pages = 0;
-
- mb();
- root_page_table = root_pt;
- write_csr(sptbr, (uintptr_t)root_pt >> RISCV_PGSHIFT);
-}
+ __map_kernel_range(0, 0, first_free_paddr, PROT_READ|PROT_WRITE|PROT_EXEC);
+ __map_kernel_range(first_free_page, first_free_page, free_pages * RISCV_PGSIZE, PROT_READ|PROT_WRITE);
-uintptr_t pk_vm_init()
-{
// keep user addresses positive
- current.mmap_max = MIN(current.mmap_max, (uintptr_t)INTPTR_MAX + 1);
-
- __map_kernel_range(0, 0, current.first_free_paddr, PROT_READ|PROT_WRITE|PROT_EXEC);
- __map_kernel_range(first_free_page, first_free_page, free_pages * RISCV_PGSIZE, PROT_READ|PROT_WRITE);
+ current.mmap_max = MIN(first_free_page, (uintptr_t)INTPTR_MAX + 1);
+ current.brk_max = current.mmap_max;
size_t stack_size = RISCV_PGSIZE * CLAMP(mem_size/(RISCV_PGSIZE*32), 1, 256);
- current.stack_bottom = __do_mmap(current.mmap_max - stack_size, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
- current.stack_top = current.stack_bottom + stack_size;
- kassert(current.stack_bottom != (uintptr_t)-1);
+ size_t stack_bottom = __do_mmap(current.mmap_max - stack_size, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
+ kassert(stack_bottom != (uintptr_t)-1);
+ current.stack_top = stack_bottom + stack_size;
uintptr_t kernel_stack_top = __page_alloc() + RISCV_PGSIZE;
return kernel_stack_top;
diff --git a/pk/vm.h b/pk/mmap.h
index c05a1ce..e3c2035 100644
--- a/pk/vm.h
+++ b/pk/mmap.h
@@ -1,21 +1,11 @@
-#ifndef _VM_H
-#define _VM_H
+#ifndef _MMAP_H
+#define _MMAP_H
+#include "vm.h"
#include "syscall.h"
+#include "encoding.h"
#include "file.h"
-#include <string.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#define SUPERPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS))
-#ifdef __riscv64
-# define VM_CHOICE VM_SV39
-# define VA_BITS 39
-# define MEGAPAGE_SIZE (SUPERPAGE_SIZE << RISCV_PGLEVEL_BITS)
-#else
-# define VM_CHOICE VM_SV32
-# define VA_BITS 32
-#endif
+#include <stddef.h>
#define PROT_NONE 0
#define PROT_READ 1
@@ -28,8 +18,7 @@
#define MAP_POPULATE 0x8000
#define MREMAP_FIXED 0x2
-void vm_init();
-void supervisor_vm_init();
+extern int have_vm;
uintptr_t pk_vm_init();
int handle_page_fault(uintptr_t vaddr, int prot);
void populate_mapping(const void* start, size_t size, int prot);
@@ -42,12 +31,4 @@ uintptr_t do_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags)
uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot);
uintptr_t do_brk(uintptr_t addr);
-typedef uintptr_t pte_t;
-extern pte_t* root_page_table;
-
-static inline void flush_tlb()
-{
- asm volatile("sfence.vm");
-}
-
#endif
diff --git a/pk/pk.ac b/pk/pk.ac
index aa0c669..f846905 100644
--- a/pk/pk.ac
+++ b/pk/pk.ac
@@ -2,13 +2,3 @@ AC_ARG_ENABLE([vm], AS_HELP_STRING([--disable-vm], [Disable virtual memory]))
AS_IF([test "x$enable_vm" != "xno"], [
AC_DEFINE([PK_ENABLE_VM],,[Define if virtual memory support is enabled])
])
-
-AC_ARG_ENABLE([vm], 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_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])
-])
diff --git a/pk/pk.c b/pk/pk.c
index 6318963..2737048 100644
--- a/pk/pk.c
+++ b/pk/pk.c
@@ -1,24 +1,66 @@
#include "pk.h"
+#include "mmap.h"
#include "boot.h"
-#include "vm.h"
#include "elf.h"
+#include "mtrap.h"
+#include "frontend.h"
-void run_loaded_program(size_t argc, char** argv)
+elf_info current;
+
+int uarch_counters_enabled;
+long uarch_counters[NUM_COUNTERS];
+char* uarch_counter_names[NUM_COUNTERS];
+
+static void handle_option(const char* s)
{
- if (current.is_supervisor)
- panic("pk can't run kernel binaries; try using bbl instead");
+ switch (s[1])
+ {
+ case 's': // print cycle count upon termination
+ current.t0 = 1;
+ break;
- uintptr_t kernel_stack_top = pk_vm_init();
+ 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;
- extern char trap_entry;
- write_csr(stvec, &trap_entry);
- write_csr(sscratch, 0);
- clear_csr(sie, SIP_STIP | SIP_SSIP);
+ default:
+ panic("unrecognized option: `%c'", s[1]);
+ break;
+ }
+}
- // enter supervisor mode
- prepare_supervisor_mode();
- asm volatile("la t0, 1f; csrw mepc, t0; eret; 1:" ::: "t0");
+#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;
+}
+
+static 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 run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top)
+{
// copy phdrs to user stack
size_t stack_top = current.stack_top - current.phdr_size;
memcpy((void*)stack_top, (void*)current.phdr, current.phdr_size);
@@ -94,10 +136,37 @@ void run_loaded_program(size_t argc, char** argv)
trapframe_t tf;
init_tf(&tf, current.entry, stack_top);
__clear_cache(0, 0);
- write_csr(sscratch, kernel_stack_top);
+ write_csr(sscratch, kstack_top);
start_user(&tf);
}
+static void rest_of_boot_loader(uintptr_t kstack_top)
+{
+ 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], &current);
+
+ run_loaded_program(argc, args.argv, kstack_top);
+}
+
+void boot_loader()
+{
+ extern char trap_entry;
+ write_csr(stvec, &trap_entry);
+ write_csr(sscratch, 0);
+ write_csr(sie, 0);
+
+ file_init();
+ enter_supervisor_mode(rest_of_boot_loader, pk_vm_init());
+}
+
void boot_other_hart()
{
// stall all harts besides hart 0
diff --git a/pk/pk.h b/pk/pk.h
index 280ad6a..c86d596 100644
--- a/pk/pk.h
+++ b/pk/pk.h
@@ -24,30 +24,18 @@ typedef struct
#define kassert(cond) do { if(!(cond)) kassert_fail(""#cond); } while(0)
void do_panic(const char* s, ...) __attribute__((noreturn));
void kassert_fail(const char* s) __attribute__((noreturn));
-#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)
#ifdef __cplusplus
extern "C" {
#endif
-extern int have_vm;
-
void printk(const char* s, ...);
void printm(const char* s, ...);
int vsnprintf(char* out, size_t n, const char* s, va_list vl);
int snprintf(char* out, size_t n, const char* s, ...);
-void init_tf(trapframe_t*, long pc, long sp);
void start_user(trapframe_t* tf) __attribute__((noreturn));
void dump_tf(trapframe_t*);
-void unhandled_trap(trapframe_t*);
-void handle_misaligned_load(trapframe_t*);
-void handle_misaligned_store(trapframe_t*);
-void handle_fault_load(trapframe_t*);
-void handle_fault_store(trapframe_t*);
-
static inline int insn_len(long insn)
{
return (insn & 0x3) < 0x3 ? 2 : 4;
@@ -60,11 +48,6 @@ extern int uarch_counters_enabled;
extern long uarch_counters[NUM_COUNTERS];
extern char* uarch_counter_names[NUM_COUNTERS];
-static inline void wfi()
-{
- asm volatile ("wfi" ::: "memory");
-}
-
#ifdef __cplusplus
}
#endif
diff --git a/pk/pk.ld b/pk/pk.lds
index 77ba6cf..0897e50 100644
--- a/pk/pk.ld
+++ b/pk/pk.lds
@@ -86,10 +86,5 @@ SECTIONS
*(COMMON)
}
- .sbi :
- {
- sbi.o(.sbi)
- }
-
_end = .;
}
diff --git a/pk/pk.mk.in b/pk/pk.mk.in
index 78f826e..3caa25d 100644
--- a/pk/pk.mk.in
+++ b/pk/pk.mk.in
@@ -1,52 +1,30 @@
pk_subproject_deps = \
+ util \
softfloat \
+ machine \
pk_hdrs = \
- atomic.h \
- bits.h \
boot.h \
elf.h \
- emulation.h \
- encoding.h \
file.h \
- fp_emulation.h \
frontend.h \
- mcall.h \
- mtrap.h \
+ mmap.h \
pk.h \
- sbi.h \
syscall.h \
- unprivileged_memory.h \
- vm.h \
pk_c_srcs = \
- snprintf.c \
- mtrap.c \
- minit.c \
- emulation.c \
- fp_emulation.c \
- sbi_impl.c \
- init.c \
file.c \
syscall.c \
handlers.c \
frontend.c \
elf.c \
console.c \
- vm.c \
- string.c \
- logo.c \
- configstring.c \
+ mmap.c \
pk_asm_srcs = \
- mentry.S \
entry.S \
- fp_asm.S \
- sbi_entry.S \
- sbi.S \
pk_test_srcs =
pk_install_prog_srcs = \
pk.c \
- bbl.c \
diff --git a/pk/syscall.c b/pk/syscall.c
index 17112d8..de11a0a 100644
--- a/pk/syscall.c
+++ b/pk/syscall.c
@@ -4,7 +4,7 @@
#include "pk.h"
#include "file.h"
#include "frontend.h"
-#include "vm.h"
+#include "mmap.h"
#include "boot.h"
#include <string.h>
#include <errno.h>
diff --git a/pk/snprintf.c b/util/snprintf.c
index 1544a6c..1544a6c 100644
--- a/pk/snprintf.c
+++ b/util/snprintf.c
diff --git a/pk/string.c b/util/string.c
index e896379..e896379 100644
--- a/pk/string.c
+++ b/util/string.c
diff --git a/util/util.ac b/util/util.ac
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/util/util.ac
diff --git a/util/util.mk.in b/util/util.mk.in
new file mode 100644
index 0000000..abbdbd1
--- /dev/null
+++ b/util/util.mk.in
@@ -0,0 +1,9 @@
+util_subproject_deps = \
+
+util_hdrs = \
+
+util_c_srcs = \
+ snprintf.c \
+ string.c \
+
+util_asm_srcs = \