base-hw: RISC-V BBL

The Berkley Boot Loader handles kernel loading and machine mode
This commit is contained in:
Sebastian Sumpf 2017-05-12 10:35:33 +02:00 committed by Christian Helmuth
parent 4cbfed11ee
commit 6c95eb9aff
20 changed files with 182 additions and 66 deletions

View File

@ -12,7 +12,7 @@ SRC_CC += spec/riscv/kernel/cpu.cc
SRC_CC += spec/riscv/platform_support.cc SRC_CC += spec/riscv/platform_support.cc
#add assembly sources #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 SRC_S += spec/riscv/crt0.s
# include less specific configuration # include less specific configuration

View File

@ -0,0 +1 @@
65cc50461e5e1c4d89f8e41dce69362023f445d7

View File

@ -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

View File

View File

View File

@ -0,0 +1,8 @@
#ifndef _ERRNO_H_
#define _ERRNO_H_
enum {
ENOSYS = 38,
};
#endif /* _ERRNO_H_ */

View File

@ -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:

View File

@ -0,0 +1,8 @@
#ifndef _LIMITS_H_
#define _LIMITS_H_
enum {
ULONG_MAX = ~0UL
};
#endif /* _LIMITS_H_ */

View File

@ -0,0 +1,7 @@
.section ".payload","a",@progbits
.align 3
.globl _payload_start, _payload_end
_payload_start:
.incbin BBL_PAYLOAD
_payload_end:

View File

@ -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_ */

View File

@ -0,0 +1,6 @@
#ifndef _STDIO_H_
#define _STDIO_H_
typedef unsigned long long uint64_t;
#endif /* _STDIO_H_ */

View File

@ -0,0 +1,9 @@
#ifndef _STRING_H_
#define _STRING_H_
#include <stdint.h>
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
#endif /* _STRING_H_ */

View File

@ -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)

View File

@ -34,7 +34,7 @@ addi a0, a0, 8
bne a0, a1, 1b bne a0, a1, 1b
la sp, _stack_area_start la sp, _stack_area_start
la a0, STACK_SIZE li a0, STACK_SIZE
ld a0, (a0) ld a0, (a0)
add sp, sp, a0 add sp, sp, a0

View File

@ -18,14 +18,13 @@
.set CALL_PUT_CHAR, 0x100 .set CALL_PUT_CHAR, 0x100
.set CALL_SET_SYS_TIMER, 0x101 .set CALL_SET_SYS_TIMER, 0x101
.set CALL_IS_USER_MODE, 0x102 .set CALL_GET_SYS_TIMER, 0x102
.set CPU_IP, 0 .set CPU_IP, 0
.set CPU_EXCEPTION, 8 .set CPU_EXCEPTION, 8
.set CPU_X1, 2*8 .set CPU_X1, 2*8
.set CPU_SP, 3*8 .set CPU_SP, 3*8
.set CPU_SASID, 33*8 .set CPU_SPTBR, 33*8
.set CPU_SPTBR, 34*8
# From encoding.h (riscv-opcode) # From encoding.h (riscv-opcode)
@ -120,21 +119,20 @@
# If irq from supervisor and MSTATUS.IE1 is not set, # If irq from supervisor and MSTATUS.IE1 is not set,
# then bail out using 'eret' # then bail out using 'eret'
# #
.if \mode == SUPERVISOR_MODE .if \mode == SUPERVISOR_MODE
csrr t1, mstatus csrr t1, mstatus
and t0, t1, MSTATUS_IE1 and t0, t1, MSTATUS_IE1
bne zero, t0, 1f bne zero, t0, 1f
# So, IE1 is not set. # So, IE1 is not set.
_restore_scratch_registers \mode _restore_scratch_registers \mode
eret mret
.endif
.endif
1: 1:
# should cause a interrupt trap in supervisor mode # should cause a interrupt trap in supervisor mode
_restore_scratch_registers \mode _restore_scratch_registers \mode
mrts # mrts
2: 2:
# If interrupt source is IRQ HOST .... # If interrupt source is IRQ HOST ....
li t1, IRQ_HOST * 2 li t1, IRQ_HOST * 2
@ -143,7 +141,7 @@
3: 3:
# Empty mfromhost # Empty mfromhost
li t0, 0 li t0, 0
csrrw t0, mfromhost, t0 #csrrw t0, mfromhost, t0
bne zero,t0, 3b bne zero,t0, 3b
j 9f j 9f
@ -153,7 +151,7 @@
9: 9:
#******** IRQ OUT ********* #******** IRQ OUT *********
_restore_scratch_registers \mode _restore_scratch_registers \mode
eret mret
11: 11:
# Handle trap # Handle trap
@ -179,7 +177,7 @@
li t1, CALL_SET_SYS_TIMER li t1, CALL_SET_SYS_TIMER
beq t1, a0, 13f beq t1, a0, 13f
li t1, CALL_IS_USER_MODE li t1, CALL_GET_SYS_TIMER
beq t1, a0, 14f beq t1, a0, 14f
# else, unknown ecall number # else, unknown ecall number
@ -187,17 +185,17 @@
# Assume that Genode (supervisor trap handler) # Assume that Genode (supervisor trap handler)
# knows what to do then. # knows what to do then.
_restore_scratch_registers \mode _restore_scratch_registers \mode
mrts # mrts
.endif .endif
j 15f j 15f
12: 12:
# output character but first wait until mtohost reads 0 atomically # output character but first wait until mtohost reads 0 atomically
# to make sure any previous character is gone.. # to make sure any previous character is gone..
csrr t1, mtohost #csrr t1, mtohost
bne zero, t1, 12b bne zero, t1, 12b
csrw mtohost, a1 #csrw mtohost, a1
j 15f j 15f
13: 13:
@ -208,7 +206,7 @@
csrc mip, t0 csrc mip, t0
# Set system timer # Set system timer
csrw mtimecmp, a1 #csrw mtimecmp, a1
# enable timer interrupt in M-mode # enable timer interrupt in M-mode
li t0, MIP_MTIP li t0, MIP_MTIP
@ -217,17 +215,16 @@
j 15f j 15f
14: 14:
mv a0, x0 .if \mode == SUPERVISOR_MODE
.if \mode == USER_MODE #csrr a0, mtime
li a0, 1
.endif .endif
j 15f j 15f
15: 15:
#******* ECALL OUT ********* #******* ECALL OUT *********
# Empty mfromhost # Empty mfromhost
li t0, 0 li t0, 0
csrrw t0, mfromhost, t0 #csrrw t0, mfromhost, t0
bne zero,t0, 14b bne zero,t0, 14b
# advance epc # advance epc
@ -236,7 +233,7 @@
csrw mepc, t0 csrw mepc, t0
_restore_scratch_registers \mode _restore_scratch_registers \mode
eret mret
19: 19:
.endm .endm
@ -278,7 +275,7 @@ user_trap:
_save_scratch_registers USER_MODE _save_scratch_registers USER_MODE
_handle_trap USER_MODE _handle_trap USER_MODE
_restore_scratch_registers USER_MODE _restore_scratch_registers USER_MODE
mrts # mrts
supervisor_trap: supervisor_trap:
@ -340,15 +337,11 @@ _mt_kernel_entry_pic:
csrrw x31, sscratch, x31 csrrw x31, sscratch, x31
addi x31, x31, 8 addi x31, x31, 8
# save x29, x30 in master # save x30 in master
sd x29, CPU_X1 + 8 * 28(x31) sd x30, CPU_X1 + 8 * 28(x31)
sd x30, CPU_X1 + 8 * 29(x31)
# load kernel page table # load kernel page table
ld x29, CPU_SASID(x31)
ld x30, CPU_SPTBR(x31) ld x30, CPU_SPTBR(x31)
csrw sasid, x29
csrw sptbr, x30 csrw sptbr, x30
# #
@ -421,11 +414,9 @@ _mt_user_entry_pic:
.endr .endr
# switch page table # switch page table
ld x31, CPU_SASID(x30) ld x31, CPU_SPTBR(x30)
ld x30, CPU_SPTBR(x30)
csrw sasid, x31 csrw sptbr, x31
csrw sptbr, x30
# #
# FIXME # FIXME
@ -440,7 +431,7 @@ _mt_user_entry_pic:
ld x\reg, CPU_X1 + 8 * (\reg - 1)(x29) ld x\reg, CPU_X1 + 8 * (\reg - 1)(x29)
.endr .endr
eret sret
# end of the mode transition code # end of the mode transition code
.global _mt_end .global _mt_end

View File

@ -29,32 +29,40 @@ void Bootstrap::Platform::enable_mmu()
SUPERVISOR = 1, SUPERVISOR = 1,
Sv39 = 9, Sv39 = 9,
}; };
struct Ie : Bitfield<0, 1> { }; struct Uie : Bitfield<0, 1> { };
struct Priv : Bitfield<1, 2> { }; struct Sie : Bitfield<1, 1> { };
struct Ie1 : Bitfield<3, 1> { }; struct Upie : Bitfield<4, 1> { };
struct Priv1 : Bitfield<4, 2> { }; struct Spie : Bitfield<5, 1> { };
struct Fs : Bitfield<12, 2> { enum { INITIAL = 1 }; }; struct Spp : Bitfield<8, 1> { };
struct Vm : Bitfield<17, 5> { }; struct Mpp : Bitfield<11, 2> { };
struct Fs : Bitfield<13, 2> { enum { INITIAL = 1 }; };
struct Vm : Bitfield<24, 5> { };
}; };
/* read status register */ /* read status register */
Mstatus::access_t mstatus = 0; Mstatus::access_t mstatus = 0;
Mstatus::Vm::set(mstatus, Mstatus::Sv39); /* enable Sv39 paging */ Mstatus::Vm::set(mstatus, Mstatus::Sv39); /* enable Sv39 paging */
Mstatus::Fs::set(mstatus, Mstatus::Fs::INITIAL); /* enable FPU */ Mstatus::Fs::set(mstatus, Mstatus::Fs::INITIAL); /* enable FPU */
Mstatus::Ie1::set(mstatus, 1); /* user mode interrupt */ Mstatus::Upie::set(mstatus, 1); /* user mode interrupt */
Mstatus::Priv1::set(mstatus, Mstatus::USER); /* set user mode */ Mstatus::Spp::set(mstatus, Mstatus::USER); /* set user mode */
Mstatus::Ie::set(mstatus, 0); /* disable interrupts */ Mstatus::Spie::set(mstatus, 0); /* disable interrupts */
Mstatus::Priv::set(mstatus, Mstatus::SUPERVISOR); /* set supervisor mode */ Mstatus::Mpp::set(mstatus, Mstatus::SUPERVISOR); /* set supervisor mode */
asm volatile ("csrw sasid, %0\n" /* address space id */ asm volatile (
"csrw sptbr, %1\n" /* set page table */ "la t0, 1f\n"
"csrw mstatus, %2\n" /* change mode */ "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" ((addr_t)core_pd->table_base >> 12),
"r" (core_pd->table_base),
"r" (mstatus) "r" (mstatus)
: "memory"); : "memory");
} }

View File

@ -17,6 +17,8 @@
/* Genode includes */ /* Genode includes */
#include <base/stdint.h> #include <base/stdint.h>
#include <cpu/cpu_state.h> #include <cpu/cpu_state.h>
#include <util/register.h>
namespace Genode namespace Genode
{ {
@ -42,23 +44,28 @@ class Genode::Cpu
*/ */
struct Context : Cpu_state struct Context : Cpu_state
{ {
addr_t sasid = 0; struct Sptbr : Register<64>
addr_t sptbr = 0; /* supervisor page table register */ {
struct Ppn : Bitfield<0, 38> { };
struct Asid : Bitfield<38, 26> { };
};
Sptbr::access_t sptbr;
/** /**
* Return base of assigned translation table * 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' * 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 * 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 struct Pd
@ -120,10 +127,10 @@ class Genode::Cpu
*/ */
static void sfence() static void sfence()
{ {
asm volatile ("csrrw t0, sasid, x0\n" /*
"sfence.vm\n" * Note: In core the address space id must be zero
"csrw sasid, t0\n" */
: : : "t0"); asm volatile ("sfence.vm\n");
} }
/** /**

View File

@ -30,7 +30,7 @@ namespace Hw {
*/ */
constexpr Call_arg call_id_put_char() { return 0x100; } constexpr Call_arg call_id_put_char() { return 0x100; }
constexpr Call_arg call_id_set_sys_timer() { return 0x101; } 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) { inline void put_char(uint64_t c) {
Kernel::call(call_id_put_char(), (Call_arg)c); } Kernel::call(call_id_put_char(), (Call_arg)c); }
@ -38,8 +38,8 @@ namespace Hw {
inline void set_sys_timer(addr_t t) { inline void set_sys_timer(addr_t t) {
Kernel::call(call_id_set_sys_timer(), (Call_arg)t); } Kernel::call(call_id_set_sys_timer(), (Call_arg)t); }
inline bool is_user_mode() { inline addr_t get_sys_timer() {
return Kernel::call(call_id_is_user_mode()); } return Kernel::call(call_id_get_sys_timer()); }
} }
#endif /* _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ */ #endif /* _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ */

View File

@ -3,5 +3,5 @@
## Run tool configuration ## Run tool configuration
## ##
RUN_OPT = --include power_on/spike --include log/spike RUN_OPT = --include image/bbl

6
tool/run/image/bbl Normal file
View File

@ -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
}