mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
base-hw: RISC-V BBL
The Berkley Boot Loader handles kernel loading and machine mode
This commit is contained in:
parent
4cbfed11ee
commit
6c95eb9aff
@ -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
|
||||
|
1
repos/base-hw/ports/bbl.hash
Normal file
1
repos/base-hw/ports/bbl.hash
Normal file
@ -0,0 +1 @@
|
||||
65cc50461e5e1c4d89f8e41dce69362023f445d7
|
8
repos/base-hw/ports/bbl.port
Normal file
8
repos/base-hw/ports/bbl.port
Normal 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
|
||||
|
0
repos/base-hw/src/bbl/ctype.h
Normal file
0
repos/base-hw/src/bbl/ctype.h
Normal file
0
repos/base-hw/src/bbl/dummy
Normal file
0
repos/base-hw/src/bbl/dummy
Normal file
8
repos/base-hw/src/bbl/errno.h
Normal file
8
repos/base-hw/src/bbl/errno.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _ERRNO_H_
|
||||
#define _ERRNO_H_
|
||||
|
||||
enum {
|
||||
ENOSYS = 38,
|
||||
};
|
||||
|
||||
#endif /* _ERRNO_H_ */
|
9
repos/base-hw/src/bbl/image.S
Normal file
9
repos/base-hw/src/bbl/image.S
Normal 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:
|
8
repos/base-hw/src/bbl/limits.h
Normal file
8
repos/base-hw/src/bbl/limits.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _LIMITS_H_
|
||||
#define _LIMITS_H_
|
||||
|
||||
enum {
|
||||
ULONG_MAX = ~0UL
|
||||
};
|
||||
|
||||
#endif /* _LIMITS_H_ */
|
7
repos/base-hw/src/bbl/payload.S
Normal file
7
repos/base-hw/src/bbl/payload.S
Normal file
@ -0,0 +1,7 @@
|
||||
.section ".payload","a",@progbits
|
||||
.align 3
|
||||
|
||||
.globl _payload_start, _payload_end
|
||||
_payload_start:
|
||||
.incbin BBL_PAYLOAD
|
||||
_payload_end:
|
15
repos/base-hw/src/bbl/stdint.h
Normal file
15
repos/base-hw/src/bbl/stdint.h
Normal 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_ */
|
6
repos/base-hw/src/bbl/stdio.h
Normal file
6
repos/base-hw/src/bbl/stdio.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _STDIO_H_
|
||||
#define _STDIO_H_
|
||||
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
#endif /* _STDIO_H_ */
|
9
repos/base-hw/src/bbl/string.h
Normal file
9
repos/base-hw/src/bbl/string.h
Normal 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_ */
|
33
repos/base-hw/src/bbl/target.mk
Normal file
33
repos/base-hw/src/bbl/target.mk
Normal 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)
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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_ */
|
||||
|
@ -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
6
tool/run/image/bbl
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user