From 585c4b8c69f1a5fb73a9b730c748baf1203628f9 Mon Sep 17 00:00:00 2001 From: Piotr Tworek Date: Sun, 15 Sep 2019 01:10:20 +0200 Subject: [PATCH] hw: Add support for Qemu virt arm platforms. This patch adds support for booting base-hw kernel on qemu-arm virt machines. The arm_virt machine has 2GB of RAM, 2 Cortex A15 cores and uses GICv2 interrupt controller. The arm_64_virt machine also has 2GB of RAM, but has 4 Cortex A53 cores and uses GICv3. Both machines use PSCI to boot additional CPU cores. Fixes #3673 --- .../mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk | 14 +++++ .../lib/mk/spec/arm_v7/core-hw-virt_qemu.mk | 13 ++++ .../mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk | 14 +++++ .../lib/mk/spec/arm_v8/core-hw-virt_qemu.mk | 26 ++++++++ .../recipes/src/base-hw-virt_qemu/content.mk | 7 +++ .../recipes/src/base-hw-virt_qemu/hash | 1 + .../recipes/src/base-hw-virt_qemu/used_apis | 2 + .../src/bootstrap/spec/virt_qemu/board.h | 31 ++++++++++ .../src/bootstrap/spec/virt_qemu/platform.cc | 59 +++++++++++++++++++ .../src/bootstrap/spec/virt_qemu_64/board.h | 36 +++++++++++ .../bootstrap/spec/virt_qemu_64/platform.cc | 36 +++++++++++ repos/base-hw/src/core/spec/virt_qemu/board.h | 28 +++++++++ .../src/core/spec/virt_qemu_64/board.h | 28 +++++++++ .../src/include/hw/spec/arm/virt_qemu_board.h | 46 +++++++++++++++ tool/builddir/build.conf/run_arm_v7 | 3 +- tool/builddir/build.conf/run_arm_v8 | 5 +- tool/run/boot_dir/hw | 2 + tool/run/power_on/qemu | 11 ++++ 18 files changed, 359 insertions(+), 3 deletions(-) create mode 100644 repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk create mode 100644 repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk create mode 100644 repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk create mode 100644 repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk create mode 100644 repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk create mode 100644 repos/base-hw/recipes/src/base-hw-virt_qemu/hash create mode 100644 repos/base-hw/recipes/src/base-hw-virt_qemu/used_apis create mode 100644 repos/base-hw/src/bootstrap/spec/virt_qemu/board.h create mode 100644 repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc create mode 100644 repos/base-hw/src/bootstrap/spec/virt_qemu_64/board.h create mode 100644 repos/base-hw/src/bootstrap/spec/virt_qemu_64/platform.cc create mode 100644 repos/base-hw/src/core/spec/virt_qemu/board.h create mode 100644 repos/base-hw/src/core/spec/virt_qemu_64/board.h create mode 100644 repos/base-hw/src/include/hw/spec/arm/virt_qemu_board.h diff --git a/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk new file mode 100644 index 000000000..9764104d4 --- /dev/null +++ b/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw-virt_qemu.mk @@ -0,0 +1,14 @@ +INC_DIR += $(REP_DIR)/src/bootstrap/spec/virt_qemu + +SRC_CC += bootstrap/spec/arm/arm_v7_cpu.cc +SRC_CC += bootstrap/spec/arm/cortex_a15_cpu.cc +SRC_CC += bootstrap/spec/arm/gicv2.cc +SRC_CC += bootstrap/spec/virt_qemu/platform.cc +SRC_CC += hw/spec/32bit/memory_map.cc +SRC_S += bootstrap/spec/arm/crt0.s + +NR_OF_CPUS = 2 + +CC_MARCH = -march=armv7ve -mtune=cortex-a15 -mfpu=vfpv3 -mfloat-abi=softfp + +include $(REP_DIR)/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk new file mode 100644 index 000000000..64fb035bf --- /dev/null +++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw-virt_qemu.mk @@ -0,0 +1,13 @@ +INC_DIR += $(REP_DIR)/src/core/spec/virt_qemu + +# add C++ sources +SRC_CC += kernel/vm_thread_off.cc +SRC_CC += platform_services.cc +SRC_CC += spec/arm/generic_timer.cc +SRC_CC += spec/arm/gicv2.cc + +NR_OF_CPUS = 2 + +CC_MARCH = -march=armv7ve -mtune=cortex-a15 -mfpu=vfpv3 -mfloat-abi=soft + +include $(REP_DIR)/lib/mk/spec/cortex_a15/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk new file mode 100644 index 000000000..48df14a0a --- /dev/null +++ b/repos/base-hw/lib/mk/spec/arm_v8/bootstrap-hw-virt_qemu.mk @@ -0,0 +1,14 @@ +INC_DIR += $(REP_DIR)/src/bootstrap/spec/virt_qemu_64 + +SRC_CC += bootstrap/spec/arm/gicv3.cc +SRC_CC += bootstrap/spec/arm_64/cortex_a53_mmu.cc +SRC_CC += bootstrap/spec/virt_qemu_64/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 + +NR_OF_CPUS = 4 + +include $(REP_DIR)/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk new file mode 100644 index 000000000..cea773992 --- /dev/null +++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-virt_qemu.mk @@ -0,0 +1,26 @@ +INC_DIR += $(REP_DIR)/src/core/spec/virt_qemu_64 +INC_DIR += $(REP_DIR)/src/core/spec/arm_v8 + +# add C++ sources +SRC_CC += kernel/cpu_mp.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/kernel/lock.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 + +NR_OF_CPUS = 4 + +# include less specific configuration +include $(REP_DIR)/lib/mk/core-hw.inc diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk b/repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk new file mode 100644 index 000000000..87fbf761b --- /dev/null +++ b/repos/base-hw/recipes/src/base-hw-virt_qemu/content.mk @@ -0,0 +1,7 @@ +BOARD = virt_qemu + +include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc + +content: enable_board_spec +enable_board_spec: etc/specs.conf + echo "SPECS += virt_qemu" >> etc/specs.conf diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu/hash b/repos/base-hw/recipes/src/base-hw-virt_qemu/hash new file mode 100644 index 000000000..9b7137ee7 --- /dev/null +++ b/repos/base-hw/recipes/src/base-hw-virt_qemu/hash @@ -0,0 +1 @@ +2020-02-10 bddcf1924aa3e440d8c728ce1a880da4489750d0 diff --git a/repos/base-hw/recipes/src/base-hw-virt_qemu/used_apis b/repos/base-hw/recipes/src/base-hw-virt_qemu/used_apis new file mode 100644 index 000000000..ed9b77256 --- /dev/null +++ b/repos/base-hw/recipes/src/base-hw-virt_qemu/used_apis @@ -0,0 +1,2 @@ +base-hw +base diff --git a/repos/base-hw/src/bootstrap/spec/virt_qemu/board.h b/repos/base-hw/src/bootstrap/spec/virt_qemu/board.h new file mode 100644 index 000000000..2df1bd3a5 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/virt_qemu/board.h @@ -0,0 +1,31 @@ +/* + * \brief Board driver for bootstrap + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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__BOOTSTRAP__SPEC__VIRT__QEMU_H_ +#define _SRC__BOOTSTRAP__SPEC__VIRT__QEMU_H_ + +#include +#include +#include +#include +#include + +namespace Board { + using namespace Hw::Virt_qemu_board; + + using Psci = Hw::Psci; + using Pic = Hw::Gicv2; + static constexpr bool NON_SECURE = false; +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__VIRT__QEMU_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc b/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc new file mode 100644 index 000000000..79498a403 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc @@ -0,0 +1,59 @@ +/* + * \brief Platform implementations specific for base-hw and Qemu arm virt machine + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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 + +extern "C" void * _start_setup_stack; + +using namespace Board; + +Bootstrap::Platform::Board::Board() +: early_ram_regions(Memory_region { RAM_BASE, RAM_SIZE }), + late_ram_regions(Memory_region { }), + core_mmio(Memory_region { UART_BASE, UART_SIZE }, + Memory_region { Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE, + Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE }, + Memory_region { Cpu_mmio::IRQ_CONTROLLER_CPU_BASE, + Cpu_mmio::IRQ_CONTROLLER_CPU_SIZE }) {} + + +unsigned Bootstrap::Platform::enable_mmu() +{ + static volatile bool primary_cpu = true; + + /* locally initialize interrupt controller */ + ::Board::Pic pic { }; + + Cpu::Sctlr::init(); + Cpu::Cpsr::init(); + + /* primary cpu wakes up all others */ + if (primary_cpu && NR_OF_CPUS > 1) { + Cpu::invalidate_data_cache(); + primary_cpu = false; + Cpu::wake_up_all_cpus(&_start_setup_stack); + } + + Cpu::enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); + return Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read()); +} + + +void Board::Cpu::wake_up_all_cpus(void * const ip) +{ + for (unsigned cpu_id = 1; cpu_id < NR_OF_CPUS; cpu_id++) { + if (!Board::Psci::cpu_on(cpu_id, ip)) { + Genode::error("Failed to boot CPU", cpu_id); + } + } +} diff --git a/repos/base-hw/src/bootstrap/spec/virt_qemu_64/board.h b/repos/base-hw/src/bootstrap/spec/virt_qemu_64/board.h new file mode 100644 index 000000000..507e6a249 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/virt_qemu_64/board.h @@ -0,0 +1,36 @@ +/* + * \brief Board driver for bootstrap + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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__BOOTSTRAP__SPEC__VIRT_QEMU_64_H_ +#define _SRC__BOOTSTRAP__SPEC__VIRT_QEMU_64_H_ + +#include +#include +#include +#include +#include + +namespace Board { + using namespace Hw::Virt_qemu_board; + + using Psci = Hw::Psci; + + struct Cpu : Hw::Arm_64_cpu + { + static void wake_up_all_cpus(void*); + }; + + using Hw::Pic; +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__VIRT_QEMU_64_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/virt_qemu_64/platform.cc b/repos/base-hw/src/bootstrap/spec/virt_qemu_64/platform.cc new file mode 100644 index 000000000..f5e2573de --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/virt_qemu_64/platform.cc @@ -0,0 +1,36 @@ +/* + * \brief Platform implementations specific for base-hw and Qemu arm64 virt machine + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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 + +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 }) +{ + ::Board::Pic pic {}; +} + + +void Board::Cpu::wake_up_all_cpus(void *entry) +{ + for (unsigned cpu_id = 1; cpu_id < NR_OF_CPUS; cpu_id++) { + if (!Board::Psci::cpu_on(cpu_id, entry)) { + Genode::error("Failed to boot CPU", cpu_id); + } + } +} diff --git a/repos/base-hw/src/core/spec/virt_qemu/board.h b/repos/base-hw/src/core/spec/virt_qemu/board.h new file mode 100644 index 000000000..e3f5175b7 --- /dev/null +++ b/repos/base-hw/src/core/spec/virt_qemu/board.h @@ -0,0 +1,28 @@ +/* + * \brief Arm virt board driver for core + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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__CORE__SPEC__VIRT__QEMU_H_ +#define _SRC__CORE__SPEC__VIRT__QEMU_H_ + +#include +#include +#include + +namespace Board { + using namespace Hw::Virt_qemu_board; + using Pic = Hw::Gicv2; + + enum { TIMER_IRQ = 30 /* PPI IRQ 14 */ }; +}; + +#endif /* _SRC__CORE__SPEC__VIRT__QEMU_H_ */ diff --git a/repos/base-hw/src/core/spec/virt_qemu_64/board.h b/repos/base-hw/src/core/spec/virt_qemu_64/board.h new file mode 100644 index 000000000..666220aa9 --- /dev/null +++ b/repos/base-hw/src/core/spec/virt_qemu_64/board.h @@ -0,0 +1,28 @@ +/* + * \brief Arm64 virt board driver for core + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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__CORE__SPEC__VIRT_QEMU_64_H_ +#define _SRC__CORE__SPEC__VIRT_QEMU_64_H_ + +#include +#include +#include + +namespace Board { + using namespace Hw::Virt_qemu_board; + using Hw::Pic; + + enum { TIMER_IRQ = 30 /* PPI IRQ 14 */ }; +}; + +#endif /* _SRC__CORE__SPEC__VIRT_QEMU_64_H_ */ diff --git a/repos/base-hw/src/include/hw/spec/arm/virt_qemu_board.h b/repos/base-hw/src/include/hw/spec/arm/virt_qemu_board.h new file mode 100644 index 000000000..97cac09d2 --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/arm/virt_qemu_board.h @@ -0,0 +1,46 @@ +/* + * \brief Board definitions for Qemu ARM virt machine + * \author Piotr Tworek + * \date 2019-09-15 + */ + +/* + * 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__VIRT_QEMU_BOARD_H_ +#define _SRC__INCLUDE__HW__SPEC__ARM__VIRT_QEMU_BOARD_H_ + +#include +#include + +namespace Hw::Virt_qemu_board { + using Serial = Genode::Pl011_uart; + + enum { + RAM_BASE = 0x40000000, + RAM_SIZE = 0x80000000, + + UART_BASE = 0x09000000, + UART_SIZE = 0x1000, + UART_CLOCK = 250000000, + + CACHE_LINE_SIZE_LOG2 = 6, + }; + + namespace Cpu_mmio { + enum { + IRQ_CONTROLLER_DISTR_BASE = 0x08000000, + IRQ_CONTROLLER_DISTR_SIZE = 0x10000, + IRQ_CONTROLLER_CPU_BASE = 0x08010000, + IRQ_CONTROLLER_CPU_SIZE = 0x10000, + IRQ_CONTROLLER_REDIST_BASE = 0x080A0000, + IRQ_CONTROLLER_REDIST_SIZE = 0xC0000, + }; + }; +}; + +#endif /* _SRC__INCLUDE__HW__SPEC__ARM__VIRT_QEMU_BOARD_H_ */ diff --git a/tool/builddir/build.conf/run_arm_v7 b/tool/builddir/build.conf/run_arm_v7 index a83a48b14..72fe3bb90 100644 --- a/tool/builddir/build.conf/run_arm_v7 +++ b/tool/builddir/build.conf/run_arm_v7 @@ -6,11 +6,12 @@ QEMU_RUN_OPT := --include power_on/qemu --include log/qemu # board to use (arndale, imx53_qsb, imx53_qsb_tz, imx6q_sabrelite, imx7d_sabre, # nit6_solox, odroid_xu, odroid_x2, panda, pbxa9, usb_armory, -# wand_quad, or zynq_qemu) +# virt_qemu, wand_quad, or zynq_qemu) #BOARD ?= pbxa9 # local variable for run-tool arguments that depend on the used board BOARD_RUN_OPT(pbxa9) = $(QEMU_RUN_OPT) +BOARD_RUN_OPT(virt_qemu) = $(QEMU_RUN_OPT) BOARD_RUN_OPT(zynq_qemu) = $(QEMU_RUN_OPT) ## diff --git a/tool/builddir/build.conf/run_arm_v8 b/tool/builddir/build.conf/run_arm_v8 index 5e69d212d..c8c10b729 100644 --- a/tool/builddir/build.conf/run_arm_v8 +++ b/tool/builddir/build.conf/run_arm_v8 @@ -4,11 +4,12 @@ QEMU_RUN_OPT := --include power_on/qemu --include log/qemu # kernel to use (hw, foc, or sel4) #KERNEL ?= hw -# board to use (rpi3, imx8q_evk) +# board to use (rpi3, imx8q_evk, virt_qemu) #BOARD ?= rpi3 # local variable for run-tool arguments that depend on the used board -BOARD_RUN_OPT(rpi3) := $(QEMU_RUN_OPT) +BOARD_RUN_OPT(rpi3) := $(QEMU_RUN_OPT) +BOARD_RUN_OPT(virt_qemu) := $(QEMU_RUN_OPT) ## ## Qemu arguments, effective when using the run tool's 'power_on/qemu' back end diff --git a/tool/run/boot_dir/hw b/tool/run/boot_dir/hw index 29f9271d4..c27579f5d 100644 --- a/tool/run/boot_dir/hw +++ b/tool/run/boot_dir/hw @@ -22,6 +22,7 @@ proc bootstrap_link_address { } { if {[have_spec "rpi"]} { return "0x00800000" } if {[have_spec "rpi3"]} { return "0x00800000" } if {[have_spec "nit6_solox"]} { return "0x88000000" } + if {[have_spec "virt_qemu"]} { return "0x40000000" } puts "unknown platform no linker address known" exit -1 @@ -229,6 +230,7 @@ proc base_src { } { if {[have_spec arndale]} { return base-hw-arndale } if {[have_spec panda]} { return base-hw-panda } if {[have_spec zynq_qemu]} { return base-hw-zynq_qemu } + if {[have_spec virt_qemu]} { return base-hw-virt_qemu } global specs diff --git a/tool/run/power_on/qemu b/tool/run/power_on/qemu index 69c619ef5..bac3d5aea 100644 --- a/tool/run/power_on/qemu +++ b/tool/run/power_on/qemu @@ -109,6 +109,17 @@ proc run_power_on { } { if {[have_spec zynq_qemu]} { append qemu_args " -M xilinx-zynq-a9 -cpu cortex-a9 -m 256 " } if {[have_spec rpi3]} { append qemu_args " -M raspi3 -m 512 " } + if {[have_spec virt_qemu]} { + append qemu_args " -M virt" + if {[have_spec arm_v8a]} { + append qemu_args ",gic_version=3 -cpu cortex-a53 -smp 4" + } + if {[have_spec arm_v7a]} { + append qemu_args " -cpu cortex-a15 -smp 2" + } + append qemu_args " -m 2048" + } + # on x86, we support booting via pxe or iso/disk image if {[have_spec x86]} { if {![regexp -- {-m} $qemu_args dummy]} {