From 6c95eb9affad7d20068d37bd4287a784baa1e5ae Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Fri, 12 May 2017 10:35:33 +0200 Subject: [PATCH] base-hw: RISC-V BBL The Berkley Boot Loader handles kernel loading and machine mode --- repos/base-hw/lib/mk/spec/riscv/core-hw.mk | 2 +- repos/base-hw/ports/bbl.hash | 1 + repos/base-hw/ports/bbl.port | 8 +++ repos/base-hw/src/bbl/ctype.h | 0 repos/base-hw/src/bbl/dummy | 0 repos/base-hw/src/bbl/errno.h | 8 +++ repos/base-hw/src/bbl/image.S | 9 +++ repos/base-hw/src/bbl/limits.h | 8 +++ repos/base-hw/src/bbl/payload.S | 7 +++ repos/base-hw/src/bbl/stdint.h | 15 +++++ repos/base-hw/src/bbl/stdio.h | 6 ++ repos/base-hw/src/bbl/string.h | 9 +++ repos/base-hw/src/bbl/target.mk | 33 +++++++++++ repos/base-hw/src/bootstrap/spec/riscv/crt0.s | 2 +- .../bootstrap/spec/riscv/exception_vector.s | 57 ++++++++----------- .../src/bootstrap/spec/riscv/platform.cc | 44 ++++++++------ repos/base-hw/src/core/spec/riscv/cpu.h | 25 +++++--- .../src/lib/hw/spec/riscv/machine_call.h | 6 +- tool/builddir/build.conf/run_opt_spike | 2 +- tool/run/image/bbl | 6 ++ 20 files changed, 182 insertions(+), 66 deletions(-) create mode 100644 repos/base-hw/ports/bbl.hash create mode 100644 repos/base-hw/ports/bbl.port create mode 100644 repos/base-hw/src/bbl/ctype.h create mode 100644 repos/base-hw/src/bbl/dummy create mode 100644 repos/base-hw/src/bbl/errno.h create mode 100644 repos/base-hw/src/bbl/image.S create mode 100644 repos/base-hw/src/bbl/limits.h create mode 100644 repos/base-hw/src/bbl/payload.S create mode 100644 repos/base-hw/src/bbl/stdint.h create mode 100644 repos/base-hw/src/bbl/stdio.h create mode 100644 repos/base-hw/src/bbl/string.h create mode 100644 repos/base-hw/src/bbl/target.mk create mode 100644 tool/run/image/bbl diff --git a/repos/base-hw/lib/mk/spec/riscv/core-hw.mk b/repos/base-hw/lib/mk/spec/riscv/core-hw.mk index bdfe8f45b..e62d655b2 100644 --- a/repos/base-hw/lib/mk/spec/riscv/core-hw.mk +++ b/repos/base-hw/lib/mk/spec/riscv/core-hw.mk @@ -12,7 +12,7 @@ SRC_CC += spec/riscv/kernel/cpu.cc SRC_CC += spec/riscv/platform_support.cc #add assembly sources -SRC_S += spec/riscv/mode_transition.s +SRC_S += $(REP_DIR)/src/bootstrap/spec/riscv/exception_vector.s SRC_S += spec/riscv/crt0.s # include less specific configuration diff --git a/repos/base-hw/ports/bbl.hash b/repos/base-hw/ports/bbl.hash new file mode 100644 index 000000000..2d7612f93 --- /dev/null +++ b/repos/base-hw/ports/bbl.hash @@ -0,0 +1 @@ +65cc50461e5e1c4d89f8e41dce69362023f445d7 diff --git a/repos/base-hw/ports/bbl.port b/repos/base-hw/ports/bbl.port new file mode 100644 index 000000000..ff0e23c75 --- /dev/null +++ b/repos/base-hw/ports/bbl.port @@ -0,0 +1,8 @@ +LICENSE := BSD-3-Clause +VERSION := git +DOWNLOADS := bbl.git + +URL(bbl) = https://github.com/ssumpf/bbl-lite.git +REV(bbl) = b24944dde265016ff9b3c8608fe5cc24994e360a +DIR(bbl) = src/lib/bbl + diff --git a/repos/base-hw/src/bbl/ctype.h b/repos/base-hw/src/bbl/ctype.h new file mode 100644 index 000000000..e69de29bb diff --git a/repos/base-hw/src/bbl/dummy b/repos/base-hw/src/bbl/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/repos/base-hw/src/bbl/errno.h b/repos/base-hw/src/bbl/errno.h new file mode 100644 index 000000000..8bc189cf2 --- /dev/null +++ b/repos/base-hw/src/bbl/errno.h @@ -0,0 +1,8 @@ +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +enum { + ENOSYS = 38, +}; + +#endif /* _ERRNO_H_ */ diff --git a/repos/base-hw/src/bbl/image.S b/repos/base-hw/src/bbl/image.S new file mode 100644 index 000000000..3b57e11a5 --- /dev/null +++ b/repos/base-hw/src/bbl/image.S @@ -0,0 +1,9 @@ +.section ".payload","a",@progbits +.align 3 + +.globl _payload_start, _payload_end +_payload_start: +#ifdef BBL_PAYLOAD +.incbin BBL_PAYLOAD +#endif +_payload_end: diff --git a/repos/base-hw/src/bbl/limits.h b/repos/base-hw/src/bbl/limits.h new file mode 100644 index 000000000..a77ad41fb --- /dev/null +++ b/repos/base-hw/src/bbl/limits.h @@ -0,0 +1,8 @@ +#ifndef _LIMITS_H_ +#define _LIMITS_H_ + +enum { + ULONG_MAX = ~0UL +}; + +#endif /* _LIMITS_H_ */ diff --git a/repos/base-hw/src/bbl/payload.S b/repos/base-hw/src/bbl/payload.S new file mode 100644 index 000000000..7ff1e589d --- /dev/null +++ b/repos/base-hw/src/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/repos/base-hw/src/bbl/stdint.h b/repos/base-hw/src/bbl/stdint.h new file mode 100644 index 000000000..9f777c5a1 --- /dev/null +++ b/repos/base-hw/src/bbl/stdint.h @@ -0,0 +1,15 @@ +#ifndef _STDINT_H_ +#define _STDINT_H_ + +typedef unsigned long uintptr_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned uint32_t; +typedef unsigned long long uint64_t; +typedef signed long long int64_t; + +typedef signed long ssize_t; +typedef unsigned long size_t; + +#endif /* _STDINT_H_ */ diff --git a/repos/base-hw/src/bbl/stdio.h b/repos/base-hw/src/bbl/stdio.h new file mode 100644 index 000000000..e8d5e5b5d --- /dev/null +++ b/repos/base-hw/src/bbl/stdio.h @@ -0,0 +1,6 @@ +#ifndef _STDIO_H_ +#define _STDIO_H_ + +typedef unsigned long long uint64_t; + +#endif /* _STDIO_H_ */ diff --git a/repos/base-hw/src/bbl/string.h b/repos/base-hw/src/bbl/string.h new file mode 100644 index 000000000..47693f0e0 --- /dev/null +++ b/repos/base-hw/src/bbl/string.h @@ -0,0 +1,9 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include + +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, const void *src, size_t n); + +#endif /* _STRING_H_ */ diff --git a/repos/base-hw/src/bbl/target.mk b/repos/base-hw/src/bbl/target.mk new file mode 100644 index 000000000..b9e3b5cd5 --- /dev/null +++ b/repos/base-hw/src/bbl/target.mk @@ -0,0 +1,33 @@ +TARGET = bbl +REQUIRES = riscv + +SRC_C = bbl.c \ + configstring.c \ + kernel_elf.c \ + logo.c \ + mtrap.c \ + minit.c \ + sbi_impl.c \ + snprintf.c \ + string.c \ + mentry.S \ + sbi_entry.S \ + sbi.S \ + image.S + +IMAGE_ELF ?= $(PRG_DIR)/dummy + +INC_DIR += $(PRG_DIR) + +CC_OPT_PIC = +CC_C_OPT += -mcmodel=medany +CC_OPT_image += -DBBL_PAYLOAD=\"$(IMAGE_ELF)\" + +LD_TEXT_ADDR = 0x80000000 + +CONTRIB = $(call select_from_ports,bbl)/src/lib/bbl/bbl + +LD_SCRIPT_STATIC = $(CONTRIB)/bbl.lds + +vpath %.c $(CONTRIB) +vpath %.S $(CONTRIB) diff --git a/repos/base-hw/src/bootstrap/spec/riscv/crt0.s b/repos/base-hw/src/bootstrap/spec/riscv/crt0.s index b09f6e270..2688c6c44 100644 --- a/repos/base-hw/src/bootstrap/spec/riscv/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/riscv/crt0.s @@ -34,7 +34,7 @@ addi a0, a0, 8 bne a0, a1, 1b la sp, _stack_area_start -la a0, STACK_SIZE +li a0, STACK_SIZE ld a0, (a0) add sp, sp, a0 diff --git a/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.s b/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.s index a3a25f0cc..6493e341f 100644 --- a/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.s +++ b/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.s @@ -18,14 +18,13 @@ .set CALL_PUT_CHAR, 0x100 .set CALL_SET_SYS_TIMER, 0x101 -.set CALL_IS_USER_MODE, 0x102 +.set CALL_GET_SYS_TIMER, 0x102 .set CPU_IP, 0 .set CPU_EXCEPTION, 8 .set CPU_X1, 2*8 .set CPU_SP, 3*8 -.set CPU_SASID, 33*8 -.set CPU_SPTBR, 34*8 +.set CPU_SPTBR, 33*8 # From encoding.h (riscv-opcode) @@ -120,21 +119,20 @@ # If irq from supervisor and MSTATUS.IE1 is not set, # then bail out using 'eret' # - .if \mode == SUPERVISOR_MODE + .if \mode == SUPERVISOR_MODE csrr t1, mstatus and t0, t1, MSTATUS_IE1 bne zero, t0, 1f # So, IE1 is not set. _restore_scratch_registers \mode - eret - - .endif + mret + .endif 1: # should cause a interrupt trap in supervisor mode _restore_scratch_registers \mode - mrts +# mrts 2: # If interrupt source is IRQ HOST .... li t1, IRQ_HOST * 2 @@ -143,7 +141,7 @@ 3: # Empty mfromhost li t0, 0 - csrrw t0, mfromhost, t0 + #csrrw t0, mfromhost, t0 bne zero,t0, 3b j 9f @@ -153,7 +151,7 @@ 9: #******** IRQ OUT ********* _restore_scratch_registers \mode - eret + mret 11: # Handle trap @@ -179,7 +177,7 @@ li t1, CALL_SET_SYS_TIMER beq t1, a0, 13f - li t1, CALL_IS_USER_MODE + li t1, CALL_GET_SYS_TIMER beq t1, a0, 14f # else, unknown ecall number @@ -187,17 +185,17 @@ # Assume that Genode (supervisor trap handler) # knows what to do then. _restore_scratch_registers \mode - mrts + # mrts .endif j 15f 12: # output character but first wait until mtohost reads 0 atomically # to make sure any previous character is gone.. - csrr t1, mtohost + #csrr t1, mtohost bne zero, t1, 12b - csrw mtohost, a1 + #csrw mtohost, a1 j 15f 13: @@ -208,7 +206,7 @@ csrc mip, t0 # Set system timer - csrw mtimecmp, a1 + #csrw mtimecmp, a1 # enable timer interrupt in M-mode li t0, MIP_MTIP @@ -217,17 +215,16 @@ j 15f 14: - mv a0, x0 - .if \mode == USER_MODE - li a0, 1 + .if \mode == SUPERVISOR_MODE + #csrr a0, mtime .endif j 15f 15: #******* ECALL OUT ********* - # Empty mfromhost + # Empty mfromhost li t0, 0 - csrrw t0, mfromhost, t0 + #csrrw t0, mfromhost, t0 bne zero,t0, 14b # advance epc @@ -236,7 +233,7 @@ csrw mepc, t0 _restore_scratch_registers \mode - eret + mret 19: .endm @@ -278,7 +275,7 @@ user_trap: _save_scratch_registers USER_MODE _handle_trap USER_MODE _restore_scratch_registers USER_MODE - mrts +# mrts supervisor_trap: @@ -340,15 +337,11 @@ _mt_kernel_entry_pic: csrrw x31, sscratch, x31 addi x31, x31, 8 - # save x29, x30 in master - sd x29, CPU_X1 + 8 * 28(x31) - sd x30, CPU_X1 + 8 * 29(x31) + # save x30 in master + sd x30, CPU_X1 + 8 * 28(x31) # load kernel page table - ld x29, CPU_SASID(x31) ld x30, CPU_SPTBR(x31) - - csrw sasid, x29 csrw sptbr, x30 # @@ -421,11 +414,9 @@ _mt_user_entry_pic: .endr # switch page table - ld x31, CPU_SASID(x30) - ld x30, CPU_SPTBR(x30) + ld x31, CPU_SPTBR(x30) - csrw sasid, x31 - csrw sptbr, x30 + csrw sptbr, x31 # # FIXME @@ -440,7 +431,7 @@ _mt_user_entry_pic: ld x\reg, CPU_X1 + 8 * (\reg - 1)(x29) .endr - eret + sret # end of the mode transition code .global _mt_end diff --git a/repos/base-hw/src/bootstrap/spec/riscv/platform.cc b/repos/base-hw/src/bootstrap/spec/riscv/platform.cc index 3c3136eef..a41fbadbd 100644 --- a/repos/base-hw/src/bootstrap/spec/riscv/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/riscv/platform.cc @@ -29,32 +29,40 @@ void Bootstrap::Platform::enable_mmu() SUPERVISOR = 1, Sv39 = 9, }; - struct Ie : Bitfield<0, 1> { }; - struct Priv : Bitfield<1, 2> { }; - struct Ie1 : Bitfield<3, 1> { }; - struct Priv1 : Bitfield<4, 2> { }; - struct Fs : Bitfield<12, 2> { enum { INITIAL = 1 }; }; - struct Vm : Bitfield<17, 5> { }; + struct Uie : Bitfield<0, 1> { }; + struct Sie : Bitfield<1, 1> { }; + struct Upie : Bitfield<4, 1> { }; + struct Spie : Bitfield<5, 1> { }; + struct Spp : Bitfield<8, 1> { }; + struct Mpp : Bitfield<11, 2> { }; + + + struct Fs : Bitfield<13, 2> { enum { INITIAL = 1 }; }; + struct Vm : Bitfield<24, 5> { }; }; /* read status register */ Mstatus::access_t mstatus = 0; - Mstatus::Vm::set(mstatus, Mstatus::Sv39); /* enable Sv39 paging */ - Mstatus::Fs::set(mstatus, Mstatus::Fs::INITIAL); /* enable FPU */ - Mstatus::Ie1::set(mstatus, 1); /* user mode interrupt */ - Mstatus::Priv1::set(mstatus, Mstatus::USER); /* set user mode */ - Mstatus::Ie::set(mstatus, 0); /* disable interrupts */ - Mstatus::Priv::set(mstatus, Mstatus::SUPERVISOR); /* set supervisor mode */ + Mstatus::Vm::set(mstatus, Mstatus::Sv39); /* enable Sv39 paging */ + Mstatus::Fs::set(mstatus, Mstatus::Fs::INITIAL); /* enable FPU */ + Mstatus::Upie::set(mstatus, 1); /* user mode interrupt */ + Mstatus::Spp::set(mstatus, Mstatus::USER); /* set user mode */ + Mstatus::Spie::set(mstatus, 0); /* disable interrupts */ + Mstatus::Mpp::set(mstatus, Mstatus::SUPERVISOR); /* set supervisor mode */ - asm volatile ("csrw sasid, %0\n" /* address space id */ - "csrw sptbr, %1\n" /* set page table */ - "csrw mstatus, %2\n" /* change mode */ + asm volatile ( + "la t0, 1f\n" + "csrw sepc, t0\n" + "csrw sptbr, %0\n" /* set asid | page table */ + "csrw mstatus, %1\n" /* change mode */ + "mret \n" /* supverisor mode, jump to 1f */ + "rdtime t0 \n" + "1: \n" : - : "r" (0/*core_pd.asid*/), - "r" (core_pd->table_base), + : "r" ((addr_t)core_pd->table_base >> 12), "r" (mstatus) - : "memory"); + : "memory"); } diff --git a/repos/base-hw/src/core/spec/riscv/cpu.h b/repos/base-hw/src/core/spec/riscv/cpu.h index b8ed75b63..16d98b307 100644 --- a/repos/base-hw/src/core/spec/riscv/cpu.h +++ b/repos/base-hw/src/core/spec/riscv/cpu.h @@ -17,6 +17,8 @@ /* Genode includes */ #include #include +#include + namespace Genode { @@ -42,23 +44,28 @@ class Genode::Cpu */ struct Context : Cpu_state { - addr_t sasid = 0; - addr_t sptbr = 0; /* supervisor page table register */ + struct Sptbr : Register<64> + { + struct Ppn : Bitfield<0, 38> { }; + struct Asid : Bitfield<38, 26> { }; + }; + + Sptbr::access_t sptbr; /** * Return base of assigned translation table */ - addr_t translation_table() const { return sptbr; } + addr_t translation_table() const { return Sptbr::Ppn::get(sptbr) << 12; } /** * Assign translation-table base 'table' */ - void translation_table(addr_t const table) { sptbr = table; } + void translation_table(addr_t const table) { Sptbr::Ppn::set(sptbr, table >> 12); } /** * Assign protection domain */ - void protection_domain(Genode::uint8_t const id) { sasid = id; } + void protection_domain(Genode::uint8_t const id) { Sptbr::Asid::set(sptbr, id); } }; struct Pd @@ -120,10 +127,10 @@ class Genode::Cpu */ static void sfence() { - asm volatile ("csrrw t0, sasid, x0\n" - "sfence.vm\n" - "csrw sasid, t0\n" - : : : "t0"); + /* + * Note: In core the address space id must be zero + */ + asm volatile ("sfence.vm\n"); } /** diff --git a/repos/base-hw/src/lib/hw/spec/riscv/machine_call.h b/repos/base-hw/src/lib/hw/spec/riscv/machine_call.h index 89eb6f765..85aaf46f2 100644 --- a/repos/base-hw/src/lib/hw/spec/riscv/machine_call.h +++ b/repos/base-hw/src/lib/hw/spec/riscv/machine_call.h @@ -30,7 +30,7 @@ namespace Hw { */ constexpr Call_arg call_id_put_char() { return 0x100; } constexpr Call_arg call_id_set_sys_timer() { return 0x101; } - constexpr Call_arg call_id_is_user_mode() { return 0x102; } + constexpr Call_arg call_id_get_sys_timer() { return 0x102; } inline void put_char(uint64_t c) { Kernel::call(call_id_put_char(), (Call_arg)c); } @@ -38,8 +38,8 @@ namespace Hw { inline void set_sys_timer(addr_t t) { Kernel::call(call_id_set_sys_timer(), (Call_arg)t); } - inline bool is_user_mode() { - return Kernel::call(call_id_is_user_mode()); } + inline addr_t get_sys_timer() { + return Kernel::call(call_id_get_sys_timer()); } } #endif /* _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ */ diff --git a/tool/builddir/build.conf/run_opt_spike b/tool/builddir/build.conf/run_opt_spike index 6f73bf281..ebff089e5 100644 --- a/tool/builddir/build.conf/run_opt_spike +++ b/tool/builddir/build.conf/run_opt_spike @@ -3,5 +3,5 @@ ## Run tool configuration ## -RUN_OPT = --include power_on/spike --include log/spike +RUN_OPT = --include image/bbl diff --git a/tool/run/image/bbl b/tool/run/image/bbl new file mode 100644 index 000000000..28d610475 --- /dev/null +++ b/tool/run/image/bbl @@ -0,0 +1,6 @@ +proc run_image {elf_img} { + puts "using '$elf_img' as bbl image" + + exec rm -f bbl/image.o + exec make IMAGE_ELF=[pwd]/$elf_img bbl +}