base-hw: RISC-V Rocket Core on Zynq

This commit adds rocket core on the Zynq FPGA support to base HW. It also takes
advantage of the new timer infrastructure introduced with the privileged 1.8 and
adds improved TLB flush support.

fixes #1880
This commit is contained in:
Mark Vels 2015-11-10 12:49:05 +01:00 committed by Christian Helmuth
parent c246a0d194
commit 1668983efa
23 changed files with 376 additions and 242 deletions

View File

@ -1,4 +1,4 @@
/**
/*
* \brief CPU state
* \author Sebastian Sumpf
* \date 2015-06-01
@ -25,11 +25,15 @@ struct Genode::Cpu_state
INSTRUCTION_UNALIGNED = 0,
INSTRUCTION_PAGE_FAULT = 1,
INSTRUCTION_ILLEGAL = 2,
BREAKPOINT = 3,
LOAD_UNALIGNED = 4,
LOAD_PAGE_FAULT = 5,
STORE_UNALIGNED = 6,
STORE_PAGE_FAULT = 7,
SUPERVISOR_CALL = 8,
ECALL_FROM_USER = 8,
ECALL_FROM_SUPERVISOR = 9,
ECALL_FROM_HYPERVISOR = 10,
ECALL_FROM_MACHINE = 11,
RESET = 16,
IRQ_FLAG = 1UL << 63,
};

View File

@ -1,4 +1,4 @@
/**
/*
* \brief Memory barrier
* \author Sebastian Sumpf
* \date 2015-06-01
@ -16,10 +16,8 @@
namespace Genode {
static inline void memory_barrier()
{
asm volatile ("fence" ::: "memory");
}
static inline void memory_barrier() {
asm volatile ("fence" ::: "memory"); }
}
#endif /* _INCLUDE__RISCV__CPU__MEMORY_BARRIER_H_ */

View File

@ -25,11 +25,7 @@ namespace Kernel
/**
* Events that are provided by a kernel thread-object for user handling
*/
struct Thread_event_id
{
enum { FAULT = 0 };
};
struct Thread_event_id { enum { FAULT = 0 }; };
}
#endif /* _KERNEL__INTERFACE_SUPPORT_H_ */

View File

@ -11,6 +11,7 @@ SRC_CC += spec/riscv/kernel/pd.cc
SRC_CC += spec/riscv/kernel/cpu.cc
SRC_CC += spec/riscv/kernel/exception_vector.cc
SRC_CC += spec/riscv/platform_support.cc
SRC_CC += spec/riscv/cpu.cc
#add assembly sources
SRC_S += spec/riscv/mode_transition.s

View File

@ -2,8 +2,8 @@ SPECS += hw riscv platform_riscv 64bit
LD_TEXT_ADDR ?= 0x1000
CORE_LD_TEXT_ADDR = 0x200
NR_OF_CPUS = 1
REP_INC_DIR += include/spec/riscv
NR_OF_CPUS = 1
REP_INC_DIR += include/spec/riscv
include $(call select_from_repositories,mk/spec/64bit.mk)
include $(call select_from_repositories,mk/spec/hw.mk)

View File

@ -14,12 +14,6 @@
#ifndef _BOARD_H_
#define _BOARD_H_
namespace Genode
{
struct Board
{
void init() { }
};
}
namespace Genode { struct Board { void init() { } }; }
#endif /* _BOARD_H_ */

View File

@ -107,16 +107,34 @@ class Genode::Cpu
static void wait_for_interrupt() { asm volatile ("wfi"); };
/**
* From the manual
*
* The behavior of SFENCE.VM depends on the current value of the sasid
* register. If sasid is nonzero, SFENCE.VM takes effect only for address
* translations in the current address space. If sasid is zero, SFENCE.VM
* affects address translations for all address spaces. In this case, it
* also affects global mappings, which are described in Section 4.5.1.
*
* Right no we will flush anything
*/
static void sfence()
{
asm volatile ("csrrw t0, sasid, x0\n"
"sfence.vm\n"
"csrw sasid, t0\n"
: : : "t0");
}
/**
* Post processing after a translation was added to a translation table
*
* \param addr virtual address of the translation
* \param size size of the translation
*/
static void translation_added(addr_t const addr, size_t const size)
{
PDBG("not impl");
}
static void translation_added(addr_t const addr, size_t const size);
static void invalidate_tlb_by_pid(unsigned const pid) { sfence(); }
/**
* Return kernel name of the executing CPU
@ -128,11 +146,6 @@ class Genode::Cpu
*/
static unsigned primary_id() { return 0; }
static void flush_tlb_by_pid(unsigned const pid)
{
PDBG("not impl");
}
static addr_t sbadaddr()
{
addr_t addr;
@ -140,20 +153,11 @@ class Genode::Cpu
return addr;
}
static void data_synchronization_barrier() {
asm volatile ("fence\n" : : : "memory"); }
/*************
** Dummies **
*************/
void switch_to(User_context&) { }
static void prepare_proceeding(Cpu_lazy_state *, Cpu_lazy_state *) { }
static void invalidate_instr_caches() { }
static void invalidate_data_caches() { }
static void flush_data_caches() { }
static void flush_data_caches_by_virt_region(addr_t, size_t) { }
static void invalidate_instr_caches_by_virt_region(addr_t, size_t) { }
};
#endif /* _CPU_H_ */

View File

@ -1,6 +1,7 @@
/**
* \brief Calls supported by machine mode (or SBI interface in RISC-V)
* \author Sebastian Sumpf
* \author Martin Stein
* \date 2015-06-14
*/
@ -14,23 +15,29 @@
#ifndef _MACHINE_CALL_H_
#define _MACHINE_CALL_H_
#include <base/stdint.h>
/* base-hw includes */
#include <kernel/interface.h>
namespace Machine {
enum Call {
PUT_CHAR = 0x100, /* output character */
SET_SYS_TIMER = 0x101, /* set timer */
IS_USER_MODE = 0x102, /* check if we are in user mode */
};
using namespace Kernel;
inline void call(Call const number, Genode::addr_t const arg0)
{
register Genode::addr_t a0 asm("a0") = number;;
register Genode::addr_t a1 asm("a1") = arg0;
/**
* SBI calls to machine mode.
*
* 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_is_user_mode() { return 0x102; }
asm volatile ("ecall\n" : : "r"(a0), "r"(a1));
}
inline void put_char(Genode::uint64_t const c) {
call(call_id_put_char(), (Call_arg)c); }
inline void set_sys_timer(addr_t const t) {
call(call_id_set_sys_timer(), (Call_arg)t); }
inline bool is_user_mode() { return call(call_id_is_user_mode()); }
}
#endif /* _MACHINE_CALL_H_ */

View File

@ -11,11 +11,6 @@
* under the terms of the GNU General Public License version 2.
*/
/***************************************************
** Constant values that are pretty commonly used **
***************************************************/
/* alignment constraints */
.set DATA_ACCESS_ALIGNM_LOG2, 2
.set DATA_ACCESS_ALIGNM_LOG2, 3
.set MIN_PAGE_SIZE_LOG2, 12

View File

@ -16,16 +16,11 @@
#ifndef _PIC_H_
#define _PIC_H_
#include <base/printf.h>
namespace Genode
{
/**
* Programmable interrupt controller for core
*/
class Pic;
}
namespace Genode { class Pic; }
/**
* Dummy PIC driver for core
*/
class Genode::Pic
{
public:
@ -39,32 +34,10 @@ class Genode::Pic
NR_OF_IRQ = 15,
};
/**
* Constructor
*/
Pic() { }
/**
* Receive a pending request number 'i'
*/
bool take_request(unsigned & i) {
return true;
}
/**
* Unmask interrupt 'i'
*/
bool take_request(unsigned & i) { return true; }
void unmask(unsigned const i, unsigned) { }
/**
* Mask interrupt 'i'
*/
void mask(unsigned const i) { }
/*************
** Dummies **
*************/
void finish_request() { }
};

View File

@ -44,9 +44,9 @@ class Genode::Serial
struct Stdout : Bitfield<56, 1> { };
};
Machine::call(Machine::PUT_CHAR, Arg::Char::bits(c) |
Arg::Stdout::bits(1) |
Arg::Write_cmd::bits(1));
Machine::put_char(Arg::Char::bits(c) |
Arg::Stdout::bits(1) |
Arg::Write_cmd::bits(1));
}
};

View File

@ -14,19 +14,18 @@
#ifndef _TIMER_H_
#define _TIMER_H_
/* Genode includes */
#include <base/printf.h>
#include <base/stdint.h>
/* Core includes */
#include <machine_call.h>
namespace Genode
{
/**
* Timer driver for core
*/
class Timer;
}
namespace Genode { class Timer; }
/**
* Timer driver for core
*/
struct Genode::Timer
{
private:
@ -62,7 +61,7 @@ struct Genode::Timer
void start_one_shot(unsigned const tics, unsigned /* cpu */)
{
_timeout = _stime() + tics;
asm volatile ("csrw stimecmp, %0" : : "r"(_timeout));
Machine::set_sys_timer(_timeout);
}
/**

View File

@ -14,9 +14,12 @@
#ifndef _TRANSLATION_TABLE_H_
#define _TRANSLATION_TABLE_H_
/* Genode includes */
#include <util/misc_math.h>
#include <util/register.h>
/* Core includes */
#include <cpu.h>
#include <page_flags.h>
#include <translation_table_allocator.h>
@ -186,6 +189,9 @@ class Sv39::Level_x_translation_table
func(vo, pa, sz, _entries[i]);
/* flush cached table entry address */
Cpu::translation_added((addr_t)&_entries[i], sz);
/* check whether we wrap */
if (end < vo) return;
@ -215,7 +221,7 @@ class Sv39::Level_x_translation_table
typename Descriptor::access_t blk_desc =
Block_descriptor::create(flags, pa);
if (Descriptor::valid(desc) && desc != blk_desc)
if (Descriptor::valid(desc) && desc == blk_desc)
throw Double_insertion();
desc = blk_desc;
@ -372,7 +378,7 @@ namespace Sv39 {
Descriptor::access_t blk_desc =
Block_descriptor::create(flags, pa);
if (Descriptor::valid(desc) && desc != blk_desc)
if (Descriptor::valid(desc) && desc == blk_desc)
throw Double_insertion();
desc = blk_desc;
@ -382,7 +388,7 @@ namespace Sv39 {
template <> template <>
struct Level_3_translation_table::Remove_func<None>
{
Remove_func(Translation_table_allocator * /* alloc */) { }
Remove_func(Translation_table_allocator *) { }
void operator () (addr_t const vo,
addr_t const pa,
@ -400,12 +406,12 @@ namespace Genode {
enum {
TABLE_LEVEL_X_SIZE_LOG2 = Sv39::SIZE_LOG2_4K,
CORE_VM_AREA_SIZE = 128 * 1024 * 1024,
CORE_TRANS_TABLE_COUNT =
_count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_1G)
+ _count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_2M),
CORE_VM_AREA_SIZE = 128 * 1024 * 1024,
CORE_TRANS_TABLE_COUNT =
_count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_1G) +
_count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_2M),
};
};
} /* namespace Genode */
}
#endif /* _TRANSLATION_TABLE_H_ */

View File

@ -217,9 +217,6 @@ void Core_platform_pd::_map(addr_t start, addr_t end, bool io_mem)
if (start < VIRT_ADDR_SPACE_START)
start = VIRT_ADDR_SPACE_START;
if (end > VIRT_ADDR_SPACE_START + VIRT_ADDR_SPACE_SIZE)
end = VIRT_ADDR_SPACE_START + VIRT_ADDR_SPACE_SIZE;
size_t size = round_page(end) - start;
try {
_table()->insert_translation(start, start, size, flags, _table_alloc());

View File

@ -0,0 +1,27 @@
/*
* \brief CPU core implementation
* \author Sebastian Sumpf
* \date 2016-02-10
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/printf.h>
#include <kernel/interface.h>
/* Core includes */
#include <cpu.h>
#include <machine_call.h>
void Genode::Cpu::translation_added(addr_t const addr, size_t const size)
{
if (Machine::is_user_mode())
Kernel::update_data_region(addr, size);
else Genode::Cpu::sfence();
}

View File

@ -38,7 +38,8 @@ struct Mstatus : Genode::Register<64>
};
void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd, Genode::Board & board)
void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd,
Genode::Board & board)
{
/* read status register */
Mstatus::access_t mstatus = 0;
@ -50,6 +51,8 @@ void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd, Genode::Board & b
Mstatus::Ie::set(mstatus, 0); /* disable interrupts */
Mstatus::Priv::set(mstatus, Mstatus::SUPERVISOR); /* set supervisor mode */
addr_t client_context_ptr_off = (addr_t)&_mt_client_context_ptr & 0xfff;
addr_t client_context_ptr = exception_entry | client_context_ptr_off;
asm volatile ("csrw sasid, %0\n" /* address space id */
"csrw sptbr, %1\n" /* set page table */
"csrw mstatus, %2\n" /* change mode */
@ -60,7 +63,7 @@ void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd, Genode::Board & b
"r" (core_pd.translation_table()),
"r" (mstatus),
"r" (exception_entry),
"r" (exception_entry | ((addr_t)&_mt_client_context_ptr & 0xfff))
"r" (client_context_ptr)
: "memory");
}

View File

@ -11,6 +11,7 @@
* under the terms of the GNU General Public License version 2.
*/
/* Core includes */
#include <kernel/cpu.h>
extern int _machine_begin, _machine_end;

View File

@ -1,7 +1,7 @@
/*
* \brief Kernel backend for protection domains
* \author Stefan Kalkowski
* \date 2015-03-20
* \author Seastian Sumpf
* \date 2015-06-02
*/
/*
@ -38,7 +38,7 @@ Kernel::Pd::~Pd()
oir->~Object_identity_reference();
/* clean up buffers of memory management */
Cpu::flush_tlb_by_pid(asid);
Cpu::invalidate_tlb_by_pid(asid);
alloc().free(asid);
}

View File

@ -25,7 +25,7 @@ void Thread::exception(unsigned const cpu)
return;
switch(cpu_exception) {
case SUPERVISOR_CALL:
case ECALL_FROM_USER:
_call();
ip += 4; /* set to next instruction */
break;
@ -55,11 +55,14 @@ void Thread::_mmu_exception()
void Thread::_call_update_pd()
{
asm volatile ("sfence.vm");
Cpu::sfence();
}
void Thread::_call_update_data_region() { }
void Thread::_call_update_data_region()
{
Cpu::sfence();
}
void Thread::_call_update_instr_region() { }

View File

@ -13,16 +13,9 @@
/* core includes */
#include <kernel/thread.h>
#include <kernel/pd.h>
#include <kernel/kernel.h>
using namespace Kernel;
/*************************
** Kernel::Thread_base **
*************************/
Thread_base::Thread_base(Thread * const t)
:
_fault(t),
@ -31,35 +24,3 @@ Thread_base::Thread_base(Thread * const t)
_fault_writes(0),
_fault_signal(0)
{ }
/*************************
** Kernel::Cpu_context **
*************************/
void Kernel::Cpu_context::_init(size_t const stack_size, addr_t const table)
{
/*
* the stack pointer already contains the stack base address
* of all CPU's kernel stacks, on this uni-processor platform
* it is sufficient to increase it by the stack's size
*/
sp = sp + stack_size;
}
/*************************
** CPU-state utilities **
*************************/
typedef Thread_reg_id Reg_id;
static addr_t const _cpu_state_regs[] = { };
addr_t const * cpu_state_regs() { return _cpu_state_regs; }
size_t cpu_state_regs_length()
{
return sizeof(_cpu_state_regs)/sizeof(_cpu_state_regs[0]);
}

View File

@ -1,19 +1,24 @@
/*
* \brief Transition between kernel/userland
* \date 2011-11-15
* \author Sebastian Sumpf
* \author Mark Vels
* \date 2015-06-22
*/
/*
* Copyright (C) 2011-2015 Genode Labs GmbH
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
.set USER_MODE, 0
.set SUPERVISOR_MODE, 1
.set MACHINE_MODE, 3
.set CALL_PUT_CHAR, 0xff
.set CALL_PUT_CHAR, 0x100
.set CALL_SET_SYS_TIMER, 0x101
.set CALL_IS_USER_MODE, 0x102
.set CPU_IP, 0
.set CPU_EXCEPTION, 8
@ -22,6 +27,42 @@
.set CPU_SASID, 33*8
.set CPU_SPTBR, 34*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
@ -45,48 +86,171 @@
.endif
.endm
.macro _put_char mode
.macro _handle_trap mode
/* check if ecall (8 - 11) */
csrr t0, mcause
li t1, 8
bltu t0, t1, 9f
li t1, 12
bgtu t0, t1, 9f
/* check for put char ecall number */
li t1, CALL_PUT_CHAR
bne t1, a0, 9f
# 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
/* output character */
csrw mtohost, a1
# 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
eret
.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
beqz t0, 1b
bne zero,t0, 3b
j 9f
/* advance epc */
# Future implementation check for more interrupt sources
# to handle here.....
9:
#******** IRQ OUT *********
_restore_scratch_registers \mode
eret
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_IS_USER_MODE
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:
mv a0, x0
.if \mode == USER_MODE
li a0, 1
.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
eret
9:
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.
*/
##
# 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.
#
@ -94,42 +258,42 @@
.global _machine_begin
_machine_begin:
/* 0x100 user mode */
# 0x100 user mode
j user_trap
.space 0x3c
/* 0x140 supervisor */
# 0x140 supervisor
j supervisor_trap
.space 0x3c
/* 0x180 hypervisor */
# 0x180 hypervisor
1: j 1b
.space 0x3c
/* 0x1c0 machine */
# 0x1c0 machine
j machine_trap
.space 0x38
/* 0x1fc non-maksable interrupt */
# 0x1fc non-maksable interrupt
1: j 1b
user_trap:
_save_scratch_registers USER_MODE
_put_char USER_MODE
_handle_trap USER_MODE
_restore_scratch_registers USER_MODE
mrts
supervisor_trap:
_save_scratch_registers SUPERVISOR_MODE
_put_char SUPERVISOR_MODE
_handle_trap SUPERVISOR_MODE
j fault
machine_trap:
_save_scratch_registers MACHINE_MODE
_put_char MACHINE_MODE
_handle_trap MACHINE_MODE
j fault
fault:j fault /* TODO: handle trap from supervisor or machine mode */
fault:j fault # TODO: handle trap from supervisor or machine mode
.global _machine_end
_machine_end:
@ -138,23 +302,23 @@ _machine_end:
.global _mt_begin
_mt_begin:
/* 0x100 user mode */
j _mt_kernel_entry_pic
# 0x100 user mode
j _mt_kernel_entry_pic
.space 0x3c
/* 0x140 supervisor */
# 0x140 supervisor
1: j 1b
.space 0x3c
/* 0x180 hypervisor */
# 0x180 hypervisor
1: j 1b
.space 0x3c
/* 0x1c0 machine */
# 0x1c0 machine
1: j 1b
.space 0x38
/* 0x1fc non-maksable interrupt */
# 0x1fc non-maksable interrupt
1: j 1b
/* space for a client context-pointer per CPU */
.p2align 2
.p2align 3
.global _mt_client_context_ptr
_mt_client_context_ptr:
.space 8
@ -172,22 +336,29 @@ _mt_master_context_end:
.global _mt_kernel_entry_pic
_mt_kernel_entry_pic:
/* master context */
# master context
csrrw x31, sscratch, x31
addi x31, x31, 8
/* save x29, x30 in master */
# save x29, x30 in master
sd x29, 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)
csrw sasid, x29
csrw sptbr, x30
/* save x29 - x31 in user context */
#
# 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)
@ -200,24 +371,24 @@ _mt_kernel_entry_pic:
csrr x30, sscratch /* x31 */
sd x30, CPU_X1 + 8 * 30(x29)
/* save x1 - x28 */
# 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 */
# trap reason
csrr x30, scause
sd x30, CPU_EXCEPTION(x29)
/* ip */
# ip
csrr x30, sepc
sd x30, CPU_IP(x29)
/* load kernel stack and ip */
# load kernel stack and ip
ld sp, CPU_SP(x31)
ld x30, CPU_IP(x31)
/* restore scratch */
# restore scratch
addi x31, x31, -8
csrw sscratch, x31
@ -227,42 +398,50 @@ _mt_kernel_entry_pic:
.global _mt_user_entry_pic
_mt_user_entry_pic:
/* client context pointer */
# client context pointer
csrr x30, sscratch
ld x30, (x30)
/* set return IP */
# set return IP
ld x31, CPU_IP(x30)
csrw sepc, x31
/* restore x1-x28 */
# 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 */
# save x29, x30, x31 to master context
csrr x29, sscratch
addi x29, x29, 8 /* master context */
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 */
# switch page table
ld x31, CPU_SASID(x30)
ld x30, CPU_SPTBR(x30)
csrw sasid, x31
csrw sptbr, x30
/* restore x29 - x31 from master context */
#
# 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
eret
/* end of the mode transition code */
# end of the mode transition code
.global _mt_end
_mt_end:

View File

@ -18,40 +18,22 @@
using namespace Genode;
Cpu::User_context::User_context() { }
Native_region * Platform::_ram_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ 0, 128 * 1024 * 1024 }
};
static Native_region _regions[] = { { 0, 128 * 1024 * 1024 } };
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Cpu::User_context::User_context() { }
Native_region * Platform::_core_only_mmio_regions(unsigned) { return 0; }
void Platform::_init_io_port_alloc()
{ }
void Platform::_init_io_port_alloc() { }
void Platform::_init_io_mem_alloc() { }
void Platform::_init_io_mem_alloc()
{ }
void Platform::setup_irq_mode(unsigned, unsigned, unsigned) { }
void Platform::setup_irq_mode(unsigned, unsigned, unsigned) { PDBG("not impl");}
long Platform::irq(long const user_irq)
{
PDBG("not impl");
return 0;
}
long Platform::irq(long const user_irq) { return 0; }

View File

@ -14,6 +14,10 @@ LIBS += core
# add C++ sources
SRC_CC += kernel/test.cc
#
# On RISCV we need a link address for core that differs from that of the other
# components.
#
ifneq ($(filter riscv, $(SPECS)),)
LD_TEXT_ADDR = $(CORE_LD_TEXT_ADDR)
endif