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:
Sebastian Sumpf 2017-05-26 16:27:39 +02:00 committed by Christian Helmuth
parent 6c95eb9aff
commit c3cf7f3c3a
18 changed files with 278 additions and 555 deletions

View File

@ -3,6 +3,5 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/riscv
SRC_CC += bootstrap/spec/riscv/platform.cc
SRC_CC += lib/base/riscv/kernel/interface.cc
SRC_S += bootstrap/spec/riscv/crt0.s
SRC_S += bootstrap/spec/riscv/exception_vector.s
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc

View File

@ -10,9 +10,10 @@ SRC_CC += spec/riscv/kernel/thread.cc
SRC_CC += spec/riscv/kernel/pd.cc
SRC_CC += spec/riscv/kernel/cpu.cc
SRC_CC += spec/riscv/platform_support.cc
SRC_CC += spec/riscv/timer.cc
#add assembly sources
SRC_S += $(REP_DIR)/src/bootstrap/spec/riscv/exception_vector.s
SRC_S += spec/riscv/exception_vector.s
SRC_S += spec/riscv/crt0.s
# include less specific configuration

View File

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

View File

@ -56,5 +56,3 @@ struct Buffer
Genode::Log &Genode::Log::log() {
return unmanaged_singleton<Buffer>()->log; }
void Genode::init_log() { };

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,8 @@
#ifndef _CORE__SPEC__RISCV__BOARD_H_
#define _CORE__SPEC__RISCV__BOARD_H_
#include <hw/spec/riscv/uart.h>
namespace Board {
enum { UART_BASE, UART_CLOCK };
struct Serial : Hw::Riscv_uart {

View File

@ -0,0 +1,161 @@
/*
* \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 CPU_IP, 0
.set CPU_EXCEPTION, 8
.set CPU_X1, 2*8
.set CPU_SP, 3*8
.set CPU_SPTBR, 33*8
.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:

View File

@ -13,7 +13,7 @@
/* Core includes */
#include <kernel/timer.h>
#include <machine_call.h>
#include <hw/spec/riscv/machine_call.h>
using namespace Genode;
using namespace Kernel;
@ -27,10 +27,10 @@ Timer_driver::Timer_driver(unsigned)
}
void Timer::_start_one_shot(time_t const ticks, unsigned const)
void Timer::_start_one_shot(time_t const ticks)
{
_driver.timeout = _driver.stime() + ticks;
Machine::set_sys_timer(_driver.timeout);
Hw::set_sys_timer(_driver.timeout);
}
@ -42,11 +42,11 @@ time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * Driver::TICS_PER_MS; }
time_t Timer::_max_value() {
time_t Timer::_max_value() const {
return (addr_t)~0; }
time_t Timer::_value(unsigned const)
time_t Timer::_value()
{
addr_t time = _driver.stime();
return time < _driver.timeout ? _driver.timeout - time : 0;

View File

@ -32,11 +32,10 @@ struct Kernel::Timer_driver
addr_t timeout = 0;
/* TODO: implement */
addr_t stime()
{
Genode::addr_t t;
asm volatile ("csrr %0, stime\n" : "=r"(t));
return t;
return 0;
}
Timer_driver(unsigned);

View File

@ -28,12 +28,21 @@ namespace Hw {
*
* Keep in sync with mode_transition.s.
*/
constexpr Call_arg call_id_put_char() { return 0x100; }
constexpr Call_arg call_id_set_sys_timer() { return 0x101; }
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); }
inline void ecall(addr_t call, addr_t arg)
{
asm volatile ("mv a0, %0\n"
"mv a1, %1\n"
"ecall \n"
: : "r"(call), "r"(arg)
: "a0", "a1");
}
inline void put_char(addr_t c) {
ecall(Kernel::call_id_print_char(), c);
}
inline void set_sys_timer(addr_t t) {
Kernel::call(call_id_set_sys_timer(), (Call_arg)t); }

View File

@ -53,48 +53,47 @@ namespace Sv39
struct Sv39::Descriptor : Register<64>
{
enum Descriptor_type { INVALID, TABLE, BLOCK };
struct V : Bitfield<0, 1> { }; /* present */
struct Type : Bitfield<1, 4> /* type and access rights */
struct V : Bitfield<0, 1> { }; /* present */
struct R : Bitfield<1, 1> { }; /* read */
struct W : Bitfield<2, 1> { }; /* write */
struct X : Bitfield<3, 1> { }; /* executable */
struct U : Bitfield<4, 1> { }; /* user */
struct G : Bitfield<5, 1> { }; /* global */
struct Perm : Bitfield<0, 5> { };
struct Type : Bitfield<1, 3>
{
enum {
POINTER = 0,
POINTER_GLOBAL = 1,
USER = 4, /* R + 0, RW + 1, RX + 2, RWX + 3 */
KERNEL = 8,
GLOBAL = 12,
POINTER = 0
};
};
struct Ppn : Bitfield<10, 38> { }; /* physical address 10 bit aligned */
struct Base : Bitfield<12, 38> { }; /* physical address page aligned */
template <access_t BASE>
static access_t rwx(Hw::Page_flags const &f)
{
if (f.writeable && f.executable)
return BASE + 3;
else if (f.writeable)
return BASE + 1;
else if (f.executable)
return BASE + 2;
else
return BASE;
}
static access_t permission_bits(Hw::Page_flags const &f)
{
access_t rights = 0;
R::set(rights, 1);
if (f.writeable)
W::set(rights, 1);
if (f.executable)
X::set(rights, 1);
if (!f.privileged)
U::set(rights, 1);
if (f.global)
return rwx<Type::GLOBAL>(f);
G::set(rights, 1);
if (f.privileged)
return rwx<Type::KERNEL>(f);
return rwx<Type::USER>(f);
return rights;
}
static Descriptor_type type(access_t const v)
{
if (!V::get(v)) return INVALID;
if (Type::get(v) == Type::POINTER || Type::get(v) == Type::POINTER_GLOBAL)
if (Type::get(v) == Type::POINTER)
return TABLE;
return BLOCK;
@ -127,7 +126,7 @@ struct Sv39::Block_descriptor : Descriptor
access_t desc = 0;
Ppn::set(desc, base);
Type::set(desc, permission_bits(f));
Perm::set(desc, permission_bits(f));
V::set(desc, 1);
return desc;

View File

@ -24,16 +24,7 @@ struct Hw::Riscv_uart
{
void put_char(char const c)
{
struct Arg : Genode::Register<64>
{
struct Char : Bitfield<0, 8> { };
struct Write_cmd : Bitfield<48, 1> { };
struct Stdout : Bitfield<56, 1> { };
};
Hw::put_char(Arg::Char::bits(c) |
Arg::Stdout::bits(1) |
Arg::Write_cmd::bits(1));
Hw::put_char(c);
}
};

View File

@ -0,0 +1,25 @@
/*
* \brief MMIO and IRQ definitions for RISC-V (1.9.1)
* \author Sebastian Sumpf
* \date 2017-05-29
*/
/*
* Copyright (C) 2013-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.
*/
#ifndef _INCLUDE__DRIVERS__DEFS__RISCV_H_
#define _INCLUDE__DRIVERS__DEFS__RISCV_H_
namespace Riscv {
enum {
RAM_0_BASE = 0x81000000,
RAM_0_SIZE = 0x6e00000,
};
}
#endif /* _INCLUDE__DRIVERS__DEFS__RISCV_H_ */

View File

@ -0,0 +1,31 @@
/*
* \brief Trace timestamp
* \author Sebastian Sumpf
* \date 2017-05-26
*
* Serialized reading of performance counter on ARM.
*/
/*
* Copyright (C) 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.
*/
#ifndef _INCLUDE__SPEC__RISCV__TRACE__TIMESTAMP_H_
#define _INCLUDE__SPEC__RISCV__TRACE__TIMESTAMP_H_
#include <base/fixed_stdint.h>
namespace Genode { namespace Trace {
typedef uint32_t Timestamp;
inline Timestamp timestamp()
{
return 0;
}
} }
#endif /* _INCLUDE__SPEC__RISCV__TRACE__TIMESTAMP_H_ */

View File

@ -15,7 +15,7 @@ proc bootstrap_link_address { } {
if {[have_spec "arndale"]} { return "0x80000000" }
if {[have_spec "panda"]} { return "0x81000000" }
if {[have_spec "zynq"]} { return "0x00100000" }
if {[have_spec "riscv"]} { return "0x00000200" }
if {[have_spec "riscv"]} { return "0x81000000" }
if {[have_spec "rpi"]} { return "0x00800000" }
puts "unknown platform no linker address known"