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

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
la sp, _stack_area_start
la a0, STACK_SIZE
li a0, STACK_SIZE
ld a0, (a0)
add sp, sp, a0

View File

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

View File

@ -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");
}

View File

@ -17,6 +17,8 @@
/* Genode includes */
#include <base/stdint.h>
#include <cpu/cpu_state.h>
#include <util/register.h>
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");
}
/**

View File

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

View File

@ -3,5 +3,5 @@
## 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
}