From c7b0f0a4d4eca2f0152c750373aabfad787fdf13 Mon Sep 17 00:00:00 2001 From: IkerGalardi Date: Thu, 26 Feb 2026 11:35:55 +0100 Subject: [PATCH 1/4] Add qemu_virt_aarch64_kvm platform This board differs from the standard qemu_virt_aarch64 board in that the entry point is in EL2 instead of EL1. This is necessary due to the lack of nested virtualization support on the KVM subsystem. Signed-off-by: IkerGalardi --- build_sdk.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/build_sdk.py b/build_sdk.py index cf53d5ae3..153108c63 100644 --- a/build_sdk.py +++ b/build_sdk.py @@ -292,6 +292,21 @@ class KernelPath: "KernelArmExportPTMRUser": True, } | DEFAULT_KERNEL_OPTIONS_AARCH64, ), + BoardInfo( + name="qemu_virt_aarch64_kvm", + arch=KernelArch.AARCH64, + gcc_cpu="cortex-a53", + loader_link_address=0x70000000, + smp_cores=4, + kernel_options={ + "KernelPlatform": "qemu-arm-virt", + "KernelArmHypervisorSupport": False, + "QEMU_MEMORY": "2048", + # There is no peripheral timer, so we use the ARM + # architectural timer + "KernelArmExportPTMRUser": True, + } | DEFAULT_KERNEL_OPTIONS_AARCH64, + ), BoardInfo( name="qemu_virt_riscv64", arch=KernelArch.RISCV64, From 7d50887c78aefcb1dda4ef454297b88230273d21 Mon Sep 17 00:00:00 2001 From: IkerGalardi Date: Thu, 26 Feb 2026 12:24:16 +0100 Subject: [PATCH 2/4] Correctly default intialize supported boards Previously the defaults where applied ALWAYS, meaning that if some board tried to specialize a kernel building parameter that the default configuration did, it would get overwriten by the default configuration. This patch applies the specialization to the default configuration instead of doing it the other way around. Signed-off-by: IkerGalardi --- build_sdk.py | 104 +++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/build_sdk.py b/build_sdk.py index 153108c63..a1cdfbe92 100644 --- a/build_sdk.py +++ b/build_sdk.py @@ -180,9 +180,9 @@ class KernelPath: gcc_cpu="cortex-a35", loader_link_address=0x90000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "tqma8xqp1gb", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="zcu102", @@ -190,10 +190,10 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x40000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "zynqmp", "KernelARMPlatform": "zcu102", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="maaxboard", @@ -201,9 +201,9 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x50000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "maaxboard", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="imx8mm_evk", @@ -211,9 +211,9 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x41000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "imx8mm-evk", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="imx8mp_evk", @@ -221,9 +221,9 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x41000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "imx8mp-evk", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="imx8mq_evk", @@ -231,9 +231,9 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x41000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "imx8mq-evk", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="imx8mp_iotgate", @@ -241,11 +241,11 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x50000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "imx8mp-evk", "KernelCustomDTS": Path("custom_dts/iot-gate.dts"), "KernelCustomDTSOverlay": KernelPath(path="src/plat/imx8m-evk/overlay-imx8mp-evk.dts"), - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="odroidc2", @@ -253,9 +253,9 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x20000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "odroidc2", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="odroidc4", @@ -263,9 +263,9 @@ class KernelPath: gcc_cpu="cortex-a55", loader_link_address=0x20000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "odroidc4", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="ultra96v2", @@ -273,10 +273,10 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x40000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "zynqmp", "KernelARMPlatform": "ultra96v2", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="qemu_virt_aarch64", @@ -284,13 +284,13 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x70000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "qemu-arm-virt", "QEMU_MEMORY": "2048", # There is no peripheral timer, so we use the ARM # architectural timer "KernelArmExportPTMRUser": True, - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="qemu_virt_aarch64_kvm", @@ -298,14 +298,14 @@ class KernelPath: gcc_cpu="cortex-a53", loader_link_address=0x70000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "qemu-arm-virt", "KernelArmHypervisorSupport": False, "QEMU_MEMORY": "2048", # There is no peripheral timer, so we use the ARM # architectural timer "KernelArmExportPTMRUser": True, - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="qemu_virt_riscv64", @@ -313,10 +313,10 @@ class KernelPath: gcc_cpu=None, loader_link_address=0x90000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_RISCV64 | { "KernelPlatform": "qemu-riscv-virt", "QEMU_MEMORY": "2048", - } | DEFAULT_KERNEL_OPTIONS_RISCV64, + }, ), BoardInfo( name="rpi4b_1gb", @@ -324,10 +324,10 @@ class KernelPath: gcc_cpu="cortex-a72", loader_link_address=0x10000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "bcm2711", "RPI4_MEMORY": 1024, - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="rpi4b_2gb", @@ -335,10 +335,10 @@ class KernelPath: gcc_cpu="cortex-a72", loader_link_address=0x10000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "bcm2711", "RPI4_MEMORY": 2048, - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="rpi4b_4gb", @@ -346,10 +346,10 @@ class KernelPath: gcc_cpu="cortex-a72", loader_link_address=0x10000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "bcm2711", "RPI4_MEMORY": 4096, - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="rpi4b_8gb", @@ -357,10 +357,10 @@ class KernelPath: gcc_cpu="cortex-a72", loader_link_address=0x10000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "bcm2711", "RPI4_MEMORY": 8192, - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="rockpro64", @@ -370,18 +370,18 @@ class KernelPath: # ROCKPRO64 has 4 Cortex-A53 cores and 2 Cortex-A72 cores, # we always run on the Cortex-A53s. smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "rockpro64", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="rock3b", arch=KernelArch.AARCH64, gcc_cpu="cortex-a55", loader_link_address=0x30000000, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_AARCH64 | { "KernelPlatform": "rk3568", - } | DEFAULT_KERNEL_OPTIONS_AARCH64, + }, ), BoardInfo( name="hifive_p550", @@ -389,9 +389,9 @@ class KernelPath: gcc_cpu=None, loader_link_address=0x90000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_RISCV64 | { "KernelPlatform": "hifive-p550", - } | DEFAULT_KERNEL_OPTIONS_RISCV64, + }, ), BoardInfo( name="star64", @@ -399,36 +399,36 @@ class KernelPath: gcc_cpu=None, loader_link_address=0x60000000, smp_cores=4, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_RISCV64 | { "KernelPlatform": "star64", - } | DEFAULT_KERNEL_OPTIONS_RISCV64, + }, ), BoardInfo( name="ariane", arch=KernelArch.RISCV64, gcc_cpu=None, loader_link_address=0x90000000, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_RISCV64 | { "KernelPlatform": "ariane", - } | DEFAULT_KERNEL_OPTIONS_RISCV64, + }, ), BoardInfo( name="cheshire", arch=KernelArch.RISCV64, gcc_cpu=None, loader_link_address=0x90000000, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_RISCV64 | { "KernelPlatform": "cheshire", - } | DEFAULT_KERNEL_OPTIONS_RISCV64, + }, ), BoardInfo( name="serengeti", arch=KernelArch.RISCV64, gcc_cpu=None, loader_link_address=0x90000000, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_RISCV64 | { "KernelPlatform": "cheshire", - } | DEFAULT_KERNEL_OPTIONS_RISCV64, + }, ), BoardInfo( name="x86_64_generic", @@ -436,10 +436,10 @@ class KernelPath: gcc_cpu="generic", loader_link_address=None, smp_cores=DEFAULT_X86_NUM_CPUS, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_X86_64 | { "KernelSupportPCID": False, "KernelVTX": False, - } | DEFAULT_KERNEL_OPTIONS_X86_64, + }, ), BoardInfo( name="x86_64_generic_vtx", @@ -447,11 +447,11 @@ class KernelPath: gcc_cpu="generic", loader_link_address=None, smp_cores=DEFAULT_X86_NUM_CPUS, - kernel_options={ + kernel_options=DEFAULT_KERNEL_OPTIONS_X86_64 | { "KernelSupportPCID": False, "KernelVTX": True, "KernelX86_64VTX64BitGuests": True, - } | DEFAULT_KERNEL_OPTIONS_X86_64, + }, ), ) From 2f2bf553224c7f5dd181fd45952168f3fd000c3e Mon Sep 17 00:00:00 2001 From: IkerGalardi Date: Thu, 26 Feb 2026 15:50:39 +0100 Subject: [PATCH 3/4] tool: remove arm hypervisor mode requirement Signed-off-by: IkerGalardi --- tool/microkit/src/main.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tool/microkit/src/main.rs b/tool/microkit/src/main.rs index 5b9f0a220..a2a9d14e4 100644 --- a/tool/microkit/src/main.rs +++ b/tool/microkit/src/main.rs @@ -401,13 +401,6 @@ fn main() -> Result<(), String> { std::process::exit(1); } - if let Arch::Aarch64 = kernel_config.arch { - assert!( - kernel_config.hypervisor, - "Microkit tool expects a kernel with hypervisor mode enabled on AArch64." - ); - } - assert!( kernel_config.word_size == 64, "Microkit tool has various assumptions about the word size being 64-bits." From 4ca50bd7859fed9e9cac1d9a0f6144e6d56c74d1 Mon Sep 17 00:00:00 2001 From: IkerGalardi Date: Mon, 2 Mar 2026 16:38:37 +0100 Subject: [PATCH 4/4] loader: only configure interrupt groups on hypervisor mode EL1 software can not access interrupt group registers on the GIC distributor. Signed-off-by: IkerGalardi --- loader/src/aarch64/init.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/loader/src/aarch64/init.c b/loader/src/aarch64/init.c index bc09276c6..9412e6f4c 100644 --- a/loader/src/aarch64/init.c +++ b/loader/src/aarch64/init.c @@ -25,6 +25,19 @@ #if defined(CONFIG_PLAT_ZYNQMP_ZCU102) || defined(CONFIG_PLAT_ZYNQMP_ULTRA96V2) || defined(CONFIG_PLAT_QEMU_ARM_VIRT) static void configure_gicv2(void) { + /* For any interrupts to go through the interrupt priority mask + * must be set appropriately. Only interrupts with priorities less + * than this mask will interrupt the CPU. + * + * seL4 (effectively) sets interrupts to priority 0x80, so it is + * important to make sure this is greater than 0x80. + */ + *((volatile uint32_t *)(GICC_BASE + 0x4)) = 0xf0; + + if (current_el() == EL1) { + return; + } + /* The ZCU102 start in EL3, and then we drop to EL1(NS). * * The GICv2 supports security extensions (as does the CPU). @@ -55,15 +68,6 @@ static void configure_gicv2(void) for (uint32_t i = 0; i <= it_lines_number; i++) { *((volatile uint32_t *)(GICD_BASE + 0x80 + (i * 4))) = 0xFFFFFFFF; } - - /* For any interrupts to go through the interrupt priority mask - * must be set appropriately. Only interrupts with priorities less - * than this mask will interrupt the CPU. - * - * seL4 (effectively) sets interrupts to priority 0x80, so it is - * important to make sure this is greater than 0x80. - */ - *((volatile uint32_t *)(GICC_BASE + 0x4)) = 0xf0; } #endif