riscv: Use Qemu and update to ISA v1.10

- remove Spike/BBL support in favour of Qemu (>=4.2.1)
- add 'riscv_qemu' board, remove 'spike' board'
- update to privileged ISA v1.10 (from v1.9.1)
- use direct system calls for privileged core threads (they call into
  the kernel and don't use mode changing system calls, i.e. 'ecall',
  semantics)
- use 'OpenSBI' semtantics for SBI calls (to machine mode) instead of
  BBL

issue #4012
This commit is contained in:
Sebastian Sumpf 2021-02-10 08:31:39 +01:00 committed by Norman Feske
parent 18e282ab8a
commit fd0e6685fc
46 changed files with 393 additions and 453 deletions

View File

@ -1 +0,0 @@
0x81000000

View File

@ -0,0 +1 @@
0x80200000

View File

@ -23,20 +23,23 @@ namespace Genode { struct Cpu_state; }
struct Genode::Cpu_state
{
enum Cpu_exception {
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,
ECALL_FROM_USER = 8,
ECALL_FROM_SUPERVISOR = 9,
ECALL_FROM_HYPERVISOR = 10,
ECALL_FROM_MACHINE = 11,
RESET = 16,
IRQ_FLAG = 1UL << 63,
INSTRUCTION_UNALIGNED = 0,
INSTRUCTION_ACCESS_FAULT = 1,
INSTRUCTION_ILLEGAL = 2,
BREAKPOINT = 3,
LOAD_UNALIGNED = 4,
LOAD_ACCESS_FAULT = 5,
STORE_UNALIGNED = 6,
STORE_ACCESS_FAULT = 7,
ECALL_FROM_USER = 8,
ECALL_FROM_SUPERVISOR = 9,
ECALL_FROM_HYPERVISOR = 10,
ECALL_FROM_MACHINE = 11,
INSTRUCTION_PAGE_FAULT = 12,
LOAD_PAGE_FAULT = 13,
STORE_PAGE_FAULT = 15,
RESET = 16,
IRQ_FLAG = 1UL << 63,
};
addr_t ip = 0;
@ -73,6 +76,12 @@ struct Genode::Cpu_state
addr_t t5 = 0;
addr_t t6 = 0;
/*
* Save last instruction fetch-fault needed for MIG-V stval quirk in
* kernel/riscv/thread.cc
*/
addr_t last_fetch_fault = 0;
bool is_irq() { return cpu_exception & IRQ_FLAG; }
unsigned irq() { return cpu_exception ^ IRQ_FLAG; }
};

View File

@ -7,8 +7,6 @@
include $(BASE_DIR)/lib/mk/base-common.inc
LIBS += syscall-hw
SRC_CC += rpc_dispatch_loop.cc
SRC_CC += thread.cc thread_myself.cc thread_bootstrap.cc
SRC_CC += signal_transmitter.cc

View File

@ -9,4 +9,4 @@ SRC_CC += stack_area_addr.cc
SRC_CC += native_utcb.cc
SRC_CC += platform.cc
LIBS += startup-hw base-hw-common cxx timeout-hw
LIBS += startup-hw base-hw-common syscall-hw cxx timeout-hw

View File

@ -7,6 +7,8 @@
# add include paths
REP_INC_DIR += src/core/spec/arm
LIBS += syscall-hw
# add C++ sources
SRC_CC += spec/32bit/memory_map.cc
SRC_CC += spec/arm/kernel/cpu.cc

View File

@ -1,5 +1,7 @@
REP_INC_DIR += src/core/spec/arm_v8
LIBS += syscall-hw
# add C++ sources
SRC_CC += kernel/cpu_mp.cc
SRC_CC += spec/64bit/memory_map.cc

View File

@ -0,0 +1,10 @@
INC_DIR += $(REP_DIR)/src/bootstrap/board/riscv_qemu
SRC_CC += bootstrap/spec/riscv/platform.cc
SRC_S += bootstrap/spec/riscv/crt0.s
SRC_CC += lib/base/riscv/kernel/interface.cc
SRC_CC += spec/64bit/memory_map.cc
vpath spec/64bit/memory_map.cc $(REP_DIR)/src/lib/hw
include $(REP_DIR)/lib/mk/bootstrap-hw.inc

View File

@ -1,17 +0,0 @@
#
# evaluate bbl_dir immediately, otherwise it won't recognize
# missing ports when checking library dependencies
#
REP_INC_DIR += src/bootstrap/spec/riscv
INC_DIR += $(call select_from_ports,bbl)/src/lib/bbl
SRC_CC += bootstrap/spec/riscv/platform.cc
SRC_CC += lib/base/riscv/kernel/interface.cc
SRC_CC += spec/64bit/memory_map.cc
SRC_S += bootstrap/spec/riscv/crt0.s
vpath spec/64bit/memory_map.cc $(call select_from_repositories,src/lib/hw)
include $(call select_from_repositories,lib/mk/bootstrap-hw.inc)

View File

@ -1,11 +1,4 @@
#
# evaluate bbl_dir immediately, otherwise it won't recognize
# missing ports when checking library dependencies
#
REP_INC_DIR += src/core/spec/riscv
INC_DIR += $(call select_from_ports,bbl)/src/lib/bbl
REP_INC_DIR += src/core/spec/riscv src/core/board/riscv_qemu
CC_OPT += -fno-delete-null-pointer-checks
@ -14,10 +7,11 @@ SRC_CC += platform_services.cc
SRC_CC += kernel/vm_thread_off.cc
SRC_CC += kernel/cpu_up.cc
SRC_CC += kernel/lock.cc
SRC_CC += spec/riscv/cpu.cc
SRC_CC += spec/riscv/kernel/thread.cc
SRC_CC += spec/riscv/kernel/cpu.cc
SRC_CC += spec/riscv/kernel/interface.cc
SRC_CC += spec/riscv/kernel/pd.cc
SRC_CC += spec/riscv/cpu.cc
SRC_CC += spec/riscv/platform_support.cc
SRC_CC += spec/riscv/timer.cc
SRC_CC += spec/64bit/memory_map.cc

View File

@ -8,6 +8,8 @@
# add include paths
REP_INC_DIR += src/core/spec/x86_64
LIBS += syscall-hw
# add assembly sources
SRC_S += spec/x86_64/crt0.s
SRC_S += spec/x86_64/exception_vector.s

View File

@ -1 +0,0 @@
b9358ccd68ac9fbb0ea49b22aa4dd08fdaae1978

View File

@ -1,8 +0,0 @@
LICENSE := BSD-3-Clause
VERSION := git
DOWNLOADS := bbl.git
URL(bbl) = https://github.com/skalk/bbl-lite.git
REV(bbl) = 22300f2f0ea72b7f9228ca6743d4ebb12cf5a79b
DIR(bbl) = src/lib/bbl

View File

@ -1,21 +0,0 @@
/**
* \brief Errno definitions
* \author Sebastian Sumpf
* \date 2017-08-24
*/
/*
* 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 _ERRNO_H_
#define _ERRNO_H_
enum {
ENOSYS = 38,
};
#endif /* _ERRNO_H_ */

View File

@ -1,22 +0,0 @@
/**
* \brief Placeholder for 'image.elf'
* \author Sebastian Sumpf
* \date 2017-08-24
*/
/*
* 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.
*/
.section ".payload","a",@progbits
.align 3
.globl _payload_start, _payload_end
_payload_start:
#ifdef BBL_PAYLOAD
.incbin BBL_PAYLOAD
#endif
_payload_end:

View File

@ -1,8 +0,0 @@
#ifndef _LIMITS_H_
#define _LIMITS_H_
enum {
ULONG_MAX = ~0UL
};
#endif /* _LIMITS_H_ */

View File

@ -1,7 +0,0 @@
.section ".payload","a",@progbits
.align 3
.globl _payload_start, _payload_end
_payload_start:
.incbin BBL_PAYLOAD
_payload_end:

View File

@ -1,28 +0,0 @@
/**
* \brief Base types
* \author Sebastian Sumpf
* \date 2017-08-24
*/
/*
* 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 _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_ */

View File

@ -1,24 +0,0 @@
/**
* \brief Stdio definitions
* \author Sebastian Sumpf
* \date 2017-08-24
*/
/*
* 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 _STDIO_H_
#define _STDIO_H_
#include <stdarg.h>
typedef unsigned long long uint64_t;
int snprintf(char *, size_t, const char *, ...);
int vsnprintf(char *, size_t, const char *, va_list);
#endif /* _STDIO_H_ */

View File

@ -1,22 +0,0 @@
/**
* \brief String definitions
* \author Sebastian Sumpf
* \date 2017-08-24
*/
/*
* 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 _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_ */

View File

@ -1,33 +0,0 @@
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)

View File

@ -1,5 +1,5 @@
/*
* \brief Riscv spike specific board definitions
* \brief RISC-V Qemu specific board definitions
* \author Stefan Kalkowski
* \date 2017-02-20
*/
@ -11,10 +11,10 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__BOOTSTRAP__SPEC__RISCV__BOARD_H_
#define _SRC__BOOTSTRAP__SPEC__RISCV__BOARD_H_
#ifndef _SRC__BOOTSTRAP__SPEC__RISCV_QEMU__BOARD_H_
#define _SRC__BOOTSTRAP__SPEC__RISCV_QEMU__BOARD_H_
#include <hw/spec/riscv/board.h>
#include <hw/spec/riscv/qemu_board.h>
namespace Board { using namespace Hw::Riscv_board; }
@ -22,4 +22,4 @@ template <typename E, unsigned B, unsigned S>
void Sv39::Level_x_translation_table<E, B, S>::_translation_added(addr_t, size_t)
{ }
#endif /* _SRC__BOOTSTRAP__SPEC__RISCV__BOARD_H_ */
#endif /* _SRC__BOOTSTRAP__SPEC__RISCV_QEMU__BOARD_H_ */

View File

@ -19,15 +19,29 @@ using namespace Board;
Bootstrap::Platform::Board::Board()
:
early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE } ),
early_ram_regions(Memory_region { RAM_BASE, RAM_SIZE } ),
core_mmio()
{ }
unsigned Bootstrap::Platform::enable_mmu()
{
using Sptbr = Hw::Riscv_cpu::Sptbr;
Sptbr::write(Sptbr::Ppn::masked((addr_t)core_pd->table_base >> 12));
using Satp = Hw::Riscv_cpu::Satp;
using Sstatus = Hw::Riscv_cpu::Sstatus;
/* disable supervisor interrupts */
Sstatus::access_t sstatus = Sstatus::read();
Sstatus::Sie::set(sstatus, 0);
Sstatus::write(sstatus);
/* set page table */
Satp::access_t satp = 0;
Satp::Ppn::set(satp, (addr_t)core_pd->table_base >> 12);
/* SV39 mode */
Satp::Mode::set(satp, 8);
Satp::write(satp);
asm volatile ("sfence.vma" : : : "memory");
return 0;
}

View File

@ -11,13 +11,16 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CORE__SPEC__RISCV__BOARD_H_
#define _CORE__SPEC__RISCV__BOARD_H_
#ifndef _CORE__SPEC__RISCV_QEMU__BOARD_H_
#define _CORE__SPEC__RISCV_QEMU__BOARD_H_
#include <hw/spec/riscv/board.h>
#include <hw/spec/riscv/qemu_board.h>
#include <spec/riscv/pic.h>
#include <spec/riscv/timer.h>
namespace Board { using namespace Hw::Riscv_board; }
#endif /* _CORE__SPEC__RISCV__BOARD_H_ */
#include <spec/riscv/timer.h>
#endif /* _CORE__SPEC__RISCV_QEMU__BOARD_H_ */

View File

@ -1,11 +1,12 @@
/*
* \brief CPU driver
* \brief CPU driver for RISC-V
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2017-10-06
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
* Copyright (C) 2017-2021 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.
@ -38,14 +39,15 @@ static Asid_allocator & alloc() {
Mmu_context::Mmu_context(addr_t page_table_base)
{
Sptbr::Asid::set(sptbr, (Genode::uint8_t)alloc().alloc());
Sptbr::Ppn::set(sptbr, page_table_base >> 12);
Satp::Asid::set(satp, (Genode::uint8_t)alloc().alloc());
Satp::Ppn::set(satp, page_table_base >> 12);
Satp::Mode::set(satp, 8);
}
Mmu_context::~Mmu_context()
{
unsigned asid = Sptbr::Asid::get(sptbr);
unsigned asid = Satp::Asid::get(satp);
Cpu::invalidate_tlb_by_pid(asid);
alloc().free(asid);
}
@ -57,21 +59,22 @@ void Genode::Cpu::switch_to(Mmu_context & context)
* The sstatus register defines to which privilege level
* the machin returns when doing an exception return
*/
bool user = Sptbr::Asid::get(context.sptbr);
bool user = Satp::Asid::get(context.satp);
Sstatus::access_t v = Sstatus::read();
Sstatus::Spp::set(v, user ? 0 : 1);
Sstatus::write(v);
/* change the translation table when necessary */
//Sptbr::access_t sptbr = Sptbr::read();
if (user /*&& sptbr != context.sptbr*/)
Sptbr::write(context.sptbr);
if (user) {
Satp::write(context.satp);
sfence();
}
}
void Genode::Cpu::mmu_fault(Context &, Kernel::Thread_fault & f)
{
f.addr = Genode::Cpu::Sbadaddr::read();
f.addr = Genode::Cpu::Stval::read();
f.type = Kernel::Thread_fault::PAGE_MISSING;
}

View File

@ -52,7 +52,7 @@ class Genode::Cpu : public Hw::Riscv_cpu
struct Mmu_context
{
Sptbr::access_t sptbr = 0;
Satp::access_t satp = 0;
Mmu_context(addr_t page_table_base);
~Mmu_context();
@ -75,7 +75,7 @@ class Genode::Cpu : public Hw::Riscv_cpu
/*
* Note: In core the address space id must be zero
*/
asm volatile ("sfence.vm\n");
asm volatile ("sfence.vma\n");
}
static void invalidate_tlb_by_pid(unsigned const /* pid */) { sfence(); }

View File

@ -22,7 +22,7 @@
j _kernel_entry
.p2align 8
.global _kernel_entry
_kernel_entry:
# client context
@ -63,4 +63,14 @@ _kernel_entry:
.global idle_thread_main
idle_thread_main:
wfi
/*
* MIG-V errata:
* "Place 7 NOPs after WFI to ensure proper pipeline propagation"
* Otherwise wfi will exit without an interrupt.
*/
.rept 7
nop
.endr
j idle_thread_main

View File

@ -0,0 +1,140 @@
/*
* \brief Direct kernel interface for core
* \author Sebastian Sumpf
* \date 2021-02-10
*
* System call bindings for privileged core threads. Core threads cannot use
* hardware-system calls ('ecall') because machine mode (OpenSBI) will interpret
* them as SBI calls from supvervisor mode (not system calls). Unknown SBI calls
* will lead machine mode to either stopping the machine or doing the wrong thing.
* In any case machine mode will not forward the 'ecall' to supervisor mode, it
* does only so for 'ecall's from user land. Therefore, call the kernel
* directly.
*/
/*
* 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.
*/
/* Genode includes */
#include <kernel/interface.h>
#include <base/log.h>
#include <cpu/cpu_state.h>
using namespace Kernel;
/************************************
** Helper macros for kernel calls **
************************************/
#define CALL_1_FILL_ARG_REGS \
register Call_arg arg_0_reg asm("a0") = arg_0;
#define CALL_2_FILL_ARG_REGS \
CALL_1_FILL_ARG_REGS \
register Call_arg arg_1_reg asm("a1") = arg_1;
#define CALL_3_FILL_ARG_REGS \
CALL_2_FILL_ARG_REGS \
register Call_arg arg_2_reg asm("a2") = arg_2;
#define CALL_4_FILL_ARG_REGS \
CALL_3_FILL_ARG_REGS \
register Call_arg arg_3_reg asm("a3") = arg_3;
#define CALL_5_FILL_ARG_REGS \
CALL_4_FILL_ARG_REGS \
register Call_arg arg_4_reg asm("a4") = arg_4;
extern Genode::addr_t _kernel_entry;
/*
* Emulate RISC-V hardware-system call using jump ('jalr') instead of
* environment call ('ecall').
*
* - clear SIE in sstatus (supervisor interrupt enable)
* - set scause to ECALL from supervisor mode
* - set sepc to "1:"
* - jump to '_kernel_entry
*
* After system call execution continues at "1:"
*/
#define CALL_1_SWI "li ra, 0x2 \n" \
"csrc sstatus, ra\n" \
"csrw scause, %2 \n" \
"la %2, 1f \n" \
"csrw sepc, %2 \n" \
"jalr %1 \n" \
"1: \n" \
: "+r" (arg_0_reg) : "r" (&_kernel_entry), \
"r" (Genode::Cpu_state::ECALL_FROM_SUPERVISOR)
#define CALL_2_SWI CALL_1_SWI, "r" (arg_1_reg)
#define CALL_3_SWI CALL_2_SWI, "r" (arg_2_reg)
#define CALL_4_SWI CALL_3_SWI, "r" (arg_3_reg)
#define CALL_5_SWI CALL_4_SWI, "r" (arg_4_reg)
/******************
** Kernel calls **
******************/
Call_ret Kernel::call64(Call_arg arg_0)
{
CALL_1_FILL_ARG_REGS
asm volatile(CALL_1_SWI : "ra");
return arg_0_reg;
}
Call_ret Kernel::call(Call_arg arg_0)
{
CALL_1_FILL_ARG_REGS
asm volatile(CALL_1_SWI : "ra");
return arg_0_reg;
}
Call_ret Kernel::call(Call_arg arg_0,
Call_arg arg_1)
{
CALL_2_FILL_ARG_REGS
asm volatile(CALL_2_SWI: "ra");
return arg_0_reg;
}
Call_ret Kernel::call(Call_arg arg_0,
Call_arg arg_1,
Call_arg arg_2)
{
CALL_3_FILL_ARG_REGS
asm volatile(CALL_3_SWI : "ra");
return arg_0_reg;
}
Call_ret Kernel::call(Call_arg arg_0,
Call_arg arg_1,
Call_arg arg_2,
Call_arg arg_3)
{
CALL_4_FILL_ARG_REGS
asm volatile(CALL_4_SWI : "ra");
return arg_0_reg;
}
Call_ret Kernel::call(Call_arg arg_0,
Call_arg arg_1,
Call_arg arg_2,
Call_arg arg_3,
Call_arg arg_4)
{
CALL_5_FILL_ARG_REGS
asm volatile(CALL_5_SWI : "ra");
return arg_0_reg;
}

View File

@ -25,6 +25,7 @@ void Thread::Tlb_invalidation::execute() {}
void Thread::exception(Cpu & cpu)
{
using Context = Genode::Cpu::Context;
using Stval = Genode::Cpu::Stval;
if (regs->is_irq()) {
/* there are only cpu-local timer interrupts right now */
@ -33,20 +34,51 @@ void Thread::exception(Cpu & cpu)
}
switch(regs->cpu_exception) {
case Context::ECALL_FROM_USER:
case Context::ECALL_FROM_SUPERVISOR:
_call();
break;
case Context::ECALL_FROM_USER:
_call();
regs->ip += 4; /* set to next instruction */
break;
case Context::INSTRUCTION_PAGE_FAULT:
/*
* Quirk for MIG-V:
*
* On MIG-V 'stval' does not report the correct address for instructions
* that cross a page boundary.
*
* Spec 1.10: "For instruction-fetch access faults and page faults on RISC-V
* systems with variable-length instructions, stval will point to the
* portion of the instruction that caused the fault while sepc will point to
* the beginning of the instruction."
*
* On MIG-V stval always points to the beginning of the instruction.
*
* Save the last instruction-fetch fault in 'last_fetch_fault', in case the
* next fetch fault occurs at the same IP and is at a page border, set
* page-fault address ('stval') to next page.
*/
if (regs->last_fetch_fault == regs->ip && (regs->ip & 0xfff) == 0xffe)
Stval::write(Stval::read() + 4);
_mmu_exception();
regs->last_fetch_fault = regs->ip;
break;
case Context::STORE_PAGE_FAULT:
case Context::LOAD_PAGE_FAULT:
case Context::INSTRUCTION_ACCESS_FAULT:
case Context::LOAD_ACCESS_FAULT:
case Context::STORE_ACCESS_FAULT:
_mmu_exception();
break;
default:
Genode::raw(*this, ": unhandled exception ", regs->cpu_exception,
" at ip=", (void*)regs->ip,
" addr=", Genode::Hex(Genode::Cpu::Sbadaddr::read()));
" addr=", Genode::Hex(Genode::Cpu::Stval::read()));
_die();
}
}

View File

@ -1,11 +1,11 @@
/*
* \brief Timer driver for core
* \brief SBI-timer driver for RISC-V core
* \author Sebastian Sumpf
* \date 2015-08-22
* \date 2021-01-29
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
* Copyright (C) 2021 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.
@ -13,7 +13,8 @@
/* Core includes */
#include <kernel/timer.h>
#include <hw/spec/riscv/machine_call.h>
#include <platform.h>
#include <hw/spec/riscv/sbi.h>
using namespace Genode;
using namespace Kernel;
@ -27,25 +28,32 @@ Board::Timer::Timer(unsigned)
}
time_t Board::Timer::stime() const { return Hw::get_sys_timer(); }
time_t Board::Timer::stime() const
{
register time_t time asm("a0");
asm volatile ("rdtime %0" : "=r"(time));
return time;
}
void Timer::_start_one_shot(time_t const ticks)
{
_device.timeout = _device.stime() + ticks;
Hw::set_sys_timer(_device.timeout);
Sbi::set_timer(_device.timeout);
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return ticks / Board::Timer::TICS_PER_US; }
return (ticks / Board::Timer::TICKS_PER_US); }
time_t Timer::us_to_ticks(time_t const us) const {
return us * Board::Timer::TICS_PER_MS; }
return us * Board::Timer::TICKS_PER_US; }
time_t Timer::_max_value() const { return 0xffffffff; }
time_t Timer::_max_value() const {
return 0xffffffff; }
time_t Timer::_duration() const

View File

@ -27,9 +27,8 @@ namespace Board { class Timer; }
struct Board::Timer
{
enum {
SPIKE_TIMER_HZ = 1000000,
TICS_PER_MS = SPIKE_TIMER_HZ / 1000,
TICS_PER_US = TICS_PER_MS / 1000,
TICKS_PER_MS = TIMER_HZ / 1000,
TICKS_PER_US = TICKS_PER_MS / 1000,
};
Kernel::time_t timeout = 0;

View File

@ -27,19 +27,21 @@ struct Hw::Riscv_cpu
/* Supervisor-mode status Register */
RISCV_SUPERVISOR_REGISTER(Sstatus, sstatus,
struct Sie : Bitfield<1,1> { }; /* supervisor interrupt enable */
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 Trap Value (replaces Sbadaddr in ISA 1.10) */
RISCV_SUPERVISOR_REGISTER(Stval, stval);
/* Supervisor Page-Table Base Register */
RISCV_SUPERVISOR_REGISTER(Sptbr, sptbr,
struct Ppn : Bitfield<0, 38> { };
struct Asid : Bitfield<38, 26> { };
/* Supervisor address translation an protection (replaces sptbr in ISA 1.10) */
RISCV_SUPERVISOR_REGISTER(Satp, satp,
struct Ppn : Bitfield<0, 44> { };
struct Asid : Bitfield<44,16> { };
struct Mode : Bitfield<60, 4> { };
);
};

View File

@ -1,47 +0,0 @@
/**
* \brief Calls supported by machine mode (or SBI interface in RISC-V)
* \author Sebastian Sumpf
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2015-06-14
*/
/*
* 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.
*/
#ifndef _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_
#define _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_
using uintptr_t = unsigned long;
#include <bbl/mcall.h>
namespace Hw {
inline unsigned long ecall(unsigned long id, unsigned long a0,
unsigned long a1)
{
asm volatile ("mv a0, %0\n"
"mv a1, %1\n"
"mv a2, %2\n"
"ecall \n"
"mv %0, a0\n"
: "+r"(id) : "r"(a0), "r"(a1)
: "a0", "a1", "a2");
return id;
}
inline void put_char(unsigned long c) {
ecall(MCALL_CONSOLE_PUTCHAR, c, /* unused arg */ 0); }
inline void set_sys_timer(unsigned long t) {
ecall(MCALL_SET_TIMER, t, /* unused arg */ 0); }
inline unsigned long get_sys_timer() {
return ecall(MCALL_GET_TIMER, /* unused args */ 0, 0); }
}
#endif /* _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ */

View File

@ -60,6 +60,8 @@ struct Sv39::Descriptor : Register<64>
struct X : Bitfield<3, 1> { }; /* executable */
struct U : Bitfield<4, 1> { }; /* user */
struct G : Bitfield<5, 1> { }; /* global */
struct A : Bitfield<6, 1> { }; /* access bit */
struct D : Bitfield<7, 1> { }; /* dirty bit */
struct Perm : Bitfield<0, 5> { };
struct Type : Bitfield<1, 3>
@ -130,6 +132,15 @@ struct Sv39::Block_descriptor : Descriptor
Ppn::set(desc, base);
Perm::set(desc, permission_bits(f));
/*
* Always set access and dirty bits because RISC-V may raise a page fault
* (implementation dependend) in case it observes this bits being cleared.
*/
A::set(desc, 1);
if (f.writeable)
D::set(desc, 1);
V::set(desc, 1);
return desc;

View File

@ -1,27 +1,31 @@
/*
* \brief Riscv spike specific board definitions
* \brief RISC-V Qemu specific board definitions
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2019-05-16
* \date 2021-02-09
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
* Copyright (C) 2021 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__INCLUDE__HW__SPEC__RISCV__BOARD_H_
#define _SRC__INCLUDE__HW__SPEC__RISCV__BOARD_H_
#ifndef _SRC__INCLUDE__HW__SPEC__RISCV__QEMU_BOARD_H_
#define _SRC__INCLUDE__HW__SPEC__RISCV__QEMU_BOARD_H_
#include <hw/spec/riscv/boot_info.h>
#include <hw/spec/riscv/page_table.h>
#include <hw/spec/riscv/uart.h>
#include <drivers/defs/riscv.h>
#include <hw/spec/riscv/sbi.h>
namespace Hw::Riscv_board {
using namespace Riscv;
enum {
RAM_BASE = 0x80020000,
RAM_SIZE = 0x7fe0000,
TIMER_HZ = 10000000,
};
enum { UART_BASE, UART_CLOCK };
@ -31,4 +35,4 @@ namespace Hw::Riscv_board {
};
}
#endif /* _SRC__INCLUDE__HW__SPEC__RISCV__BOARD_H_ */
#endif /* _SRC__INCLUDE__HW__SPEC__RISCV__QEMU_BOARD_H_ */

View File

@ -0,0 +1,52 @@
/**
* \brief OpenSBI interface
* \author Sebastian Sumpf
* \date 2021-01-29
*/
/*
* Copyright (C) 2021 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__SBI_H_
#define _SRC__LIB__HW__SPEC__RISCV__SBI_H_
namespace Sbi {
enum Eid {
SET_TIMER = 0,
PUT_CHAR = 1,
};
inline unsigned long ecall(Eid eid, unsigned long arg0)
{
asm volatile ("mv a0, %0\n"
"mv a7, %1\n"
"ecall \n"
"mv %0, a0\n"
: "+r"(arg0) : "r"(eid)
: "a0", "a7");
return eid;
}
inline void set_timer(unsigned long value) { ecall(SET_TIMER, value); }
inline void console_put_char(unsigned long c) { ecall(PUT_CHAR, c); }
}
namespace Hw { struct Riscv_uart; }
/**
* SBI Uart
*/
struct Hw::Riscv_uart
{
void put_char(char const c)
{
Sbi::console_put_char(c);
}
};
#endif /* _SRC__LIB__HW__SPEC__RISCV__SBI_H_ */

View File

@ -1,32 +0,0 @@
/*
* \brief UART output driver for RISCV
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \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.
*/
#ifndef _SRC__LIB__HW__SPEC__RISCV__UART_H_
#define _SRC__LIB__HW__SPEC__RISCV__UART_H_
#include <hw/spec/riscv/machine_call.h>
#include <util/register.h>
namespace Hw { struct Riscv_uart; }
struct Hw::Riscv_uart
{
void put_char(char const c)
{
Hw::put_char(c);
}
};
#endif /* _SRC__LIB__HW__SPEC__RISCV__UART_H_ */

View File

@ -1,25 +0,0 @@
/*
* \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

@ -1,9 +1,11 @@
# local variable for run-tool arguments used for running scenarios in Qemu
QEMU_RUN_OPT := --include power_on/qemu --include log/qemu
# kernel to use
KERNEL ?= hw
# board to use
BOARD ?= spike
# board to use (riscv_qemu)
BOARD ?= riscv_qemu
# local variable for run-tool arguments that depend on the used board
BOARD_RUN_OPT(spike) = --include image/bbl --include power_on/spike --include log/spike
BOARD_RUN_OPT(riscv_qemu) = $(QEMU_RUN_OPT)

View File

@ -1,6 +0,0 @@
proc run_image {elf_img} {
puts "using '$elf_img' as bbl image"
exec rm -f bbl/image.o
exec -ignorestderr make IMAGE_ELF=[pwd]/$elf_img bbl
}

View File

@ -1,34 +0,0 @@
source [genode_dir]/tool/run/log.inc
source [genode_dir]/tool/run/spike.inc
proc run_log { wait_for_re timeout_value } {
global spike_spawn_id
global output_spawn_id
set kernel_msg [run_boot_string]
set output_spawn_id $spike_spawn_id
if {$wait_for_re == "forever"} {
set timeout -1
} else {
set timeout $timeout_value
}
expect {
-i $output_spawn_id $kernel_msg { }
eof {
puts stderr "Aborting, received EOF"
return false
}
timeout {
puts stderr "Boot process timed out"
close
return false
}
}
wait_for_output $wait_for_re $timeout_value $spike_spawn_id
return true
}

View File

@ -52,6 +52,7 @@ proc run_power_on { } {
if {[have_spec x86_64]} { set qemu "qemu-system-x86_64" }
if {[have_spec arm]} { set qemu "qemu-system-arm" }
if {[have_spec arm_64]} { set qemu "qemu-system-aarch64" }
if {[have_spec riscv]} { set qemu "qemu-system-riscv64" }
#
# Only the x86_64 variant of Qemu provides the emulation of hardware
@ -155,8 +156,14 @@ proc run_power_on { } {
append qemu_args " -machine q35 "
}
# on ARM, we supply the boot image as kernel
if {[have_spec arm] || [have_spec arm_v8]} { append qemu_args " -kernel [run_dir]/boot/image.elf " }
if {[have_board riscv_qemu]} {
append qemu_args " -m 128 -machine virt -cpu rv64,priv_spec=v1.10.0 "
append qemu_args " -bios default "
}
# on ARM/RISC-V, we supply the boot image as kernel
if {[have_spec arm] || [have_spec arm_v8] || [have_spec riscv]} {
append qemu_args " -kernel [run_dir]/boot/image.elf " }
eval spawn $qemu $qemu_args
set qemu_spawn_id $spawn_id

View File

@ -1,28 +0,0 @@
##
# Execute scenario using spike
#
source [genode_dir]/tool/run/spike.inc
proc is_spike_available { } {
if {[have_spec riscv]} { return true }
puts stderr "skipping execution because platform is not supported by spike"
return false
}
proc run_power_on { } {
global spike_args
global spike
global spike_spawn_id
if {![is_spike_available]} { return 0 }
append spike_args "-m128 [pwd]/debug/bbl "
set spike "spike"
eval spawn $spike $spike_args
set spike_spawn_id $spawn_id
return true
}

View File

@ -1 +0,0 @@
set spike_spawn_id ""