]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/kvm/arm: Add architecture specific post-EFI stub
authorSergiu Moga <sergiu.moga@protonmail.com>
Mon, 27 Mar 2023 09:51:22 +0000 (12:51 +0300)
committerUnikraft <monkey@unikraft.io>
Fri, 11 Aug 2023 10:47:30 +0000 (10:47 +0000)
Implement a stub that comes after the architecture generic EFI stub
calls the routine that exits `Boot Services`.

This is supposed to finish the architecture specific setupin order
to be able to have a Unikraft valid initial environment state before
`_libkvmplat_start` is execited.

Thus, the interrupt flags are masked, the data cache is invalidated
in the range of this image's instance and then default, warm reset
values are placed into the system registers that EFI would have
otherwise left modified.

Signed-off-by: Sergiu Moga <sergiu.moga@protonmail.com>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #909

plat/kvm/arm/efi_arm.c [new file with mode: 0644]

diff --git a/plat/kvm/arm/efi_arm.c b/plat/kvm/arm/efi_arm.c
new file mode 100644 (file)
index 0000000..e28beba
--- /dev/null
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/* Copyright (c) 2023, Unikraft GmbH and The Unikraft Authors.
+ * Licensed under the BSD-3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ */
+#include <kvm/efi.h>
+#include <uk/arch/paging.h>
+#include <uk/plat/common/bootinfo.h>
+#include <uk/plat/lcpu.h>
+#include <uk/plat/common/sections.h>
+
+extern void clean_and_invalidate_dcache_range(unsigned long, unsigned long);
+extern void _ukplat_entry(void *) __noreturn;
+extern __paddr_t vector_table;
+extern void start_mmu(void);
+
+static __u8 __align(16) uk_efi_bootstack[__PAGE_SIZE];
+
+/* We cannot set the system register directly */
+#define uk_efi_set_sp_el1(sp)                                          \
+       __asm__ __volatile__("mov sp, %0\n" ::"r" (sp))
+
+void __noreturn uk_efi_jmp_to_kern(void)
+{
+       ukplat_lcpu_disable_irq();
+
+       /* Invalidate the image from the data cache */
+       clean_and_invalidate_dcache_range(__BASE_ADDR, __END);
+
+       SYSREG_WRITE64(sctlr_el1, SCTLR_SET_BITS);
+       SYSREG_WRITE64(contextidr_el1, 0);
+       SYSREG_WRITE64(VBAR_EL1, &vector_table);
+       SYSREG_WRITE64(spsr_el1, 0);
+       SYSREG_WRITE64(elr_el1, 0);
+       SYSREG_WRITE64(cntv_cval_el0, 0);
+       /* EDKII's backtrace and dump register code is written in C, so
+        * it requires a stack. If SP_EL1 is corrupted before an exception
+        * is taken, they rely on SP_EL0 which is set to a backup stack.
+        * Thus, reset it to 0 to avoid any back reference to firmware.
+        */
+       SYSREG_WRITE64(sp_el0, 0);
+       SYSREG_WRITE64(tpidr_el0, 0);
+
+       start_mmu();
+       uk_efi_set_sp_el1(uk_efi_bootstack + __PAGE_SIZE);
+       _ukplat_entry(ukplat_bootinfo_get());
+}