mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-17 14:48:20 +00:00
riscv: ISA-1.9.1 and GCC-6.3.0 adaptions
Adds 1.9.1 support to base-hw Note: * the kernel timer is not working * dynamic linking is currently not supported
This commit is contained in:
committed by
Christian Helmuth
parent
6c95eb9aff
commit
c3cf7f3c3a
@ -25,7 +25,6 @@ extern "C" void init() __attribute__ ((noreturn));
|
||||
|
||||
extern "C" void init()
|
||||
{
|
||||
Genode::init_log();
|
||||
Bootstrap::platform().enable_mmu();
|
||||
Bootstrap::platform().start_core();
|
||||
}
|
||||
|
@ -56,5 +56,3 @@ struct Buffer
|
||||
Genode::Log &Genode::Log::log() {
|
||||
return unmanaged_singleton<Buffer>()->log; }
|
||||
|
||||
|
||||
void Genode::init_log() { };
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <hw/spec/riscv/page_table.h>
|
||||
#include <hw/spec/riscv/uart.h>
|
||||
#include <drivers/defs/riscv.h>
|
||||
|
||||
namespace Bootstrap {
|
||||
struct Cpu {};
|
||||
@ -23,6 +24,9 @@ namespace Bootstrap {
|
||||
}
|
||||
|
||||
namespace Board {
|
||||
|
||||
using namespace Riscv;
|
||||
|
||||
enum { UART_BASE, UART_CLOCK };
|
||||
struct Serial : Hw::Riscv_uart {
|
||||
Serial(unsigned, unsigned, unsigned) {} };
|
||||
|
@ -35,13 +35,10 @@ bne a0, a1, 1b
|
||||
|
||||
la sp, _stack_area_start
|
||||
li a0, STACK_SIZE
|
||||
ld a0, (a0)
|
||||
add sp, sp, a0
|
||||
|
||||
/* save kernel stack pointer in mscratch */
|
||||
csrw mscratch, sp
|
||||
|
||||
jal setup_riscv_exception_vector
|
||||
csrw sscratch, sp
|
||||
jal init
|
||||
|
||||
1: j 1b
|
||||
|
@ -1,438 +0,0 @@
|
||||
/*
|
||||
* \brief Transition between kernel/userland
|
||||
* \author Sebastian Sumpf
|
||||
* \author Mark Vels
|
||||
* \date 2015-06-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
.set USER_MODE, 0
|
||||
.set SUPERVISOR_MODE, 1
|
||||
.set MACHINE_MODE, 3
|
||||
|
||||
.set CALL_PUT_CHAR, 0x100
|
||||
.set CALL_SET_SYS_TIMER, 0x101
|
||||
.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_SPTBR, 33*8
|
||||
|
||||
|
||||
# From encoding.h (riscv-opcode)
|
||||
.set MIP_MTIP, 0x00000020
|
||||
.set MIP_SSIP, 0x00000002
|
||||
.set MIP_HSIP, 0x00000004
|
||||
.set MIP_MSIP, 0x00000008
|
||||
.set MIP_STIP, 0x00000020
|
||||
.set MIP_HTIP, 0x00000040
|
||||
.set MIP_MTIP, 0x00000080
|
||||
.set MSTATUS_IE, 0x00000001
|
||||
.set MSTATUS_PRV, 0x00000006
|
||||
.set MSTATUS_IE1, 0x00000008
|
||||
.set MSTATUS_PRV1, 0x00000030
|
||||
.set MSTATUS_IE2, 0x00000040
|
||||
.set MSTATUS_PRV2, 0x00000180
|
||||
.set MSTATUS_IE3, 0x00000200
|
||||
.set MSTATUS_PRV3, 0x00000C00
|
||||
.set MSTATUS_FS, 0x00003000
|
||||
.set MSTATUS_XS, 0x0000C000
|
||||
.set MSTATUS_MPRV, 0x00010000
|
||||
.set MSTATUS_VM, 0x003E0000
|
||||
.set MSTATUS64_SD, 0x8000000000000000
|
||||
|
||||
.set TRAP_ECALL_FROM_USER, 8
|
||||
.set TRAP_ECALL_FROM_SUPERVISOR, 9
|
||||
.set TRAP_ECALL_FROM_HYPERVISOR, 10
|
||||
.set TRAP_ECALL_FROM_MACHINE, 11
|
||||
|
||||
.set TRAP_INTERRUPT_BITNR, 63
|
||||
.set IRQ_SOFT, 0x0
|
||||
.set IRQ_TIMER, 0x1
|
||||
.set IRQ_HOST, 0x2
|
||||
.set IRQ_COP, 0x3
|
||||
|
||||
|
||||
|
||||
.macro _save_scratch_registers mode
|
||||
|
||||
.if \mode == USER_MODE
|
||||
csrrw sp, mscratch, sp
|
||||
.endif
|
||||
|
||||
addi sp, sp, -24
|
||||
sd t0, 0(sp)
|
||||
sd t1, 8(sp)
|
||||
sd t2, 16(sp)
|
||||
.endm
|
||||
|
||||
.macro _restore_scratch_registers mode
|
||||
ld t0, 0(sp)
|
||||
ld t1, 8(sp)
|
||||
ld t2, 16(sp)
|
||||
addi sp, sp, 24
|
||||
|
||||
.if \mode == USER_MODE
|
||||
csrrw sp, mscratch, sp
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro _handle_trap mode
|
||||
|
||||
csrr t0, mcause
|
||||
|
||||
# If IRQ bit not setup, goto trap handler.
|
||||
# If an interrupt has occurred, the MSB will be set and
|
||||
# hence mcause will be negative
|
||||
#
|
||||
bgez t0, 11f
|
||||
|
||||
# The bit was not set so we're handling an interrupt
|
||||
# Valid interrupts are :
|
||||
# - Software IRQ - 0
|
||||
# - Timer IRQ - 1
|
||||
# - HOST HTIF - 2
|
||||
# - COP - 3
|
||||
#
|
||||
|
||||
sll t0, t0, 1 # discard MSB
|
||||
|
||||
# If interrupt source is IRQ TIMER ....
|
||||
li t1, IRQ_TIMER * 2
|
||||
bne t0, t1, 2f
|
||||
|
||||
# Forward handling of timer IRQ to SUPERVISOR
|
||||
li t0, MIP_MTIP
|
||||
csrc mip, t0
|
||||
csrc mie, t0
|
||||
li t1, MIP_STIP
|
||||
csrs mip, t1
|
||||
|
||||
# If irq from supervisor and MSTATUS.IE1 is not set,
|
||||
# then bail out using 'eret'
|
||||
#
|
||||
.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
|
||||
mret
|
||||
.endif
|
||||
|
||||
1:
|
||||
# should cause a interrupt trap in supervisor mode
|
||||
_restore_scratch_registers \mode
|
||||
# mrts
|
||||
2:
|
||||
# If interrupt source is IRQ HOST ....
|
||||
li t1, IRQ_HOST * 2
|
||||
bne t0, t1, 9f
|
||||
|
||||
3:
|
||||
# Empty mfromhost
|
||||
li t0, 0
|
||||
#csrrw t0, mfromhost, t0
|
||||
bne zero,t0, 3b
|
||||
j 9f
|
||||
|
||||
# Future implementation check for more interrupt sources
|
||||
# to handle here.....
|
||||
|
||||
9:
|
||||
#******** IRQ OUT *********
|
||||
_restore_scratch_registers \mode
|
||||
mret
|
||||
|
||||
11:
|
||||
# Handle trap
|
||||
|
||||
# check if ecall (8..11):
|
||||
# 8 : Environment call from U-mode
|
||||
# 9 : Environment call from S-mode
|
||||
# 10 : Environment call from H-mode
|
||||
# 11 : Environment call from M-mode
|
||||
#
|
||||
# If not, jump to end of macro.
|
||||
#
|
||||
|
||||
li t1, TRAP_ECALL_FROM_USER
|
||||
bltu t0, t1, 19f
|
||||
li t1, TRAP_ECALL_FROM_MACHINE
|
||||
bgt t0, t1, 19f
|
||||
|
||||
# Switch on ecall number
|
||||
li t1, CALL_PUT_CHAR
|
||||
beq t1, a0, 12f
|
||||
|
||||
li t1, CALL_SET_SYS_TIMER
|
||||
beq t1, a0, 13f
|
||||
|
||||
li t1, CALL_GET_SYS_TIMER
|
||||
beq t1, a0, 14f
|
||||
|
||||
# else, unknown ecall number
|
||||
.if \mode == USER_MODE
|
||||
# Assume that Genode (supervisor trap handler)
|
||||
# knows what to do then.
|
||||
_restore_scratch_registers \mode
|
||||
# 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
|
||||
bne zero, t1, 12b
|
||||
|
||||
#csrw mtohost, a1
|
||||
j 15f
|
||||
|
||||
13:
|
||||
# Only allow timer fiddling from supervisor mode
|
||||
.if \mode == SUPERVISOR_MODE
|
||||
# Clear any pending STIP
|
||||
li t0, MIP_STIP
|
||||
csrc mip, t0
|
||||
|
||||
# Set system timer
|
||||
#csrw mtimecmp, a1
|
||||
|
||||
# enable timer interrupt in M-mode
|
||||
li t0, MIP_MTIP
|
||||
csrrs t0, mie, t0
|
||||
.endif
|
||||
j 15f
|
||||
|
||||
14:
|
||||
.if \mode == SUPERVISOR_MODE
|
||||
#csrr a0, mtime
|
||||
.endif
|
||||
j 15f
|
||||
|
||||
15:
|
||||
#******* ECALL OUT *********
|
||||
# Empty mfromhost
|
||||
li t0, 0
|
||||
#csrrw t0, mfromhost, t0
|
||||
bne zero,t0, 14b
|
||||
|
||||
# advance epc
|
||||
csrr t0, mepc
|
||||
addi t0, t0, 4
|
||||
csrw mepc, t0
|
||||
|
||||
_restore_scratch_registers \mode
|
||||
mret
|
||||
19:
|
||||
.endm
|
||||
|
||||
.section .text
|
||||
|
||||
##
|
||||
# Page aligned base of mode transition code.
|
||||
#
|
||||
# This position independent code switches between a kernel context and a
|
||||
# user context and thereby between their address spaces. Due to the latter
|
||||
# it must be mapped executable to the same region in every address space.
|
||||
# To enable such switching, the kernel context must be stored within this
|
||||
# region, thus one should map it solely accessable for privileged modes.
|
||||
#
|
||||
|
||||
|
||||
|
||||
.p2align 8
|
||||
.global _machine_begin
|
||||
_machine_begin:
|
||||
|
||||
# 0x100 user mode
|
||||
j user_trap
|
||||
.space 0x3c
|
||||
# 0x140 supervisor
|
||||
j supervisor_trap
|
||||
.space 0x3c
|
||||
# 0x180 hypervisor
|
||||
1: j 1b
|
||||
.space 0x3c
|
||||
# 0x1c0 machine
|
||||
j machine_trap
|
||||
.space 0x38
|
||||
# 0x1fc non-maksable interrupt
|
||||
1: j 1b
|
||||
|
||||
user_trap:
|
||||
|
||||
_save_scratch_registers USER_MODE
|
||||
_handle_trap USER_MODE
|
||||
_restore_scratch_registers USER_MODE
|
||||
# mrts
|
||||
|
||||
supervisor_trap:
|
||||
|
||||
_save_scratch_registers SUPERVISOR_MODE
|
||||
_handle_trap SUPERVISOR_MODE
|
||||
j fault
|
||||
|
||||
machine_trap:
|
||||
|
||||
_save_scratch_registers MACHINE_MODE
|
||||
_handle_trap MACHINE_MODE
|
||||
j fault
|
||||
|
||||
|
||||
fault:j fault # TODO: handle trap from supervisor or machine mode
|
||||
|
||||
.global _machine_end
|
||||
_machine_end:
|
||||
|
||||
.p2align 12
|
||||
.global _mt_begin
|
||||
_mt_begin:
|
||||
|
||||
# 0x100 user mode
|
||||
j _mt_kernel_entry_pic
|
||||
.space 0x3c
|
||||
# 0x140 supervisor
|
||||
1: j 1b
|
||||
.space 0x3c
|
||||
# 0x180 hypervisor
|
||||
1: j 1b
|
||||
.space 0x3c
|
||||
# 0x1c0 machine
|
||||
1: j 1b
|
||||
.space 0x38
|
||||
# 0x1fc non-maksable interrupt
|
||||
1: j 1b
|
||||
|
||||
/* space for a client context-pointer per CPU */
|
||||
.p2align 3
|
||||
.global _mt_client_context_ptr
|
||||
_mt_client_context_ptr:
|
||||
.space 8
|
||||
|
||||
/* space for a copy of the kernel context */
|
||||
.global _mt_master_context_begin
|
||||
_mt_master_context_begin:
|
||||
|
||||
/* space must be at least as large as 'Context' */
|
||||
.space 35*8
|
||||
|
||||
.global _mt_master_context_end
|
||||
_mt_master_context_end:
|
||||
|
||||
.global _mt_kernel_entry_pic
|
||||
_mt_kernel_entry_pic:
|
||||
|
||||
# master context
|
||||
csrrw x31, sscratch, x31
|
||||
addi x31, x31, 8
|
||||
|
||||
# save x30 in master
|
||||
sd x30, CPU_X1 + 8 * 28(x31)
|
||||
|
||||
# load kernel page table
|
||||
ld x30, CPU_SPTBR(x31)
|
||||
csrw sptbr, x30
|
||||
|
||||
#
|
||||
# FIXME
|
||||
# A TLB flush. Might be necessary to remove this in the near future again
|
||||
# because on real hardware we currently get problems without.
|
||||
#
|
||||
sfence.vm x0
|
||||
|
||||
# save x29 - x31 in user context
|
||||
mv x29, x31
|
||||
addi x29, x29, -8
|
||||
ld x29, (x29)
|
||||
|
||||
.irp reg,29,30
|
||||
ld x30, CPU_X1 + 8 * (\reg - 1)(x31)
|
||||
sd x30, CPU_X1 + 8 * (\reg - 1)(x29)
|
||||
.endr
|
||||
|
||||
csrr x30, sscratch /* x31 */
|
||||
sd x30, CPU_X1 + 8 * 30(x29)
|
||||
|
||||
# save x1 - x28
|
||||
.irp reg,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
|
||||
sd x\reg, CPU_X1 + 8 * (\reg - 1)(x29)
|
||||
.endr
|
||||
|
||||
# trap reason
|
||||
csrr x30, scause
|
||||
sd x30, CPU_EXCEPTION(x29)
|
||||
|
||||
# ip
|
||||
csrr x30, sepc
|
||||
sd x30, CPU_IP(x29)
|
||||
|
||||
# load kernel stack and ip
|
||||
ld sp, CPU_SP(x31)
|
||||
ld x30, CPU_IP(x31)
|
||||
|
||||
# restore scratch
|
||||
addi x31, x31, -8
|
||||
csrw sscratch, x31
|
||||
|
||||
jalr x30
|
||||
|
||||
|
||||
.global _mt_user_entry_pic
|
||||
_mt_user_entry_pic:
|
||||
|
||||
# client context pointer
|
||||
csrr x30, sscratch
|
||||
ld x30, (x30)
|
||||
|
||||
# set return IP
|
||||
ld x31, CPU_IP(x30)
|
||||
csrw sepc, x31
|
||||
|
||||
# restore x1-x28
|
||||
.irp reg,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
|
||||
ld x\reg, CPU_X1 + 8 * (\reg - 1)(x30)
|
||||
.endr
|
||||
|
||||
# save x29, x30, x31 to master context
|
||||
csrr x29, sscratch
|
||||
addi x29, x29, 8 # master context
|
||||
|
||||
.irp reg,29,30,31
|
||||
ld x31, CPU_X1 + 8 * (\reg - 1)(x30)
|
||||
sd x31, CPU_X1 + 8 * (\reg - 1)(x29)
|
||||
.endr
|
||||
|
||||
# switch page table
|
||||
ld x31, CPU_SPTBR(x30)
|
||||
|
||||
csrw sptbr, x31
|
||||
|
||||
#
|
||||
# FIXME
|
||||
# A TLB flush. Might be necessary to remove this in the near future again
|
||||
# because on real hardware we currently get problems without.
|
||||
#
|
||||
|
||||
sfence.vm x0
|
||||
|
||||
# restore x29 - x31 from master context
|
||||
.irp reg,31,30,29
|
||||
ld x\reg, CPU_X1 + 8 * (\reg - 1)(x29)
|
||||
.endr
|
||||
|
||||
sret
|
||||
|
||||
# end of the mode transition code
|
||||
.global _mt_end
|
||||
_mt_end:
|
@ -11,72 +11,18 @@
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <util/string.h>
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
using namespace Board;
|
||||
|
||||
Bootstrap::Platform::Board::Board()
|
||||
: early_ram_regions(Memory_region { 0, 128 * 1024 * 1024 } ) {}
|
||||
: early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE } ) {}
|
||||
|
||||
|
||||
void Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
struct Mstatus : Genode::Register<64>
|
||||
{
|
||||
enum {
|
||||
USER = 0,
|
||||
SUPERVISOR = 1,
|
||||
Sv39 = 9,
|
||||
};
|
||||
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::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 (
|
||||
"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"
|
||||
asm volatile ("csrw sptbr, %0\n" /* set asid | page table */
|
||||
:
|
||||
: "r" ((addr_t)core_pd->table_base >> 12),
|
||||
"r" (mstatus)
|
||||
: "r" ((addr_t)core_pd->table_base >> 12)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
|
||||
extern int _machine_begin, _machine_end;
|
||||
|
||||
extern "C" void setup_riscv_exception_vector()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* retrieve exception vector */
|
||||
addr_t vector;
|
||||
asm volatile ("csrr %0, mtvec\n" : "=r"(vector));
|
||||
|
||||
/* copy machine mode exception vector */
|
||||
memcpy((void *)vector,
|
||||
&_machine_begin, (addr_t)&_machine_end - (addr_t)&_machine_begin);
|
||||
}
|
||||
|
Reference in New Issue
Block a user