mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-02 09:18:18 +00:00
hw: support for ARM64 Raspberry Pi 3
Restriction: enables only cpu core 0 and the timer interrupt by now. Fix #3405
This commit is contained in:
parent
87015df66c
commit
90d07741aa
27
repos/base-hw/include/spec/arm_64/kernel/interface_support.h
Normal file
27
repos/base-hw/include/spec/arm_64/kernel/interface_support.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* \brief Interface between kernel and userland
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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__ARM_64__KERNEL__INTERFACE_SUPPORT_H_
|
||||
#define _INCLUDE__SPEC__ARM_64__KERNEL__INTERFACE_SUPPORT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
typedef Genode::uint64_t Call_arg;
|
||||
typedef Genode::uint64_t Call_ret;
|
||||
typedef Genode::uint64_t Call_ret_64;
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM_64__KERNEL__INTERFACE_SUPPORT_H_ */
|
3
repos/base-hw/lib/mk/spec/arm_64/startup-hw.mk
Normal file
3
repos/base-hw/lib/mk/spec/arm_64/startup-hw.mk
Normal file
@ -0,0 +1,3 @@
|
||||
include $(BASE_DIR)/lib/mk/startup.inc
|
||||
|
||||
vpath crt0.s $(BASE_DIR)/src/lib/startup/spec/arm_64
|
3
repos/base-hw/lib/mk/spec/arm_64/syscall-hw.mk
Normal file
3
repos/base-hw/lib/mk/spec/arm_64/syscall-hw.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC += kernel/interface.cc
|
||||
|
||||
vpath kernel/interface.cc $(REP_DIR)/src/lib/base/arm_64
|
10
repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk
Normal file
10
repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk
Normal file
@ -0,0 +1,10 @@
|
||||
INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/rpi3
|
||||
|
||||
SRC_CC += lib/base/arm_64/kernel/interface.cc
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
SRC_CC += bootstrap/spec/rpi3/platform.cc
|
||||
SRC_S += bootstrap/spec/arm_64/crt0.s
|
||||
|
||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
24
repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk
Normal file
24
repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk
Normal file
@ -0,0 +1,24 @@
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/rpi3
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm_v8
|
||||
|
||||
# add C++ sources
|
||||
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/arm_v8/cpu.cc
|
||||
SRC_CC += spec/arm_v8/kernel/thread.cc
|
||||
SRC_CC += spec/arm_v8/kernel/cpu.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
SRC_CC += spec/rpi3/pic.cc
|
||||
SRC_CC += spec/rpi3/timer.cc
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
|
||||
#add assembly sources
|
||||
SRC_S += spec/arm_v8/exception_vector.s
|
||||
SRC_S += spec/arm_v8/crt0.s
|
||||
|
||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/core-hw.inc
|
3
repos/base-hw/lib/mk/spec/arm_v8/ld-hw.mk
Normal file
3
repos/base-hw/lib/mk/spec/arm_v8/ld-hw.mk
Normal file
@ -0,0 +1,3 @@
|
||||
BASE_LIBS += base-hw-common base-hw
|
||||
|
||||
include $(BASE_DIR)/lib/mk/spec/arm_64/ld-platform.inc
|
64
repos/base-hw/src/bootstrap/spec/arm_64/crt0.s
Normal file
64
repos/base-hw/src/bootstrap/spec/arm_64/crt0.s
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* \brief Startup code for bootstrap
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 ".text.crt0"
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/***********************
|
||||
** Detect CPU number **
|
||||
***********************/
|
||||
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #0b11111111
|
||||
cbz x0, _crt0_fill_bss_zero
|
||||
wfe
|
||||
b _start
|
||||
|
||||
|
||||
/***************************
|
||||
** Zero-fill BSS segment **
|
||||
***************************/
|
||||
|
||||
_crt0_fill_bss_zero:
|
||||
ldr x0, =_bss_start
|
||||
ldr x1, =_bss_end
|
||||
1:
|
||||
cmp x1, x0
|
||||
b.eq _crt0_enable_fpu
|
||||
str xzr, [x0], #8
|
||||
b 1b
|
||||
|
||||
|
||||
/****************
|
||||
** Enable FPU **
|
||||
****************/
|
||||
|
||||
_crt0_enable_fpu:
|
||||
mov x0, #0b11
|
||||
lsl x0, x0, #20
|
||||
msr cpacr_el1, x0
|
||||
|
||||
|
||||
/**********************
|
||||
** Initialize stack **
|
||||
**********************/
|
||||
|
||||
ldr x0, =_crt0_start_stack
|
||||
mov sp, x0
|
||||
bl init
|
||||
|
||||
.p2align 4
|
||||
.space 0x4000
|
||||
_crt0_start_stack:
|
30
repos/base-hw/src/bootstrap/spec/rpi3/board.h
Normal file
30
repos/base-hw/src/bootstrap/spec/rpi3/board.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* \brief Board driver for bootstrap
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 _BOOTSTRAP__SPEC__RPI3__BOARD_H_
|
||||
#define _BOOTSTRAP__SPEC__RPI3__BOARD_H_
|
||||
|
||||
#include <hw/spec/arm_64/rpi3_board.h>
|
||||
#include <hw/spec/arm_64/cpu.h>
|
||||
#include <hw/spec/arm/lpae.h>
|
||||
|
||||
namespace Bootstrap {
|
||||
using Cpu = Hw::Arm_64_cpu;
|
||||
struct Pic {};
|
||||
};
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Rpi3_board;
|
||||
};
|
||||
|
||||
#endif /* _BOOTSTRAP__SPEC__RPI3__BOARD_H_ */
|
144
repos/base-hw/src/bootstrap/spec/rpi3/platform.cc
Normal file
144
repos/base-hw/src/bootstrap/spec/rpi3/platform.cc
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* \brief Platform implementations specific for base-hw and Raspberry Pi3
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
using Bootstrap::Cpu;
|
||||
|
||||
|
||||
/**
|
||||
* Leave out the first page (being 0x0) from bootstraps RAM allocator,
|
||||
* some code does not feel happy with addresses being zero
|
||||
*/
|
||||
Bootstrap::Platform::Board::Board()
|
||||
: early_ram_regions(Memory_region { ::Board::RAM_BASE + 0x1000,
|
||||
::Board::RAM_SIZE - 0x1000 }),
|
||||
late_ram_regions(Memory_region { ::Board::RAM_BASE, 0x1000 }),
|
||||
core_mmio(Memory_region { ::Board::UART_BASE, ::Board::UART_SIZE },
|
||||
Memory_region { ::Board::LOCAL_IRQ_CONTROLLER_BASE,
|
||||
::Board::LOCAL_IRQ_CONTROLLER_SIZE },
|
||||
Memory_region { ::Board::IRQ_CONTROLLER_BASE,
|
||||
::Board::IRQ_CONTROLLER_SIZE }) {}
|
||||
|
||||
|
||||
static inline void prepare_non_secure_world()
|
||||
{
|
||||
bool el2 = Cpu::Id_pfr0::El2::get(Cpu::Id_pfr0::read());
|
||||
|
||||
Cpu::Scr::access_t scr = Cpu::Scr::read();
|
||||
Cpu::Scr::Ns::set(scr, 1); /* set non-secure bit */
|
||||
Cpu::Scr::Rw::set(scr, 1); /* exec in aarch64 */
|
||||
Cpu::Scr::Smd::set(scr, 1); /* disable smc call */
|
||||
Cpu::Scr::write(scr);
|
||||
|
||||
Cpu::Spsr::access_t pstate = 0;
|
||||
Cpu::Spsr::Sp::set(pstate, 1); /* select non-el0 stack pointer */
|
||||
Cpu::Spsr::El::set(pstate, el2 ? Cpu::Current_el::EL2
|
||||
: Cpu::Current_el::EL1);
|
||||
Cpu::Spsr::F::set(pstate, 1);
|
||||
Cpu::Spsr::I::set(pstate, 1);
|
||||
Cpu::Spsr::A::set(pstate, 1);
|
||||
Cpu::Spsr::D::set(pstate, 1);
|
||||
Cpu::Spsr_el3::write(pstate);
|
||||
|
||||
#ifndef SWITCH_TO_ELX
|
||||
#define SWITCH_TO_ELX(el) \
|
||||
"mov x0, sp \n" \
|
||||
"msr sp_" #el ", x0 \n" \
|
||||
"adr x0, 1f \n" \
|
||||
"msr elr_el3, x0 \n" \
|
||||
"eret \n" \
|
||||
"1:"
|
||||
|
||||
if (el2)
|
||||
asm volatile(SWITCH_TO_ELX(el2) ::: "x0");
|
||||
else
|
||||
asm volatile(SWITCH_TO_ELX(el1) ::: "x0");
|
||||
#undef SWITCH_TO_ELX
|
||||
#else
|
||||
#error "macro SWITCH_TO_ELX already defined"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_hypervisor()
|
||||
{
|
||||
Cpu::Hcr::access_t scr = Cpu::Hcr::read();
|
||||
Cpu::Hcr::Rw::set(scr, 1); /* exec in aarch64 */
|
||||
Cpu::Hcr::write(scr);
|
||||
|
||||
Cpu::Spsr::access_t pstate = 0;
|
||||
Cpu::Spsr::Sp::set(pstate, 1); /* select non-el0 stack pointer */
|
||||
Cpu::Spsr::El::set(pstate, Cpu::Current_el::EL1);
|
||||
Cpu::Spsr::F::set(pstate, 1);
|
||||
Cpu::Spsr::I::set(pstate, 1);
|
||||
Cpu::Spsr::A::set(pstate, 1);
|
||||
Cpu::Spsr::D::set(pstate, 1);
|
||||
Cpu::Spsr_el2::write(pstate);
|
||||
|
||||
asm volatile("mov x0, sp \n"
|
||||
"msr sp_el1, x0 \n"
|
||||
"adr x0, 1f \n"
|
||||
"msr elr_el2, x0 \n"
|
||||
"eret \n"
|
||||
"1:");
|
||||
}
|
||||
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
while (Cpu::current_privilege_level() > Cpu::Current_el::EL1) {
|
||||
if (Cpu::current_privilege_level() == Cpu::Current_el::EL3)
|
||||
prepare_non_secure_world();
|
||||
else
|
||||
prepare_hypervisor();
|
||||
}
|
||||
|
||||
Cpu::Vbar_el1::write(Hw::Mm::supervisor_exception_vector().base);
|
||||
|
||||
/* set memory attributes in indirection register */
|
||||
Cpu::Mair::access_t mair = 0;
|
||||
Cpu::Mair::Attr0::set(mair, Cpu::Mair::NORMAL_MEMORY_UNCACHED);
|
||||
Cpu::Mair::Attr1::set(mair, Cpu::Mair::DEVICE_MEMORY);
|
||||
Cpu::Mair::Attr2::set(mair, Cpu::Mair::NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair::Attr3::set(mair, Cpu::Mair::DEVICE_MEMORY);
|
||||
Cpu::Mair::write(mair);
|
||||
|
||||
Cpu::Ttbr::access_t ttbr = Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base);
|
||||
Cpu::Ttbr0_el1::write(ttbr);
|
||||
Cpu::Ttbr1_el1::write(ttbr);
|
||||
|
||||
Cpu::Tcr_el1::access_t tcr = 0;
|
||||
Cpu::Tcr_el1::T0sz::set(tcr, 25);
|
||||
Cpu::Tcr_el1::T1sz::set(tcr, 25);
|
||||
Cpu::Tcr_el1::Irgn0::set(tcr, 1);
|
||||
Cpu::Tcr_el1::Irgn1::set(tcr, 1);
|
||||
Cpu::Tcr_el1::Orgn0::set(tcr, 1);
|
||||
Cpu::Tcr_el1::Orgn1::set(tcr, 1);
|
||||
Cpu::Tcr_el1::Sh0::set(tcr, 0b10);
|
||||
Cpu::Tcr_el1::Sh1::set(tcr, 0b10);
|
||||
Cpu::Tcr_el1::Ips::set(tcr, 0b10);
|
||||
Cpu::Tcr_el1::As::set(tcr, 1);
|
||||
Cpu::Tcr_el1::write(tcr);
|
||||
|
||||
Cpu::Sctlr_el1::access_t sctlr = Cpu::Sctlr_el1::read();
|
||||
Cpu::Sctlr_el1::C::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::I::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::A::set(sctlr, 0);
|
||||
Cpu::Sctlr_el1::M::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::Sa0::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::Sa::set(sctlr, 0);
|
||||
Cpu::Sctlr_el1::write(sctlr);
|
||||
|
||||
return 0;
|
||||
}
|
96
repos/base-hw/src/core/spec/arm_v8/cpu.cc
Normal file
96
repos/base-hw/src/core/spec/arm_v8/cpu.cc
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* \brief ARMv8 cpu context initialization
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2017-04-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <board.h>
|
||||
#include <cpu.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <util/bit_allocator.h>
|
||||
|
||||
|
||||
Genode::Cpu::Context::Context(bool privileged)
|
||||
{
|
||||
Spsr::El::set(pstate, privileged ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::switch_to(Context&, Mmu_context & mmu_context)
|
||||
{
|
||||
if (mmu_context.id() == 0) return;
|
||||
|
||||
if (mmu_context.id() != Ttbr::Asid::get(Ttbr0_el1::read()))
|
||||
Ttbr0_el1::write(mmu_context.ttbr);
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::mmu_fault(Genode::Cpu::Context &,
|
||||
Kernel::Thread_fault & fault)
|
||||
{
|
||||
Esr::access_t esr = Esr_el1::read();
|
||||
|
||||
fault.addr = Far_el1::read();
|
||||
|
||||
switch (Esr::Iss::Abort::Fsc::get(Esr::Iss::get(esr))) {
|
||||
case Esr::Iss::Abort::Fsc::TRANSLATION:
|
||||
fault.type = Kernel::Thread_fault::PAGE_MISSING;
|
||||
return;
|
||||
case Esr::Iss::Abort::Fsc::PERMISSION:
|
||||
fault.type = Esr::Iss::Abort::Write::get(Esr::Iss::get(esr))
|
||||
? Kernel::Thread_fault::WRITE : Kernel::Thread_fault::EXEC;
|
||||
return;
|
||||
default:
|
||||
Genode::raw("MMU-fault not handled ESR=", Genode::Hex(esr));
|
||||
fault.type = Kernel::Thread_fault::UNKNOWN;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
using Asid_allocator = Genode::Bit_allocator<65536>;
|
||||
|
||||
static Asid_allocator &alloc() {
|
||||
return *unmanaged_singleton<Asid_allocator>(); }
|
||||
|
||||
|
||||
Genode::Cpu::Mmu_context::Mmu_context(addr_t table)
|
||||
: ttbr(Ttbr::Baddr::masked(table))
|
||||
{
|
||||
Ttbr::Asid::set(ttbr, (Genode::uint16_t)alloc().alloc());
|
||||
}
|
||||
|
||||
|
||||
Genode::Cpu::Mmu_context::~Mmu_context()
|
||||
{
|
||||
alloc().free(id());
|
||||
}
|
||||
|
||||
|
||||
static constexpr Genode::addr_t line_size = 1 << Board::CACHE_LINE_SIZE_LOG2;
|
||||
static constexpr Genode::addr_t line_align_mask = ~(line_size - 1);
|
||||
|
||||
|
||||
void Genode::Cpu::clean_data_cache_by_virt_region(addr_t base, size_t sz)
|
||||
{
|
||||
addr_t const top = base + sz;
|
||||
base &= line_align_mask;
|
||||
for (; base < top; base += line_size) {
|
||||
asm volatile("dc cvau, %0" :: "r" (base)); }
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::invalidate_instr_cache_by_virt_region(addr_t base,
|
||||
size_t size)
|
||||
{
|
||||
addr_t const top = base + size;
|
||||
base &= line_align_mask;
|
||||
for (; base < top; base += line_size) {
|
||||
asm volatile("ic ivau, %0" :: "r" (base)); }
|
||||
}
|
93
repos/base-hw/src/core/spec/arm_v8/cpu.h
Normal file
93
repos/base-hw/src/core/spec/arm_v8/cpu.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 _CORE__SPEC__ARM_V8__CPU_H_
|
||||
#define _CORE__SPEC__ARM_V8__CPU_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.h>
|
||||
#include <cpu/cpu_state.h>
|
||||
#include <base/internal/align_at.h>
|
||||
#include <hw/spec/arm_64/cpu.h>
|
||||
|
||||
namespace Kernel { struct Thread_fault; }
|
||||
|
||||
namespace Genode {
|
||||
struct Cpu;
|
||||
using sizet_arithm_t = __uint128_t;
|
||||
using uint128_t = __uint128_t;
|
||||
}
|
||||
|
||||
struct Genode::Cpu : Hw::Arm_64_cpu
|
||||
{
|
||||
enum Exception_entry {
|
||||
SYNC_LEVEL_EL1 = 0x000,
|
||||
IRQ_LEVEL_EL1 = 0x080,
|
||||
FIQ_LEVEL_EL1 = 0x100,
|
||||
SERR_LEVEL_EL1 = 0x180,
|
||||
SYNC_LEVEL_EL1_EXC_MODE = 0x200,
|
||||
IRQ_LEVEL_EL1_EXC_MODE = 0x280,
|
||||
FIQ_LEVEL_EL1_EXC_MODE = 0x300,
|
||||
SERR_LEVEL_EL1_EXC_MODE = 0x380,
|
||||
SYNC_LEVEL_EL0 = 0x400,
|
||||
IRQ_LEVEL_EL0 = 0x480,
|
||||
FIQ_LEVEL_EL0 = 0x500,
|
||||
SERR_LEVEL_EL0 = 0x580,
|
||||
AARCH32_SYNC_LEVEL_EL0 = 0x600,
|
||||
AARCH32_IRQ_LEVEL_EL0 = 0x680,
|
||||
AARCH32_FIQ_LEVEL_EL0 = 0x700,
|
||||
AARCH32_SERR_LEVEL_EL0 = 0x780,
|
||||
RESET = 0x800
|
||||
};
|
||||
|
||||
struct alignas(16) Fpu_state
|
||||
{
|
||||
Genode::uint128_t q[32];
|
||||
Genode::uint32_t fpsr;
|
||||
};
|
||||
|
||||
struct alignas(8) Context : Cpu_state
|
||||
{
|
||||
Genode::uint64_t pstate { };
|
||||
Genode::uint64_t exception_type { RESET };
|
||||
Fpu_state fpu_state { };
|
||||
|
||||
Context(bool privileged);
|
||||
};
|
||||
|
||||
struct Mmu_context
|
||||
{
|
||||
Ttbr::access_t ttbr;
|
||||
|
||||
Mmu_context(addr_t page_table_base);
|
||||
~Mmu_context();
|
||||
|
||||
Genode::uint16_t id() {
|
||||
return Ttbr::Asid::get(ttbr); }
|
||||
};
|
||||
|
||||
void switch_to(Context&, Mmu_context &);
|
||||
|
||||
static void mmu_fault(Context &, Kernel::Thread_fault &);
|
||||
|
||||
/**
|
||||
* Return kernel name of the executing CPU
|
||||
*/
|
||||
static unsigned executing_id() { return 0; }
|
||||
|
||||
|
||||
static void clean_data_cache_by_virt_region(addr_t, size_t);
|
||||
static void invalidate_instr_cache_by_virt_region(addr_t, size_t);
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__ARM_V8__CPU_H_ */
|
56
repos/base-hw/src/core/spec/arm_v8/crt0.s
Normal file
56
repos/base-hw/src/core/spec/arm_v8/crt0.s
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* \brief Startup code for core on ARM
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-03-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.section ".text"
|
||||
|
||||
/***********************
|
||||
** kernel entry code **
|
||||
***********************/
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
/* switch to cpu-specific kernel stack */
|
||||
/*adr r1, _kernel_stack
|
||||
adr r2, _kernel_stack_size
|
||||
ldr r1, [r1]
|
||||
ldr r2, [r2]
|
||||
ldr r2, [r2]
|
||||
add r0, #1
|
||||
mul r0, r0, r2
|
||||
add sp, r1, r0*/
|
||||
|
||||
/* jump into init C code */
|
||||
b kernel_init
|
||||
|
||||
_kernel_stack: .quad kernel_stack
|
||||
_kernel_stack_size: .quad kernel_stack_size
|
||||
|
||||
|
||||
/*********************************
|
||||
** core main thread entry code **
|
||||
*********************************/
|
||||
|
||||
.global _core_start
|
||||
_core_start:
|
||||
|
||||
/* create proper environment for main thread */
|
||||
bl init_main_thread
|
||||
|
||||
/* apply environment that was created by init_main_thread */
|
||||
ldr x0, =init_main_thread_result
|
||||
ldr x0, [x0]
|
||||
mov sp, x0
|
||||
|
||||
/* jump into init C code instead of calling it as it should never return */
|
||||
b _main
|
132
repos/base-hw/src/core/spec/arm_v8/exception_vector.s
Normal file
132
repos/base-hw/src/core/spec/arm_v8/exception_vector.s
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* \brief Exception vector for ARMv8
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 .text.crt0
|
||||
|
||||
.rept 16
|
||||
str x0, [sp, #-32]
|
||||
ldr x0, [sp, #-16]
|
||||
add x0, x0, #8
|
||||
stp x1, x2, [x0], #16
|
||||
stp x3, x4, [x0], #16
|
||||
stp x5, x6, [x0], #16
|
||||
stp x7, x8, [x0], #16
|
||||
stp x9, x10, [x0], #16
|
||||
stp x11, x12, [x0], #16
|
||||
stp x13, x14, [x0], #16
|
||||
stp x15, x16, [x0], #16
|
||||
stp x17, x18, [x0], #16
|
||||
stp x19, x20, [x0], #16
|
||||
stp x21, x22, [x0], #16
|
||||
stp x23, x24, [x0], #16
|
||||
stp x25, x26, [x0], #16
|
||||
stp x27, x28, [x0], #16
|
||||
stp x29, x30, [x0], #16
|
||||
mrs x1, sp_el0
|
||||
mrs x2, elr_el1
|
||||
mrs x3, spsr_el1
|
||||
adr x4, .
|
||||
and x4, x4, #0xf80
|
||||
stp x1, x2, [x0], #16
|
||||
stp x3, x4, [x0], #16
|
||||
b _kernel_entry
|
||||
.balign 128
|
||||
.endr
|
||||
|
||||
_kernel_entry:
|
||||
stp q0, q1, [x0], #32
|
||||
stp q2, q3, [x0], #32
|
||||
stp q4, q5, [x0], #32
|
||||
stp q6, q7, [x0], #32
|
||||
stp q8, q9, [x0], #32
|
||||
stp q10, q11, [x0], #32
|
||||
stp q12, q13, [x0], #32
|
||||
stp q14, q15, [x0], #32
|
||||
stp q16, q17, [x0], #32
|
||||
stp q18, q19, [x0], #32
|
||||
stp q20, q21, [x0], #32
|
||||
stp q22, q23, [x0], #32
|
||||
stp q24, q25, [x0], #32
|
||||
stp q26, q27, [x0], #32
|
||||
stp q28, q29, [x0], #32
|
||||
stp q30, q31, [x0], #32
|
||||
mrs x2, fpsr
|
||||
str x2, [x0]
|
||||
msr fpsr, xzr
|
||||
ldr x0, [sp, #-16]
|
||||
ldr x1, [sp, #-32]
|
||||
str x1, [x0]
|
||||
bl kernel
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*******************************
|
||||
** idle loop for idle thread **
|
||||
*******************************/
|
||||
|
||||
.global idle_thread_main
|
||||
idle_thread_main:
|
||||
b idle_thread_main
|
||||
|
||||
|
||||
/*****************************
|
||||
** kernel to userland switch **
|
||||
*******************************/
|
||||
|
||||
.global kernel_to_user_context_switch
|
||||
kernel_to_user_context_switch:
|
||||
mov sp, x1 /* reset stack */
|
||||
str x0, [sp, #-16] /* store cpu state pointer */
|
||||
add x1, x0, #8*31
|
||||
ldp x2, x3, [x1], #16 /* load sp, ip */
|
||||
ldr x4, [x1], #16 /* load pstate */
|
||||
msr sp_el0, x2
|
||||
msr elr_el1, x3
|
||||
msr spsr_el1, x4
|
||||
ldp q0, q1, [x1], #32
|
||||
ldp q2, q3, [x1], #32
|
||||
ldp q4, q5, [x1], #32
|
||||
ldp q6, q7, [x1], #32
|
||||
ldp q8, q9, [x1], #32
|
||||
ldp q10, q11, [x1], #32
|
||||
ldp q12, q13, [x1], #32
|
||||
ldp q14, q15, [x1], #32
|
||||
ldp q16, q17, [x1], #32
|
||||
ldp q18, q19, [x1], #32
|
||||
ldp q20, q21, [x1], #32
|
||||
ldp q22, q23, [x1], #32
|
||||
ldp q24, q25, [x1], #32
|
||||
ldp q26, q27, [x1], #32
|
||||
ldp q28, q29, [x1], #32
|
||||
ldp q30, q31, [x1], #32
|
||||
ldr x1, [x1]
|
||||
msr fpsr, x1
|
||||
add x0, x0, #8
|
||||
ldp x1, x2, [x0], #16
|
||||
ldp x3, x4, [x0], #16
|
||||
ldp x5, x6, [x0], #16
|
||||
ldp x7, x8, [x0], #16
|
||||
ldp x9, x10, [x0], #16
|
||||
ldp x11, x12, [x0], #16
|
||||
ldp x13, x14, [x0], #16
|
||||
ldp x15, x16, [x0], #16
|
||||
ldp x17, x18, [x0], #16
|
||||
ldp x19, x20, [x0], #16
|
||||
ldp x21, x22, [x0], #16
|
||||
ldp x23, x24, [x0], #16
|
||||
ldp x25, x26, [x0], #16
|
||||
ldp x27, x28, [x0], #16
|
||||
ldp x29, x30, [x0]
|
||||
ldr x0, [x0, #-29*8]
|
||||
eret
|
21
repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc
Normal file
21
repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* \brief Kernel cpu driver implementations specific to ARMv8
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
void Kernel::Cpu::_arch_init()
|
||||
{
|
||||
/* enable timer interrupt */
|
||||
_pic.unmask(_timer.interrupt_id(), id());
|
||||
}
|
141
repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
Normal file
141
repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* \brief Kernel backend for execution contexts in userland
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
#include <hw/memory_map.h>
|
||||
|
||||
extern "C" void kernel_to_user_context_switch(void *, void *);
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
void Thread::exception(Cpu & cpu)
|
||||
{
|
||||
switch (regs->exception_type) {
|
||||
case Cpu::RESET: return;
|
||||
case Cpu::IRQ_LEVEL_EL0: [[fallthrough]]
|
||||
case Cpu::IRQ_LEVEL_EL1: [[fallthrough]]
|
||||
case Cpu::FIQ_LEVEL_EL0: [[fallthrough]]
|
||||
case Cpu::FIQ_LEVEL_EL1:
|
||||
_interrupt(cpu.id());
|
||||
return;
|
||||
case Cpu::SYNC_LEVEL_EL0: [[fallthrough]]
|
||||
case Cpu::SYNC_LEVEL_EL1:
|
||||
{
|
||||
Cpu::Esr::access_t esr = Cpu::Esr_el1::read();
|
||||
switch (Cpu::Esr::Ec::get(esr)) {
|
||||
case Cpu::Esr::Ec::SVC:
|
||||
_call();
|
||||
return;
|
||||
case Cpu::Esr::Ec::INST_ABORT_SAME_LEVEL: [[fallthrough]];
|
||||
case Cpu::Esr::Ec::DATA_ABORT_SAME_LEVEL:
|
||||
Genode::raw("Fault in kernel/core ESR=", Genode::Hex(esr));
|
||||
[[fallthrough]];
|
||||
case Cpu::Esr::Ec::INST_ABORT_LOW_LEVEL: [[fallthrough]];
|
||||
case Cpu::Esr::Ec::DATA_ABORT_LOW_LEVEL:
|
||||
_mmu_exception();
|
||||
return;
|
||||
default:
|
||||
Genode::raw("Unknown cpu exception EC=", Cpu::Esr::Ec::get(esr),
|
||||
" ISS=", Cpu::Esr::Iss::get(esr),
|
||||
" ip=", (void*)regs->ip);
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Genode::raw("Exception vector: ", (void*)regs->exception_type,
|
||||
" not implemented!");
|
||||
};
|
||||
|
||||
while (1) { ; }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* on ARM with multiprocessing extensions, maintainance operations on TLB,
|
||||
* and caches typically work coherently across CPUs when using the correct
|
||||
* coprocessor registers (there might be ARM SoCs where this is not valid,
|
||||
* with several shareability domains, but until now we do not support them)
|
||||
*/
|
||||
void Kernel::Thread::Tlb_invalidation::execute() { };
|
||||
|
||||
|
||||
bool Kernel::Pd::invalidate_tlb(Cpu &, addr_t addr, size_t size)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* The kernel part of the address space is mapped as global
|
||||
* therefore we have to invalidate it differently
|
||||
*/
|
||||
if (addr >= Hw::Mm::supervisor_exception_vector().base) {
|
||||
for (addr_t end = addr+size; addr < end; addr += get_page_size())
|
||||
asm volatile ("tlbi vaae1is, %0" :: "r" (addr >> 12));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Too big mappings will result in long running invalidation loops,
|
||||
* just invalidate the whole tlb for the ASID then.
|
||||
*/
|
||||
if (size > 8 * get_page_size()) {
|
||||
asm volatile ("tlbi aside1is, %0"
|
||||
:: "r" ((uint64_t)mmu_regs.id() << 48));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (addr_t end = addr+size; addr < end; addr += get_page_size())
|
||||
asm volatile ("tlbi vae1is, %0"
|
||||
:: "r" (addr >> 12 | (uint64_t)mmu_regs.id() << 48));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Thread::_call_update_data_region()
|
||||
{
|
||||
Genode::raw(__func__, " not implemented yet!");
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Thread::_call_update_instr_region()
|
||||
{
|
||||
addr_t const base = (addr_t)user_arg_1();
|
||||
size_t const size = (size_t)user_arg_2();
|
||||
Cpu::clean_data_cache_by_virt_region(base, size);
|
||||
Cpu::invalidate_instr_cache_by_virt_region(base, size);
|
||||
}
|
||||
|
||||
|
||||
void Thread::proceed(Cpu & cpu)
|
||||
{
|
||||
cpu.switch_to(*regs, pd().mmu_regs);
|
||||
kernel_to_user_context_switch((static_cast<Cpu::Context*>(&*regs)),
|
||||
(void*)cpu.stack_start());
|
||||
}
|
||||
|
||||
|
||||
void Thread::user_ret_time(Kernel::time_t const t) { regs->r[0] = t; }
|
||||
void Thread::user_arg_0(Kernel::Call_arg const arg) { regs->r[0] = arg; }
|
||||
void Thread::user_arg_1(Kernel::Call_arg const arg) { regs->r[1] = arg; }
|
||||
void Thread::user_arg_2(Kernel::Call_arg const arg) { regs->r[2] = arg; }
|
||||
void Thread::user_arg_3(Kernel::Call_arg const arg) { regs->r[3] = arg; }
|
||||
void Thread::user_arg_4(Kernel::Call_arg const arg) { regs->r[4] = arg; }
|
||||
|
||||
Kernel::Call_arg Thread::user_arg_0() const { return regs->r[0]; }
|
||||
Kernel::Call_arg Thread::user_arg_1() const { return regs->r[1]; }
|
||||
Kernel::Call_arg Thread::user_arg_2() const { return regs->r[2]; }
|
||||
Kernel::Call_arg Thread::user_arg_3() const { return regs->r[3]; }
|
||||
Kernel::Call_arg Thread::user_arg_4() const { return regs->r[4]; }
|
20
repos/base-hw/src/core/spec/arm_v8/translation_table.h
Normal file
20
repos/base-hw/src/core/spec/arm_v8/translation_table.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* \brief Translation table definitions for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 _CORE__SPEC__ARM_V8__TRANSLATION_TABLE_H_
|
||||
#define _CORE__SPEC__ARM_V8__TRANSLATION_TABLE_H_
|
||||
|
||||
/* core includes */
|
||||
#include <hw/spec/arm/lpae.h>
|
||||
|
||||
#endif /* _CORE__SPEC__ARM_V8__TRANSLATION_TABLE_H_ */
|
25
repos/base-hw/src/core/spec/rpi3/board.h
Normal file
25
repos/base-hw/src/core/spec/rpi3/board.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief Board driver for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 _CORE__SPEC__RPI3__BOARD_H_
|
||||
#define _CORE__SPEC__RPI3__BOARD_H_
|
||||
|
||||
#include <hw/spec/arm_64/rpi3_board.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Rpi3_board;
|
||||
|
||||
static constexpr bool SMP = true;
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__RPI3__BOARD_H_ */
|
58
repos/base-hw/src/core/spec/rpi3/pic.cc
Normal file
58
repos/base-hw/src/core/spec/rpi3/pic.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* \brief Pic implementation specific to Rpi3
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
#include <pic.h>
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
Genode::Pic::Pic()
|
||||
: Mmio(Platform::mmio_to_virt(Board::LOCAL_IRQ_CONTROLLER_BASE)) { }
|
||||
|
||||
|
||||
bool Genode::Pic::take_request(unsigned & irq)
|
||||
{
|
||||
Core0_irq_source::access_t src = read<Core0_irq_source>();
|
||||
if ((1 << TIMER_IRQ) & src) {
|
||||
irq = TIMER_IRQ;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Genode::Pic::mask() { }
|
||||
|
||||
|
||||
void Genode::Pic::unmask(unsigned const i, unsigned cpu)
|
||||
{
|
||||
if (cpu > 0)
|
||||
Genode::raw("multi-core irq controller not implemented yet");
|
||||
|
||||
if (i == TIMER_IRQ) {
|
||||
write<Core0_timer_irq_control::Cnt_p_ns_irq>(1);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::raw("irq of peripherals != timer not implemented yet!");
|
||||
}
|
||||
|
||||
|
||||
void Genode::Pic::mask(unsigned const i)
|
||||
{
|
||||
if (i == TIMER_IRQ) {
|
||||
write<Core0_timer_irq_control::Cnt_p_ns_irq>(0);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::raw("irq of peripherals != timer not implemented yet!");
|
||||
}
|
69
repos/base-hw/src/core/spec/rpi3/pic.h
Normal file
69
repos/base-hw/src/core/spec/rpi3/pic.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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 _CORE__SPEC__RPI3__PIC_H_
|
||||
#define _CORE__SPEC__RPI3__PIC_H_
|
||||
|
||||
#include <util/mmio.h>
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode { class Pic; }
|
||||
namespace Kernel { using Pic = Genode::Pic; }
|
||||
|
||||
class Genode::Pic : Mmio
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
TIMER_IRQ = 1,
|
||||
NR_OF_IRQ = 64,
|
||||
|
||||
/*
|
||||
* dummy IPI value on non-SMP platform,
|
||||
* only used in interrupt reservation within generic code
|
||||
*/
|
||||
IPI,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
|
||||
struct Core0_timer_irq_control : Register<0x40, 32>
|
||||
{
|
||||
struct Cnt_p_ns_irq : Bitfield<1, 1> {};
|
||||
};
|
||||
|
||||
struct Core1_timer_irq_control : Register<0x44, 32> {};
|
||||
struct Core2_timer_irq_control : Register<0x48, 32> {};
|
||||
struct Core3_timer_irq_control : Register<0x4c, 32> {};
|
||||
|
||||
struct Core0_irq_source : Register<0x60, 32> {};
|
||||
struct Core1_irq_source : Register<0x64, 32> {};
|
||||
struct Core2_irq_source : Register<0x68, 32> {};
|
||||
struct Core3_irq_source : Register<0x6c, 32> {};
|
||||
|
||||
public:
|
||||
|
||||
Pic();
|
||||
|
||||
void init_cpu_local();
|
||||
bool take_request(unsigned &irq);
|
||||
void finish_request() { }
|
||||
void mask();
|
||||
void unmask(unsigned const i, unsigned);
|
||||
void mask(unsigned const i);
|
||||
|
||||
static constexpr bool fast_interrupts() { return false; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__RPI3__PIC_H_ */
|
60
repos/base-hw/src/core/spec/rpi3/timer.cc
Normal file
60
repos/base-hw/src/core/spec/rpi3/timer.cc
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* \brief Timer driver for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
#include <drivers/timer/util.h>
|
||||
#include <kernel/timer.h>
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
||||
unsigned Timer::interrupt_id() const { return Genode::Pic::TIMER_IRQ; }
|
||||
|
||||
|
||||
unsigned long Timer_driver::_freq() { return Genode::Cpu::Cntfrq_el0::read(); }
|
||||
|
||||
|
||||
Timer_driver::Timer_driver(unsigned) : ticks_per_ms(_freq() / 1000)
|
||||
{
|
||||
Cpu::Cntp_ctl_el0::access_t ctl = 0;
|
||||
Cpu::Cntp_ctl_el0::Enable::set(ctl, 1);
|
||||
Cpu::Cntp_ctl_el0::write(ctl);
|
||||
}
|
||||
|
||||
|
||||
void Timer::_start_one_shot(time_t const ticks)
|
||||
{
|
||||
_driver.last_time = Cpu::Cntpct_el0::read();
|
||||
Cpu::Cntp_tval_el0::write(ticks);
|
||||
Cpu::Cntp_ctl_el0::access_t ctl = Cpu::Cntp_ctl_el0::read();
|
||||
Cpu::Cntp_ctl_el0::Istatus::set(ctl, 0);
|
||||
Cpu::Cntp_ctl_el0::write(ctl);
|
||||
}
|
||||
|
||||
|
||||
time_t Timer::_duration() const
|
||||
{
|
||||
return Cpu::Cntpct_el0::read() - _driver.last_time;
|
||||
}
|
||||
|
||||
|
||||
time_t Timer::ticks_to_us(time_t const ticks) const {
|
||||
return Genode::timer_ticks_to_us(ticks, _driver.ticks_per_ms); }
|
||||
|
||||
|
||||
time_t Timer::us_to_ticks(time_t const us) const {
|
||||
return (us / 1000) * _driver.ticks_per_ms; }
|
||||
|
||||
|
||||
time_t Timer::_max_value() const {
|
||||
return _driver.ticks_per_ms * 5000; }
|
34
repos/base-hw/src/core/spec/rpi3/timer_driver.h
Normal file
34
repos/base-hw/src/core/spec/rpi3/timer_driver.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* \brief Timer driver for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Kernel OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_DRIVER_H_
|
||||
#define _TIMER_DRIVER_H_
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/types.h>
|
||||
|
||||
namespace Kernel { class Timer_driver; }
|
||||
|
||||
|
||||
struct Kernel::Timer_driver
|
||||
{
|
||||
unsigned long _freq();
|
||||
|
||||
unsigned const ticks_per_ms;
|
||||
|
||||
time_t last_time { 0 };
|
||||
|
||||
Timer_driver(unsigned);
|
||||
};
|
||||
|
||||
#endif /* _TIMER_DRIVER_H_ */
|
179
repos/base-hw/src/include/hw/spec/arm_64/cpu.h
Normal file
179
repos/base-hw/src/include/hw/spec/arm_64/cpu.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* \brief CPU definitions for ARM 64bit
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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__ARM_64__CPU_H_
|
||||
#define _SRC__LIB__HW__SPEC__ARM_64__CPU_H_
|
||||
|
||||
#define SYSTEM_REGISTER(sz, name, reg, ...) \
|
||||
struct name : Genode::Register<sz> \
|
||||
{ \
|
||||
static access_t read() \
|
||||
{ \
|
||||
access_t v; \
|
||||
asm volatile ("mrs %0, " #reg : "=r" (v)); \
|
||||
return v; \
|
||||
} \
|
||||
\
|
||||
static void write(access_t const v) { \
|
||||
asm volatile ("msr " #reg ", %0" :: "r" (v)); } \
|
||||
\
|
||||
__VA_ARGS__; \
|
||||
};
|
||||
|
||||
|
||||
namespace Hw { struct Arm_64_cpu; }
|
||||
|
||||
struct Hw::Arm_64_cpu
|
||||
{
|
||||
SYSTEM_REGISTER(64, Id_pfr0, id_aa64pfr0_el1,
|
||||
struct El2 : Bitfield<8, 4> {};
|
||||
struct El3 : Bitfield<8, 4> {};
|
||||
);
|
||||
|
||||
SYSTEM_REGISTER(64, Cntfrq_el0, cntfrq_el0);
|
||||
|
||||
SYSTEM_REGISTER(64, Current_el, currentel,
|
||||
enum Level { EL0, EL1, EL2, EL3 };
|
||||
struct El : Bitfield<2, 2> {};
|
||||
);
|
||||
|
||||
struct Esr : Genode::Register<64>
|
||||
{
|
||||
struct Ec : Bitfield<26, 6>
|
||||
{
|
||||
enum Exception {
|
||||
SVC = 0b010101,
|
||||
INST_ABORT_LOW_LEVEL = 0b100000,
|
||||
INST_ABORT_SAME_LEVEL = 0b100001,
|
||||
DATA_ABORT_LOW_LEVEL = 0b100100,
|
||||
DATA_ABORT_SAME_LEVEL = 0b100101,
|
||||
};
|
||||
};
|
||||
|
||||
struct Iss : Bitfield<0, 25>
|
||||
{
|
||||
struct Abort : Register<32>
|
||||
{
|
||||
struct Level : Bitfield<0, 2> {};
|
||||
struct Fsc : Bitfield<2, 4>
|
||||
{
|
||||
enum Fault {
|
||||
ADDR_SIZE,
|
||||
TRANSLATION,
|
||||
ACCESS_FLAG,
|
||||
PERMISSION
|
||||
};
|
||||
enum Data_abort_fault { ALIGNMENT = 8 };
|
||||
};
|
||||
struct Write : Bitfield<6, 1> {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SYSTEM_REGISTER(64, Esr_el1, esr_el1);
|
||||
SYSTEM_REGISTER(64, Far_el1, far_el1);
|
||||
|
||||
SYSTEM_REGISTER(64, Hcr, hcr_el2,
|
||||
struct Rw : Bitfield<31, 1> {};
|
||||
);
|
||||
|
||||
SYSTEM_REGISTER(64, Mair, mair_el1,
|
||||
enum Attributes {
|
||||
DEVICE_MEMORY = 0x04,
|
||||
NORMAL_MEMORY_UNCACHED = 0x44,
|
||||
NORMAL_MEMORY_CACHED = 0xff,
|
||||
};
|
||||
struct Attr0 : Bitfield<0, 8> {};
|
||||
struct Attr1 : Bitfield<8, 8> {};
|
||||
struct Attr2 : Bitfield<16, 8> {};
|
||||
struct Attr3 : Bitfield<24, 8> {};
|
||||
);
|
||||
|
||||
SYSTEM_REGISTER(64, Scr, scr_el3,
|
||||
struct Ns : Bitfield<0, 1> {};
|
||||
struct Smd : Bitfield<7, 1> {};
|
||||
struct Rw : Bitfield<10, 1> {};
|
||||
);
|
||||
|
||||
SYSTEM_REGISTER(64, Sctlr_el1, sctlr_el1,
|
||||
struct M : Bitfield<0, 1> { };
|
||||
struct A : Bitfield<1, 1> { };
|
||||
struct C : Bitfield<2, 1> { };
|
||||
struct Sa : Bitfield<3, 1> { };
|
||||
struct Sa0 : Bitfield<4, 1> { };
|
||||
struct I : Bitfield<12, 1> { };
|
||||
);
|
||||
|
||||
struct Spsr : Genode::Register<64>
|
||||
{
|
||||
struct Sp : Bitfield<0, 1> {};
|
||||
struct El : Bitfield<2, 2> {};
|
||||
struct F : Bitfield<6, 1> {};
|
||||
struct I : Bitfield<7, 1> {};
|
||||
struct A : Bitfield<8, 1> {};
|
||||
struct D : Bitfield<9, 1> {};
|
||||
};
|
||||
|
||||
SYSTEM_REGISTER(64, Spsr_el2, spsr_el2);
|
||||
SYSTEM_REGISTER(64, Spsr_el3, spsr_el3);
|
||||
|
||||
SYSTEM_REGISTER(64, Tcr_el1, tcr_el1,
|
||||
struct T0sz : Bitfield<0, 6> { };
|
||||
struct Epd0 : Bitfield<7, 1> { };
|
||||
struct Irgn0 : Bitfield<8, 2> { };
|
||||
struct Orgn0 : Bitfield<10, 2> { };
|
||||
struct Sh0 : Bitfield<12, 2> { };
|
||||
struct Tg0 : Bitfield<14, 2> { };
|
||||
struct T1sz : Bitfield<16, 6> { };
|
||||
struct A1 : Bitfield<22, 1> { };
|
||||
struct Epd1 : Bitfield<23, 1> { };
|
||||
struct Irgn1 : Bitfield<24, 2> { };
|
||||
struct Orgn1 : Bitfield<26, 2> { };
|
||||
struct Sh1 : Bitfield<28, 2> { };
|
||||
struct Tg1 : Bitfield<30, 2> { };
|
||||
struct Ips : Bitfield<32, 3> { };
|
||||
struct As : Bitfield<36, 1> { };
|
||||
);
|
||||
|
||||
struct Ttbr : Genode::Register<64>
|
||||
{
|
||||
struct Baddr : Bitfield<0, 48> { };
|
||||
struct Asid : Bitfield<48, 16> { };
|
||||
};
|
||||
|
||||
SYSTEM_REGISTER(64, Ttbr0_el1, ttbr0_el1);
|
||||
SYSTEM_REGISTER(64, Ttbr1_el1, ttbr1_el1);
|
||||
|
||||
SYSTEM_REGISTER(64, Vbar_el1, vbar_el1);
|
||||
|
||||
static inline unsigned current_privilege_level() {
|
||||
return Current_el::El::get(Current_el::read()); }
|
||||
|
||||
|
||||
/*****************************
|
||||
** Generic timer interface **
|
||||
*****************************/
|
||||
|
||||
SYSTEM_REGISTER(32, Cntp_ctl_el0, cntp_ctl_el0,
|
||||
struct Enable : Bitfield<0, 1> {};
|
||||
struct Istatus : Bitfield<2, 1> {};
|
||||
);
|
||||
|
||||
SYSTEM_REGISTER(64, Cntpct_el0, cntpct_el0);
|
||||
SYSTEM_REGISTER(32, Cntp_tval_el0, cntp_tval_el0);
|
||||
};
|
||||
|
||||
|
||||
#undef SYSTEM_REGISTER
|
||||
|
||||
#endif /* _SRC__LIB__HW__SPEC__ARM_64__CPU_H_ */
|
41
repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h
Normal file
41
repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* \brief Board definitions for Raspberry Pi 3
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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__ARM__RPI3__BOARD_H_
|
||||
#define _SRC__INCLUDE__HW__SPEC__ARM__RPI3__BOARD_H_
|
||||
|
||||
#include <drivers/uart/bcm2835_mini.h>
|
||||
#include <hw/spec/arm/boot_info.h>
|
||||
|
||||
namespace Hw::Rpi3_board {
|
||||
using Serial = Genode::Bcm2835_mini_uart;
|
||||
|
||||
enum {
|
||||
RAM_BASE = 0,
|
||||
RAM_SIZE = 0x20000000,
|
||||
|
||||
UART_BASE = 0x3f215000,
|
||||
UART_SIZE = 0x1000,
|
||||
UART_CLOCK = 250000000,
|
||||
|
||||
IRQ_CONTROLLER_BASE = 0x3f00b000,
|
||||
IRQ_CONTROLLER_SIZE = 0x1000,
|
||||
|
||||
LOCAL_IRQ_CONTROLLER_BASE = 0x40000000,
|
||||
LOCAL_IRQ_CONTROLLER_SIZE = 0x1000,
|
||||
|
||||
CACHE_LINE_SIZE_LOG2 = 6,
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SRC__INCLUDE__HW__SPEC__ARM__RPI3__BOARD_H_ */
|
125
repos/base-hw/src/lib/base/arm_64/kernel/interface.cc
Normal file
125
repos/base-hw/src/lib/base/arm_64/kernel/interface.cc
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* \brief Interface between kernel and userland
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
||||
/************************************
|
||||
** Helper macros for kernel calls **
|
||||
************************************/
|
||||
|
||||
#define CALL_1_FILL_ARG_REGS \
|
||||
register Call_arg arg_0_reg asm("x0") = arg_0;
|
||||
|
||||
#define CALL_2_FILL_ARG_REGS \
|
||||
CALL_1_FILL_ARG_REGS \
|
||||
register Call_arg arg_1_reg asm("x1") = arg_1;
|
||||
|
||||
#define CALL_3_FILL_ARG_REGS \
|
||||
CALL_2_FILL_ARG_REGS \
|
||||
register Call_arg arg_2_reg asm("x2") = arg_2;
|
||||
|
||||
#define CALL_4_FILL_ARG_REGS \
|
||||
CALL_3_FILL_ARG_REGS \
|
||||
register Call_arg arg_3_reg asm("x3") = arg_3;
|
||||
|
||||
#define CALL_5_FILL_ARG_REGS \
|
||||
CALL_4_FILL_ARG_REGS \
|
||||
register Call_arg arg_4_reg asm("x4") = arg_4;
|
||||
|
||||
#define CALL_6_FILL_ARG_REGS \
|
||||
CALL_5_FILL_ARG_REGS \
|
||||
register Call_arg arg_5_reg asm("x5") = arg_5;
|
||||
|
||||
#define CALL_1_SWI "svc 0\n" : "+r" (arg_0_reg)
|
||||
#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)
|
||||
#define CALL_6_SWI CALL_5_SWI, "r" (arg_5_reg)
|
||||
|
||||
|
||||
/******************
|
||||
** Kernel calls **
|
||||
******************/
|
||||
|
||||
Call_ret_64 Kernel::call64(Call_arg arg_0)
|
||||
{
|
||||
return Kernel::call(arg_0);
|
||||
}
|
||||
|
||||
|
||||
Call_ret Kernel::call(Call_arg arg_0)
|
||||
{
|
||||
CALL_1_FILL_ARG_REGS
|
||||
asm volatile(CALL_1_SWI);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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_arg arg_5)
|
||||
{
|
||||
CALL_6_FILL_ARG_REGS
|
||||
asm volatile(CALL_6_SWI);
|
||||
return arg_0_reg;
|
||||
}
|
@ -42,6 +42,11 @@ namespace Rpi {
|
||||
PL011_0_MMIO_SIZE = 0x1000,
|
||||
PL011_0_CLOCK = 3000000,
|
||||
|
||||
PL011_1_IRQ = 61,
|
||||
PL011_1_MMIO_BASE = 0x20215000,
|
||||
PL011_1_MMIO_SIZE = 0x1000,
|
||||
PL011_1_CLOCK = 3000000,
|
||||
|
||||
IRQ_CONTROLLER_BASE = 0x2000b200,
|
||||
IRQ_CONTROLLER_SIZE = 0x100,
|
||||
|
||||
|
@ -19,6 +19,7 @@ proc bootstrap_link_address { } {
|
||||
if {[have_spec "zynq"]} { return "0x00100000" }
|
||||
if {[have_spec "riscv"]} { return "0x81000000" }
|
||||
if {[have_spec "rpi"]} { return "0x00800000" }
|
||||
if {[have_spec "rpi3"]} { return "0x00800000" }
|
||||
if {[have_spec "nit6_solox"]} { return "0x88000000" }
|
||||
|
||||
puts "unknown platform no linker address known"
|
||||
@ -154,7 +155,7 @@ proc run_boot_dir {binaries} {
|
||||
run_image [run_dir]/boot/image.elf
|
||||
|
||||
# set symbolic link to image.elf file in TFTP directory for PXE boot
|
||||
if {[have_spec arm] && [have_include "load/tftp"]} {
|
||||
if {[expr [have_spec arm] || [have_spec arm_64]] && [have_include "load/tftp"]} {
|
||||
exec ln -sf [run_dir]/boot/image.elf [load_tftp_base_dir][load_tftp_offset_dir]
|
||||
|
||||
if {[have_include "image/uboot"]} {
|
||||
|
Loading…
x
Reference in New Issue
Block a user