hw: run core threads in privileged mode

* introduce new syscall (core-only) to create privileged threads
* take the privilege level of the thread into account
  when doing a context switch
* map kernel segment as accessable for privileged code only

Ref #2091
This commit is contained in:
Stefan Kalkowski 2017-08-30 11:59:35 +02:00 committed by Christian Helmuth
parent 7e47fa58b3
commit ca60e24ad9
36 changed files with 222 additions and 112 deletions

View File

@ -1 +1 @@
10f40152b12a9fd068f88a587e84e342b707698e
30243a733d49c8545adbb230df7e01f8a8fc12a0

View File

@ -2,7 +2,7 @@ LICENSE := BSD-3-Clause
VERSION := git
DOWNLOADS := bbl.git
URL(bbl) = https://github.com/ssumpf/bbl-lite.git
REV(bbl) = 0f86d104c470cfad70a9bc049865edb2ab0c4710
URL(bbl) = https://github.com/skalk/bbl-lite.git
REV(bbl) = 20e03dfa317747dd39175f9fc3c15c50b702ac04
DIR(bbl) = src/lib/bbl

View File

@ -120,9 +120,9 @@ Mapping Platform::_load_elf()
phys = dst;
}
//FIXME: set read-only, privileged and global accordingly
//FIXME: set read-only accordingly
Page_flags flags{RW, segment.flags().x ? EXEC : NO_EXEC,
USER, GLOBAL, RAM, CACHED};
KERN, GLOBAL, RAM, CACHED};
Mapping m((addr_t)phys, (addr_t)segment.start(), size, flags);
/*

View File

@ -24,16 +24,17 @@ void Bootstrap::Cpu::enable_mmu_and_caches(Genode::addr_t table)
/* do not use domains, but permission bits in table */
Dacr::write(Dacr::D0::bits(1));
Ttbcr::write(0);
Ttbcr::write(1);
Ttbr::access_t ttbr0 = Ttbr::Ba::masked(table);
Ttbr::Rgn::set(ttbr0, Ttbr::CACHEABLE);
Ttbr::access_t ttbr = Ttbr::Ba::masked(table);
Ttbr::Rgn::set(ttbr, Ttbr::CACHEABLE);
if (Mpidr::read()) { /* check for SMP system */
Ttbr::Irgn::set(ttbr0, Ttbr::CACHEABLE);
Ttbr::S::set(ttbr0, 1);
Ttbr::Irgn::set(ttbr, Ttbr::CACHEABLE);
Ttbr::S::set(ttbr, 1);
} else
Ttbr::C::set(ttbr0, 1);
Ttbr0::write(ttbr0);
Ttbr::C::set(ttbr, 1);
Ttbr0::write(ttbr);
Ttbr1::write(ttbr);
Sctlr::access_t sctlr = Sctlr::read();
Sctlr::C::set(sctlr, 1);

View File

@ -12,6 +12,7 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#include <platform.h>
#include <hw/spec/riscv/cpu.h>
using namespace Board;
@ -21,8 +22,6 @@ Bootstrap::Platform::Board::Board()
void Bootstrap::Platform::enable_mmu()
{
asm volatile ("csrw sptbr, %0\n" /* set asid | page table */
:
: "r" ((addr_t)core_pd->table_base >> 12)
: "memory");
using Sptbr = Hw::Riscv_cpu::Sptbr;
Sptbr::write(Sptbr::Ppn::masked((addr_t)core_pd->table_base >> 12));
}

View File

@ -61,8 +61,8 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
/* map the dataspace's physical pages to corresponding virtual addresses */
unsigned num_pages = page_rounded_size >> get_page_size_log2();
Page_flags const flags { ds->writable() ? RW : RO, NO_EXEC, USER,
NO_GLOBAL, ds->io_mem() ? DEVICE : RAM,
Page_flags const flags { ds->writable() ? RW : RO, NO_EXEC, KERN,
GLOBAL, ds->io_mem() ? DEVICE : RAM,
ds->cacheability() };
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages, flags))
return nullptr;

View File

@ -59,6 +59,7 @@ namespace Kernel
constexpr Call_arg call_id_new_obj() { return 121; }
constexpr Call_arg call_id_delete_obj() { return 122; }
constexpr Call_arg call_id_cancel_thread_blocking() { return 123; }
constexpr Call_arg call_id_new_core_thread() { return 124; }
/**
* Update locally effective domain configuration to in-memory state

View File

@ -37,8 +37,6 @@ extern "C" void _core_start(void);
using namespace Kernel;
bool Thread::_core() const { return pd() == core_pd(); }
void Thread::_signal_context_kill_pending()
{
assert(_state == ACTIVE);
@ -170,6 +168,16 @@ void Thread::_call_new_thread()
}
void Thread::_call_new_core_thread()
{
void * const p = (void *)user_arg_1();
char const * const label = (char *)user_arg_2();
Core_object<Thread> * co =
Genode::construct_at<Core_object<Thread> >(p, label);
user_arg_0(co->core_capid());
}
void Thread::_call_thread_quota()
{
Thread * const thread = (Thread *)user_arg_1();
@ -234,7 +242,7 @@ void Thread::_call_restart_thread()
return; }
Thread * const thread = pd()->cap_tree().find<Thread>(user_arg_1());
if (!thread || (!_core() && (pd() != thread->pd()))) {
if (!thread || (!_core && (pd() != thread->pd()))) {
warning(*this, ": failed to lookup thread ", (unsigned)user_arg_1(),
" to restart it");
_die();
@ -567,7 +575,7 @@ void Thread::_call()
case call_id_time(): user_arg_0(Cpu_job::time()); return;
default:
/* check wether this is a core thread */
if (!_core()) {
if (!_core) {
Genode::warning(*this, ": not entitled to do kernel call");
_die();
return;
@ -576,6 +584,7 @@ void Thread::_call()
/* switch over kernel calls that are restricted to core */
switch (call_id) {
case call_id_new_thread(): _call_new_thread(); return;
case call_id_new_core_thread(): _call_new_core_thread(); return;
case call_id_thread_quota(): _call_thread_quota(); return;
case call_id_delete_thread(): _call_delete<Thread>(); return;
case call_id_start_thread(): _call_start_thread(); return;
@ -614,11 +623,11 @@ void Thread::_call()
Thread::Thread(unsigned const priority, unsigned const quota,
char const * const label)
char const * const label, bool core)
:
Cpu_job(priority, quota), _fault_pd(0), _fault_addr(0),
_fault_writes(0), _state(AWAITS_START),
_signal_receiver(0), _label(label)
_signal_receiver(0), _label(label), _core(core)
{
_init();
}
@ -640,7 +649,7 @@ Genode::uint8_t __initial_stack_base[DEFAULT_STACK_SIZE];
*****************/
Core_thread::Core_thread()
: Core_object<Thread>(Cpu_priority::MAX, 0, "core")
: Core_object<Thread>("core")
{
using namespace Genode;

View File

@ -63,6 +63,7 @@ class Kernel::Thread
capid_t _timeout_sigid = 0;
bool _paused = false;
bool _cancel_next_await_signal = false;
bool const _core = false;
void _init();
@ -83,11 +84,6 @@ class Kernel::Thread
int _route_event(unsigned const event_id,
Signal_context * const signal_context_id);
/**
* Return wether this is a core thread
*/
bool _core() const;
/**
* Switch from an inactive state to the active state
*/
@ -138,6 +134,7 @@ class Kernel::Thread
*********************************************************/
void _call_new_thread();
void _call_new_core_thread();
void _call_thread_quota();
void _call_start_thread();
void _call_stop_thread();
@ -232,9 +229,18 @@ class Kernel::Thread
* \param priority scheduling priority
* \param quota CPU-time quota
* \param label debugging label
* \param core whether it is a core thread or not
*/
Thread(unsigned const priority, unsigned const quota,
char const * const label);
char const * const label, bool core = false);
/**
* Constructor for core/kernel thread
*
* \param label debugging label
*/
Thread(char const * const label)
: Thread(Cpu_priority::MAX, 0, label, true) { }
/**
* Syscall to create a thread
@ -254,6 +260,20 @@ class Kernel::Thread
(Call_arg)quota, (Call_arg)label);
}
/**
* Syscall to create a core thread
*
* \param p memory donation for the new kernel thread object
* \param label debugging label of the new thread
*
* \retval capability id of the new kernel object
*/
static capid_t syscall_create(void * const p, char const * const label)
{
return call(call_id_new_core_thread(), (Call_arg)p,
(Call_arg)label);
}
/**
* Syscall to destroy a thread
*

View File

@ -81,8 +81,7 @@ void Hw::Address_space::flush(addr_t virt, size_t size, Core_local_addr)
Hw::Address_space::Address_space(Kernel::Pd & pd, Page_table & tt,
Page_table::Allocator & tt_alloc)
: _tt(tt), _tt_phys(Platform::core_page_table()),
_tt_alloc(tt_alloc), _kernel_pd(pd) {
Kernel::mtc()->map(_tt, _tt_alloc); }
_tt_alloc(tt_alloc), _kernel_pd(pd) { }
Hw::Address_space::Address_space(Kernel::Pd & pd)

View File

@ -57,7 +57,7 @@ void Platform_thread::quota(size_t const quota) {
Platform_thread::Platform_thread(const char * const label,
Native_utcb * utcb)
: Kernel_object<Kernel::Thread>(true, Kernel::Cpu_priority::MAX, 0, _label),
: Kernel_object<Kernel::Thread>(true, _label),
_pd(Kernel::core_pd()->platform_pd()),
_pager(nullptr),
_utcb_core_addr(utcb),

View File

@ -13,12 +13,12 @@
#include <spec/arm/cpu_support.h>
Genode::Arm_cpu::User_context::User_context()
void Genode::Arm_cpu::User_context::init(bool privileged)
{
using Psr = Arm_cpu::Psr;
Psr::access_t v = 0;
Psr::M::set(v, Psr::M::USR);
Psr::M::set(v, privileged ? Psr::M::SYS : Psr::M::USR);
Psr::F::set(v, 1);
Psr::A::set(v, 1);
cpsr = v;

View File

@ -13,12 +13,12 @@
#include <spec/arm/cpu_support.h>
Genode::Arm_cpu::User_context::User_context()
void Genode::Arm_cpu::User_context::init(bool privileged)
{
using Psr = Genode::Arm_cpu::Psr;
Psr::access_t v = 0;
Psr::M::set(v, Psr::M::USR);
Psr::M::set(v, privileged ? Psr::M::SYS : Psr::M::USR);
Psr::I::set(v, 1);
Psr::A::set(v, 1);
cpsr = v;

View File

@ -107,7 +107,7 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
*/
struct User_context : Context
{
User_context();
void init(bool privileged);
/**
* Support for kernel calls

View File

@ -31,5 +31,8 @@ void Kernel::Cpu::init(Kernel::Pic &pic)
void Kernel::Cpu_domain_update::_domain_update()
{
/* flush TLB by ASID */
Cpu::Tlbiasid::write(_domain_id);
if (_domain_id)
Cpu::Tlbiasid::write(_domain_id);
else
Cpu::Tlbiall::write(0);
}

View File

@ -28,6 +28,7 @@ Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0)
ip = (addr_t)&_main;
sp = (addr_t)&_stack[stack_size];
init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid);
init(true);
}

View File

@ -18,7 +18,11 @@
using namespace Kernel;
void Kernel::Thread::_init() { cpu_exception = RESET; }
void Kernel::Thread::_init()
{
init(_core);
cpu_exception = RESET;
}
void Thread::exception(unsigned const cpu)
@ -92,7 +96,7 @@ void Kernel::Thread::_call_update_data_region()
* address space so we can use virtual addresses of the caller. Up
* until then we apply operations to caches as a whole instead.
*/
if (!_core()) {
if (!_core) {
cpu->clean_invalidate_data_cache();
return;
}
@ -116,7 +120,7 @@ void Kernel::Thread::_call_update_instr_region()
* address space so we can use virtual addresses of the caller. Up
* until then we apply operations to caches as a whole instead.
*/
if (!_core()) {
if (!_core) {
cpu->clean_invalidate_data_cache();
cpu->invalidate_instr_cache();
return;

View File

@ -20,5 +20,8 @@ void Kernel::Thread::_call_update_pd()
Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id());
cpu->invalidate_instr_cache();
cpu->clean_invalidate_data_cache();
Cpu::Tlbiasid::write(pd->asid); /* flush TLB by ASID */
if (pd->asid)
Cpu::Tlbiasid::write(pd->asid); /* flush TLB by ASID */
else
Cpu::Tlbiall::write(0);
}

View File

@ -28,5 +28,8 @@ Kernel::Lock & Kernel::data_lock() {
void Kernel::Cpu_domain_update::_domain_update()
{
/* flush TLB by ASID */
Cpu::Tlbiasid::write(_domain_id);
if (_domain_id)
Cpu::Tlbiasid::write(_domain_id);
else
Cpu::Tlbiall::write(0);
}

View File

@ -154,10 +154,10 @@ class Genode::Cpu : public Arm_v7_cpu
*/
struct User_context : Context
{
User_context()
void init(bool privileged)
{
Psr::access_t v = 0;
Psr::M::set(v, Psr::M::USR);
Psr::M::set(v, privileged ? Psr::M::SYS : Psr::M::USR);
Psr::F::set(v, 1);
Psr::A::set(v, 1);
cpsr = v;

View File

@ -19,6 +19,8 @@
#include <cpu/cpu_state.h>
#include <util/register.h>
#include <kernel/interface.h>
#include <hw/spec/riscv/cpu.h>
namespace Genode
{
@ -32,40 +34,37 @@ namespace Genode
namespace Kernel { class Pd; }
class Genode::Cpu
class Genode::Cpu : public Hw::Riscv_cpu
{
public:
static constexpr addr_t mtc_size = 0x1000;
static constexpr addr_t exception_entry = (~0ULL) & ~(0xfff);
static constexpr addr_t exception_entry = 0xffffffc000000000;
/**
* Extend basic CPU state by members relevant for 'base-hw' only
*/
struct Context : Cpu_state
{
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::Ppn::get(sptbr) << 12; }
addr_t translation_table() const {
return Sptbr::Ppn::get(sptbr) << 12; }
/**
* Assign translation-table base 'table'
*/
void translation_table(addr_t const table) { Sptbr::Ppn::set(sptbr, table >> 12); }
void translation_table(addr_t const table) {
Sptbr::Ppn::set(sptbr, table >> 12); }
/**
* Assign protection domain
*/
void protection_domain(Genode::uint8_t const id) { Sptbr::Asid::set(sptbr, id); }
void protection_domain(Genode::uint8_t const id) {
Sptbr::Asid::set(sptbr, id); }
};
struct Pd
@ -153,18 +152,17 @@ class Genode::Cpu
*/
static unsigned primary_id() { return 0; }
static addr_t sbadaddr()
{
addr_t addr;
asm volatile ("csrr %0, sbadaddr\n" : "=r"(addr));
return addr;
}
/*************
** Dummies **
*************/
void switch_to(User_context&) { }
void switch_to(User_context& context)
{
bool user = Sptbr::Asid::get(context.sptbr);
Sstatus::access_t v = Sstatus::read();
Sstatus::Spp::set(v, user ? 0 : 1);
Sstatus::write(v);
}
};
#endif /* _CORE__SPEC__RISCV__CPU_H_ */

View File

@ -18,6 +18,8 @@
.set CPU_SP, 3*8
.set CPU_SPTBR, 33*8
.section ".text.crt0"
.p2align 12
.global _mt_begin
_mt_begin:

View File

@ -25,12 +25,9 @@ void Kernel::Cpu::init(Kernel::Pic &pic/*, Kernel::Pd & core_pd,
{
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 stvec, %0\n" /* exception vector */
"csrw sscratch,%1\n" /* master conext ptr */
:
: "r" (exception_entry),
"r" (client_context_ptr)
: "memory");
asm volatile ( "csrw sscratch,%0\n" /* master conext ptr */
:: "r" (client_context_ptr) : "memory");
Stvec::write(exception_entry);
}

View File

@ -26,6 +26,7 @@ void Thread::exception(unsigned const cpu)
switch(cpu_exception) {
case ECALL_FROM_USER:
case ECALL_FROM_SUPERVISOR:
_call();
ip += 4; /* set to next instruction */
break;
@ -36,7 +37,7 @@ void Thread::exception(unsigned const cpu)
break;
default:
Genode::error(*this, ": unhandled exception ", cpu_exception,
" at ip=", (void*)ip, " addr=", Genode::Hex(Cpu::sbadaddr()));
" at ip=", (void*)ip, " addr=", Genode::Hex(Cpu::Sbadaddr::read()));
_die();
}
}
@ -46,7 +47,7 @@ void Thread::_mmu_exception()
{
_become_inactive(AWAITS_RESTART);
_fault_pd = (addr_t)_pd->platform_pd();
_fault_addr = Cpu::sbadaddr();
_fault_addr = Cpu::Sbadaddr::read();
if (_pager) _pager->submit(1);
}

View File

@ -1,16 +0,0 @@
/*
* \brief Macros that are used by multiple assembly files
* \author Sebastian Sumpf
* \date 2015-06-02
*/
/*
* 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.
*/
/* alignment constraints */
.set DATA_ACCESS_ALIGNM_LOG2, 3
.set MIN_PAGE_SIZE_LOG2, 12

View File

@ -15,13 +15,11 @@
#define _CORE__SPEC__RISCV__TRANSLATION_TABLE_H_
#include <hw/spec/riscv/page_table.h>
#include <kernel/interface.h>
#include <cpu.h>
template <typename E, unsigned B, unsigned S>
void Sv39::Level_x_translation_table<E, B, S>::_translation_added(addr_t addr,
size_t size)
{
Kernel::update_data_region(addr, size);
}
size_t size) {
Genode::Cpu::sfence(); }
#endif /* _CORE__SPEC__RISCV__TRANSLATION_TABLE_H_ */

View File

@ -31,12 +31,10 @@ void Genode::Cpu::Context::init(addr_t const table, bool core)
cr3 = Cr3::init(table);
/*
* Enable interrupts for all threads, set I/O privilege level
* (IOPL) to 3 for core threads to allow UART access.
*/
/* enable interrupts for all threads */
eflags = EFLAGS_IF_SET;
if (core) eflags |= EFLAGS_IOPL_3;
cs = core ? 0x8 : 0x1b;
ss = core ? 0x10 : 0x23;
}

View File

@ -29,6 +29,8 @@ Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0)
Cpu_job::cpu(cpu);
ip = (addr_t)&_main;
sp = (addr_t)&_stack[stack_size];
cs = 0x8;
ss = 0x10;
init((addr_t)core_pd()->translation_table(), true);
}

View File

@ -29,7 +29,9 @@
.set ERRCODE_OFFSET, 17 * 8
.set FLAGS_OFFSET, 18 * 8
.set TRAPNO_OFFSET, 19 * 8
.set CR3_OFFSET, 21 * 8
.set CS_OFFSET, 20 * 8
.set SS_OFFSET, 22 * 8
.set CR3_OFFSET, 23 * 8
/* tss segment constants */
.set TSS_LIMIT, 0x68
@ -210,11 +212,11 @@
mov (%rax), %rax
_load_address _mt_buffer rsp
add $BUFFER_SIZE, %rsp
pushq $0x23
pushq SS_OFFSET(%rax)
pushq SP_OFFSET(%rax)
pushq FLAGS_OFFSET(%rax)
pushq $0x1b
pushq CS_OFFSET(%rax)
pushq (%rax)
/* Restore register values from client context */

View File

@ -58,15 +58,15 @@ struct Hw::Page_flags
namespace Hw {
static constexpr Page_flags PAGE_FLAGS_KERN_IO
{ RW, NO_EXEC, USER, NO_GLOBAL, DEVICE, Genode::UNCACHED };
{ RW, NO_EXEC, KERN, GLOBAL, DEVICE, Genode::UNCACHED };
static constexpr Page_flags PAGE_FLAGS_KERN_DATA
{ RW, EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED };
{ RW, EXEC, KERN, GLOBAL, RAM, Genode::CACHED };
static constexpr Page_flags PAGE_FLAGS_KERN_TEXT
{ RW, EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED };
{ RW, EXEC, KERN, GLOBAL, RAM, Genode::CACHED };
static constexpr Page_flags PAGE_FLAGS_KERN_EXCEP
{ RW, EXEC, USER, GLOBAL, RAM, Genode::CACHED };
{ RW, EXEC, KERN, GLOBAL, RAM, Genode::CACHED };
static constexpr Page_flags PAGE_FLAGS_UTCB
{ RW, NO_EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED };
{ RW, NO_EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED };
}
#endif /* _SRC__LIB__HW__PAGE_FLAGS_H_ */

View File

@ -25,7 +25,7 @@ static constexpr addr_t USER_START = Genode::user_utcb_main_thread()
static constexpr addr_t KERNEL_START = 0xffffffc000000000UL;
Memory_region const Hw::Mm::user() {
return Memory_region(USER_START, KERNEL_START - USER_START); }
return Memory_region(USER_START, 0x800000000000 - USER_START); }
Memory_region const Hw::Mm::core_heap() {
return Memory_region(0xffffffd000000000UL, 0x1000000000UL); }

View File

@ -230,6 +230,7 @@ struct Hw::Arm_cpu
SVC = 19,
MON = 22,
HYP = 26,
SYS = 31,
};
};

View File

@ -0,0 +1,46 @@
/*
* \brief CPU definitions for RiscV
* \author Stefan Kalkowski
* \date 2017-09-14
*/
/*
* 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 _SRC__LIB__HW__SPEC__RISCV__CPU_H_
#define _SRC__LIB__HW__SPEC__RISCV__CPU_H_
#include <hw/spec/riscv/register_macros.h>
namespace Hw { struct Riscv_cpu; }
struct Hw::Riscv_cpu
{
/**************************
** Supervisor registers **
**************************/
/* Supervisor-mode status Register */
RISCV_SUPERVISOR_REGISTER(Sstatus, sstatus,
struct Spp : Bitfield<8,1> { }; /* prior privilege level */
);
/* Supervisor Trap Vector Base Address Register */
RISCV_SUPERVISOR_REGISTER(Stvec, stvec);
/* Supervisor Bad Address Register */
RISCV_SUPERVISOR_REGISTER(Sbadaddr, sbadaddr);
/* Supervisor Page-Table Base Register */
RISCV_SUPERVISOR_REGISTER(Sptbr, sptbr,
struct Ppn : Bitfield<0, 38> { };
struct Asid : Bitfield<38, 26> { };
);
};
#endif /* _SRC__LIB__HW__SPEC__RISCV__CPU_H_ */

View File

@ -0,0 +1,36 @@
/*
* \brief CPU register macros for RiscV
* \author Stefan Kalkowski
* \date 2017-09-14
*/
/*
* 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 _SRC__LIB__HW__SPEC__RISCV__REGISTER_MACROS_H_
#define _SRC__LIB__HW__SPEC__RISCV__REGISTER_MACROS_H_
#include <util/register.h>
#define RISCV_SUPERVISOR_REGISTER(name, reg, ...) \
struct name : Genode::Register<64> \
{ \
static access_t read() \
{ \
access_t v; \
asm volatile ("csrr %0, " #reg : "=r" (v) :: ); \
return v; \
} \
\
static void write(access_t const v) { \
asm volatile ("csrw " #reg ", %0" :: "r" (v) : ); } \
\
__VA_ARGS__; \
};
#endif /* _SRC__LIB__HW__SPEC__ARM__REGISTER_MACROS_H_ */

View File

@ -55,6 +55,8 @@ struct Genode::Cpu_state
addr_t errcode = 0;
addr_t eflags = 0;
addr_t trapno = RESET;
addr_t cs = 0;
addr_t ds = 0;
addr_t ss = 0;
};

View File

@ -6,14 +6,14 @@ proc binary_name_timer { } { return "hw_timer_drv" }
proc run_boot_string { } { return "\nkernel initialized" }
proc bootstrap_link_address { } {
if {[have_spec "odroid_xu"]} { return "0x81000000" }
if {[have_spec "odroid_xu"]} { return "0x88000000" }
if {[have_spec "pbxa9"]} { return "0x70000000" }
if {[have_spec "usb_armory"]} { return "0x72000000" }
if {[have_spec "x86_64"]} { return "0x00200000" }
if {[have_spec "wand_quad"]} { return "0x10001000" }
if {[have_spec "imx53_qsb"]} { return "0x70010000" }
if {[have_spec "arndale"]} { return "0x81000000" }
if {[have_spec "panda"]} { return "0x81000000" }
if {[have_spec "arndale"]} { return "0x88000000" }
if {[have_spec "panda"]} { return "0x88000000" }
if {[have_spec "zynq"]} { return "0x00100000" }
if {[have_spec "riscv"]} { return "0x81000000" }
if {[have_spec "rpi"]} { return "0x00800000" }