diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk new file mode 100644 index 000000000..1df46954b --- /dev/null +++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-imx8q_evk.mk @@ -0,0 +1,12 @@ +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/imx8q_evk + +SRC_CC += bootstrap/spec/arm/gicv3.cc +SRC_CC += bootstrap/spec/arm_64/cortex_a53_mmu.cc +SRC_CC += bootstrap/spec/imx8q_evk/platform.cc +SRC_CC += lib/base/arm_64/kernel/interface.cc +SRC_CC += spec/64bit/memory_map.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/bootstrap-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-rpi3.mk index d05f8d1a7..788be2348 100644 --- 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 @@ -1,8 +1,9 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/rpi3 +SRC_CC += bootstrap/spec/arm_64/cortex_a53_mmu.cc +SRC_CC += bootstrap/spec/rpi3/platform.cc 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 diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk new file mode 100644 index 000000000..626d7cfde --- /dev/null +++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-imx8q_evk.mk @@ -0,0 +1,24 @@ +INC_DIR += $(REP_DIR)/src/core/spec/imx8q_evk +INC_DIR += $(REP_DIR)/src/core/spec/arm_v8 + +# add C++ sources +SRC_CC += kernel/cpu_up.cc +SRC_CC += kernel/lock.cc +SRC_CC += kernel/vm_thread_off.cc +SRC_CC += platform_services.cc +SRC_CC += spec/64bit/memory_map.cc +SRC_CC += spec/arm/generic_timer.cc +SRC_CC += spec/arm/gicv3.cc +SRC_CC += spec/arm/platform_support.cc +SRC_CC += spec/arm_v8/cpu.cc +SRC_CC += spec/arm_v8/kernel/cpu.cc +SRC_CC += spec/arm_v8/kernel/thread.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/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc new file mode 100644 index 000000000..f0e24e7cc --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc @@ -0,0 +1,132 @@ +/* + * \brief Platform implementations specific for Cortex A53 CPUs + * \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 Board::Cpu; + + +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(); + } + + /* enable performance counter for user-land */ + Cpu::Pmuserenr_el0::write(0b1111); + + 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/bootstrap/spec/imx8q_evk/board.h b/repos/base-hw/src/bootstrap/spec/imx8q_evk/board.h new file mode 100644 index 000000000..2784a3b13 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/imx8q_evk/board.h @@ -0,0 +1,28 @@ +/* + * \brief Board driver for bootstrap + * \author Stefan Kalkowski + * \date 2019-06-12 + */ + +/* + * 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__IMX8Q_EVK__BOARD_H_ +#define _BOOTSTRAP__SPEC__IMX8Q_EVK__BOARD_H_ + +#include +#include +#include +#include + +namespace Board { + using namespace Hw::Imx8q_evk_board; + using Cpu = Hw::Arm_64_cpu; + using Hw::Pic; +}; + +#endif /* _BOOTSTRAP__SPEC__IMX8Q_EVK__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc b/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc new file mode 100644 index 000000000..72bb6e49a --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/imx8q_evk/platform.cc @@ -0,0 +1,27 @@ +/* + * \brief Platform implementations specific for base-hw and i.MX8Q EVK + * \author Stefan Kalkowski + * \date 2019-06-12 + */ + +/* + * 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 + +/** + * 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, ::Board::RAM_SIZE }), + late_ram_regions(Memory_region { }), + core_mmio(Memory_region { ::Board::UART_BASE, ::Board::UART_SIZE }, + Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE, + ::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE }, + Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE, + ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE }) {} diff --git a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc index 75457ddf3..772147938 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/rpi3/platform.cc @@ -13,9 +13,6 @@ #include -using Board::Cpu; - - /** * Leave out the first page (being 0x0) from bootstraps RAM allocator, * some code does not feel happy with addresses being zero @@ -29,119 +26,3 @@ Bootstrap::Platform::Board::Board() ::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(); - } - - /* enable performance counter for user-land */ - Cpu::Pmuserenr_el0::write(0b1111); - - 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/imx8q_evk/board.h b/repos/base-hw/src/core/spec/imx8q_evk/board.h new file mode 100644 index 000000000..35a58c826 --- /dev/null +++ b/repos/base-hw/src/core/spec/imx8q_evk/board.h @@ -0,0 +1,28 @@ +/* + * \brief Board driver for core + * \author Stefan Kalkowski + * \date 2019-06-12 + */ + +/* + * 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__IMX8Q_EVK__BOARD_H_ +#define _CORE__SPEC__IMX8Q_EVK__BOARD_H_ + +#include +#include +#include + +namespace Board { + using namespace Hw::Imx8q_evk_board; + using Hw::Pic; + + enum { TIMER_IRQ = 30 }; +}; + +#endif /* _CORE__SPEC__IMX8Q_EVK__BOARD_H_ */ diff --git a/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h b/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h new file mode 100644 index 000000000..4b199b4e8 --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/arm_64/imx8q_evk_board.h @@ -0,0 +1,44 @@ +/* + * \brief Board definitions for i.MX8 Quad EVK + * \author Stefan Kalkowski + * \date 2019-06-12 + */ + +/* + * 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_64__IMX8Q_EVK__BOARD_H_ +#define _SRC__INCLUDE__HW__SPEC__ARM_64__IMX8Q_EVK__BOARD_H_ + +#include +#include + +namespace Hw::Imx8q_evk_board { + using Serial = Genode::Imx_uart; + + enum { + RAM_BASE = 0x40000000, + RAM_SIZE = 0xc0000000, + + UART_BASE = 0x30860000, + UART_SIZE = 0x1000, + UART_CLOCK = 250000000, + + CACHE_LINE_SIZE_LOG2 = 6, + }; + + namespace Cpu_mmio { + enum { + IRQ_CONTROLLER_DISTR_BASE = 0x38800000, + IRQ_CONTROLLER_DISTR_SIZE = 0x10000, + IRQ_CONTROLLER_REDIST_BASE = 0x38880000, + IRQ_CONTROLLER_REDIST_SIZE = 0x20000, /* per core */ + }; + }; +}; + +#endif /* _SRC__INCLUDE__HW__SPEC__ARM_64__IMX8Q_EVK__BOARD_H_ */ diff --git a/tool/run/boot_dir/hw b/tool/run/boot_dir/hw index aae4ebb8a..ea6a70020 100644 --- a/tool/run/boot_dir/hw +++ b/tool/run/boot_dir/hw @@ -14,6 +14,7 @@ proc bootstrap_link_address { } { if {[have_spec "imx6q_sabrelite"]} { return "0x10001000" } if {[have_spec "imx53_qsb"]} { return "0x70010000" } if {[have_spec "imx7d_sabre"]} { return "0x88000000" } + if {[have_spec "imx8q_evk"]} { return "0x40010000" } if {[have_spec "arndale"]} { return "0x88000000" } if {[have_spec "panda"]} { return "0x88000000" } if {[have_spec "zynq"]} { return "0x00100000" }