diff --git a/repos/base-hw/include/spec/arm_64/kernel/interface_support.h b/repos/base-hw/include/spec/arm_64/kernel/interface_support.h
new file mode 100644
index 0000000000..16e4fafeef
--- /dev/null
+++ b/repos/base-hw/include/spec/arm_64/kernel/interface_support.h
@@ -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
+
+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_ */
diff --git a/repos/base-hw/lib/mk/spec/arm_64/startup-hw.mk b/repos/base-hw/lib/mk/spec/arm_64/startup-hw.mk
new file mode 100644
index 0000000000..613d120742
--- /dev/null
+++ b/repos/base-hw/lib/mk/spec/arm_64/startup-hw.mk
@@ -0,0 +1,3 @@
+include $(BASE_DIR)/lib/mk/startup.inc
+
+vpath crt0.s $(BASE_DIR)/src/lib/startup/spec/arm_64
diff --git a/repos/base-hw/lib/mk/spec/arm_64/syscall-hw.mk b/repos/base-hw/lib/mk/spec/arm_64/syscall-hw.mk
new file mode 100644
index 0000000000..e77c96c1fd
--- /dev/null
+++ b/repos/base-hw/lib/mk/spec/arm_64/syscall-hw.mk
@@ -0,0 +1,3 @@
+SRC_CC += kernel/interface.cc
+
+vpath kernel/interface.cc $(REP_DIR)/src/lib/base/arm_64
diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk
new file mode 100644
index 0000000000..d05f8d1a73
--- /dev/null
+++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk
@@ -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
diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk
new file mode 100644
index 0000000000..4c75401c75
--- /dev/null
+++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk
@@ -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
diff --git a/repos/base-hw/lib/mk/spec/arm_v8/ld-hw.mk b/repos/base-hw/lib/mk/spec/arm_v8/ld-hw.mk
new file mode 100644
index 0000000000..c79c372e28
--- /dev/null
+++ b/repos/base-hw/lib/mk/spec/arm_v8/ld-hw.mk
@@ -0,0 +1,3 @@
+BASE_LIBS += base-hw-common base-hw
+
+include $(BASE_DIR)/lib/mk/spec/arm_64/ld-platform.inc
diff --git a/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s b/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s
new file mode 100644
index 0000000000..98de01e670
--- /dev/null
+++ b/repos/base-hw/src/bootstrap/spec/arm_64/crt0.s
@@ -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:
diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/board.h b/repos/base-hw/src/bootstrap/spec/rpi3/board.h
new file mode 100644
index 0000000000..d2a30a65ce
--- /dev/null
+++ b/repos/base-hw/src/bootstrap/spec/rpi3/board.h
@@ -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
+#include
+#include
+
+namespace Bootstrap {
+ using Cpu = Hw::Arm_64_cpu;
+ struct Pic {};
+};
+
+namespace Board {
+ using namespace Hw::Rpi3_board;
+};
+
+#endif /* _BOOTSTRAP__SPEC__RPI3__BOARD_H_ */
diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc
new file mode 100644
index 0000000000..a015a355be
--- /dev/null
+++ b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc
@@ -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
+
+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;
+}
diff --git a/repos/base-hw/src/core/spec/arm_v8/cpu.cc b/repos/base-hw/src/core/spec/arm_v8/cpu.cc
new file mode 100644
index 0000000000..57cfbd4802
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/cpu.cc
@@ -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
+#include
+#include
+#include
+
+
+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(); }
+
+
+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)); }
+}
diff --git a/repos/base-hw/src/core/spec/arm_v8/cpu.h b/repos/base-hw/src/core/spec/arm_v8/cpu.h
new file mode 100644
index 0000000000..337f332fa6
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/cpu.h
@@ -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
+#include
+#include
+#include
+
+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_ */
diff --git a/repos/base-hw/src/core/spec/arm_v8/crt0.s b/repos/base-hw/src/core/spec/arm_v8/crt0.s
new file mode 100644
index 0000000000..9adb479fbd
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/crt0.s
@@ -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
diff --git a/repos/base-hw/src/core/spec/arm_v8/exception_vector.s b/repos/base-hw/src/core/spec/arm_v8/exception_vector.s
new file mode 100644
index 0000000000..d96c35e590
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/exception_vector.s
@@ -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
diff --git a/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc
new file mode 100644
index 0000000000..6954642b08
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/kernel/cpu.cc
@@ -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
+
+void Kernel::Cpu::_arch_init()
+{
+ /* enable timer interrupt */
+ _pic.unmask(_timer.interrupt_id(), id());
+}
diff --git a/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc b/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
new file mode 100644
index 0000000000..1f021cc3f6
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc
@@ -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
+#include
+#include
+#include
+
+#include
+
+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(&*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]; }
diff --git a/repos/base-hw/src/core/spec/arm_v8/translation_table.h b/repos/base-hw/src/core/spec/arm_v8/translation_table.h
new file mode 100644
index 0000000000..56fb10f856
--- /dev/null
+++ b/repos/base-hw/src/core/spec/arm_v8/translation_table.h
@@ -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
+
+#endif /* _CORE__SPEC__ARM_V8__TRANSLATION_TABLE_H_ */
diff --git a/repos/base-hw/src/core/spec/rpi3/board.h b/repos/base-hw/src/core/spec/rpi3/board.h
new file mode 100644
index 0000000000..2b3c0e35ce
--- /dev/null
+++ b/repos/base-hw/src/core/spec/rpi3/board.h
@@ -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
+
+namespace Board {
+ using namespace Hw::Rpi3_board;
+
+ static constexpr bool SMP = true;
+};
+
+#endif /* _CORE__SPEC__RPI3__BOARD_H_ */
diff --git a/repos/base-hw/src/core/spec/rpi3/pic.cc b/repos/base-hw/src/core/spec/rpi3/pic.cc
new file mode 100644
index 0000000000..3c464add5d
--- /dev/null
+++ b/repos/base-hw/src/core/spec/rpi3/pic.cc
@@ -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
+#include
+
+
+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();
+ 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(1);
+ return;
+ }
+
+ Genode::raw("irq of peripherals != timer not implemented yet!");
+}
+
+
+void Genode::Pic::mask(unsigned const i)
+{
+ if (i == TIMER_IRQ) {
+ write(0);
+ return;
+ }
+
+ Genode::raw("irq of peripherals != timer not implemented yet!");
+}
diff --git a/repos/base-hw/src/core/spec/rpi3/pic.h b/repos/base-hw/src/core/spec/rpi3/pic.h
new file mode 100644
index 0000000000..b28966311e
--- /dev/null
+++ b/repos/base-hw/src/core/spec/rpi3/pic.h
@@ -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
+#include
+
+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_ */
diff --git a/repos/base-hw/src/core/spec/rpi3/timer.cc b/repos/base-hw/src/core/spec/rpi3/timer.cc
new file mode 100644
index 0000000000..0c5b8d32b4
--- /dev/null
+++ b/repos/base-hw/src/core/spec/rpi3/timer.cc
@@ -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
+#include
+#include
+
+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; }
diff --git a/repos/base-hw/src/core/spec/rpi3/timer_driver.h b/repos/base-hw/src/core/spec/rpi3/timer_driver.h
new file mode 100644
index 0000000000..3a72a72c5f
--- /dev/null
+++ b/repos/base-hw/src/core/spec/rpi3/timer_driver.h
@@ -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
+
+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_ */
diff --git a/repos/base-hw/src/include/hw/spec/arm_64/cpu.h b/repos/base-hw/src/include/hw/spec/arm_64/cpu.h
new file mode 100644
index 0000000000..1b5684ee94
--- /dev/null
+++ b/repos/base-hw/src/include/hw/spec/arm_64/cpu.h
@@ -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 \
+ { \
+ 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_ */
diff --git a/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h b/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h
new file mode 100644
index 0000000000..9d8d841a8f
--- /dev/null
+++ b/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h
@@ -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
+#include
+
+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_ */
diff --git a/repos/base-hw/src/lib/base/arm_64/kernel/interface.cc b/repos/base-hw/src/lib/base/arm_64/kernel/interface.cc
new file mode 100644
index 0000000000..5a1df3f416
--- /dev/null
+++ b/repos/base-hw/src/lib/base/arm_64/kernel/interface.cc
@@ -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
+
+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;
+}
diff --git a/repos/base/include/drivers/defs/rpi.h b/repos/base/include/drivers/defs/rpi.h
index ef7594cde6..3374a734e5 100644
--- a/repos/base/include/drivers/defs/rpi.h
+++ b/repos/base/include/drivers/defs/rpi.h
@@ -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,
diff --git a/tool/run/boot_dir/hw b/tool/run/boot_dir/hw
index 3fa5aaa2bd..f7d6e107a8 100644
--- a/tool/run/boot_dir/hw
+++ b/tool/run/boot_dir/hw
@@ -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"]} {