]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/kvm/x86: Enable the Unikernel to be built as an UEFI application
authorSergiu Moga <sergiu.moga@protonmail.com>
Mon, 27 Mar 2023 10:00:30 +0000 (13:00 +0300)
committerUnikraft <monkey@unikraft.io>
Fri, 11 Aug 2023 10:47:30 +0000 (10:47 +0000)
If `CONFIG_EFI_STUB` is enabled, add to the build system the fake PE
header, the architecture generic EFI stub, and the x86 specific
post-EFI stub that applies finishing touches to the platform
initialization.

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/Linker.uk
plat/kvm/Makefile.uk
plat/kvm/x86/efi_post.c [new file with mode: 0644]
plat/kvm/x86/efi_x86.c [deleted file]

index 16791925b65495800dcc4b659c6a62dab489aa5f..35d53a60affa24ba3f2228065b04bc357ab30d75 100644 (file)
@@ -5,6 +5,9 @@ KVM_LDFLAGS-y += -Wl,--entry=_multiboot_entry
 ELF64_TO_32 = y
 else ifeq ($(CONFIG_KVM_BOOT_PROTO_LXBOOT),y)
 KVM_LDFLAGS-y += -Wl,--entry=_lxboot_entry
+else ifeq ($(CONFIG_KVM_BOOT_EFI_STUB),y)
+KVM_LDFLAGS-y += -Wl,--entry=uk_efi_entry64
+KVM_LDFLAGS-y += -Wl,-m,elf_x86_64
 endif
 else ifeq (arm64,$(CONFIG_UK_ARCH))
 KVM_LDFLAGS-y += -Wl,-m,aarch64elf
@@ -64,6 +67,9 @@ $(KVM_IMAGE): $(KVM_IMAGE).dbg
 ifeq ($(ELF64_TO_32),y)
        $(call build_elf64_to_32,$@)
 endif
+ifeq ($(CONFIG_KVM_BOOT_EFI_STUB),y)
+       $(call build_efi,$@)
+endif
 
 $(KVM_IMAGE).sym: $(KVM_DEBUG_IMAGE)
        $(call build_cmd,NM,,$@, $(NM) -n $< > $@)
index 144239531257523e289d8c57bc631d916ccd6ef6..98a4744ef94c8c33ce4d68fa0e4838758f7fbaf6 100644 (file)
@@ -64,6 +64,9 @@ LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/multiboot.c
 else ifeq ($(CONFIG_KVM_BOOT_PROTO_LXBOOT),y)
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/lxboot.S|x86
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/lxboot.c
+else ifeq ($(CONFIG_KVM_BOOT_EFI_STUB),y)
+LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/efi_entry64.S|x86
+LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/efi_post.c
 endif
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/pagetable64.S
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/traps.c
@@ -125,6 +128,9 @@ LIBKVMPLAT_SRCS-y                          += $(LIBKVMPLAT_BASE)/io.c
 LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
 LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_COMMON_BASE)/memory.c|common
 LIBKVMPLAT_SRCS-y                          += $(UK_PLAT_KVM_DEF_LDS)
+ifeq ($(CONFIG_KVM_BOOT_EFI_STUB),y)
+LIBKVMPLAT_SRCS-y                          += $(LIBKVMPLAT_BASE)/efi.c|common
+endif
 
 LIBKVMPLAT_SRCS-y               += $(UK_PLAT_COMMON_BASE)/bootinfo.c|common
 LIBKVMPLAT_SRCS-$(CONFIG_LIBFDT) += $(UK_PLAT_COMMON_BASE)/bootinfo_fdt.c|common
diff --git a/plat/kvm/x86/efi_post.c b/plat/kvm/x86/efi_post.c
new file mode 100644 (file)
index 0000000..21e57f7
--- /dev/null
@@ -0,0 +1,89 @@
+/* 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 <x86/apic_defs.h>
+#include <x86/cpu.h>
+
+/* Slave Controller Edge/Level Triggered Register */
+#define PIC2_ELCR2                                     0x4D1
+#define PIC2_ELCR2_IRQ11_ECL                           (1 << 3)
+#define PIC2_ELCR2_IRQ10_ECL                           (1 << 2)
+
+/* Initial Count Register (for Timer) */
+#define LAPIC_TMICT                                    0xFEE00380
+
+/* Master/Slave PIC Data Registers */
+#define PIC1_DATA                                      0x21
+#define PIC1_DATA_DEFAULT_MASK                         0xB8
+#define PIC2_DATA                                      0xA1
+#define PIC2_DATA_DEFAULT_MASK                         0x8E
+
+extern void lcpu_start64(void *, void *) __noreturn;
+extern void _ukplat_entry(void *, void *);
+extern void *x86_bpt_pml4;
+
+static __u8 __align(16) uk_efi_bootstack[__PAGE_SIZE];
+
+static struct {
+       void *entry_fn;
+       void *bootstack;
+} uk_efi_boot_startup_args;
+
+/* Unless UEFI CSM (now dropped from the specification) is activated, our PIC's
+ * are masked
+ */
+static inline void unmask_8259_pic(void)
+{
+       outb(PIC1_DATA, PIC1_DATA_DEFAULT_MASK);
+       outb(PIC2_DATA, PIC2_DATA_DEFAULT_MASK);
+}
+
+/* UEFI enables the LAPIC Timer to run periodic routines, usually at 10KHz */
+static inline void lapic_timer_disable(void)
+{
+       volatile __u32 *lapic_tmict = (volatile __u32 *)LAPIC_TMICT;
+       __u32 eax, edx;
+
+       /* Check if APIC is active */
+       rdmsr(APIC_MSR_BASE, &eax, &edx);
+       if (unlikely(!(eax & APIC_BASE_EN)))
+               return;
+
+       /* Zero-ing out this register disables the LAPIC Timer */
+       *lapic_tmict = 0x0;
+}
+
+/* Unless UEFI CSM (now dropped from the specification) is activated, our PIC's
+ * are masked and their interrupts mode are not configured.
+ * TODO: Until we have a proper IRQ subsystem to transparently set IRQ type when
+ * registering an IRQ, set the known PIIX/PIIX3 shared PCI IRQ's as
+ * level-triggered
+ */
+static inline void pic_8259_elcr2_level_irq10_11(void)
+{
+       outb(PIC2_ELCR2, PIC2_ELCR2_IRQ11_ECL | PIC2_ELCR2_IRQ10_ECL);
+}
+
+void __noreturn uk_efi_jmp_to_kern()
+{
+       struct ukplat_bootinfo *bi = ukplat_bootinfo_get();
+
+       if (unlikely(!bi))
+               ukplat_crash();
+
+       uk_efi_boot_startup_args.entry_fn = &_ukplat_entry;
+       uk_efi_boot_startup_args.bootstack = uk_efi_bootstack + __PAGE_SIZE;
+
+       ukplat_lcpu_disable_irq();
+       ukarch_pt_write_base((__paddr_t)&x86_bpt_pml4);
+       unmask_8259_pic();
+       lapic_timer_disable();
+       pic_8259_elcr2_level_irq10_11();
+       lcpu_start64(&uk_efi_boot_startup_args, bi);
+}
diff --git a/plat/kvm/x86/efi_x86.c b/plat/kvm/x86/efi_x86.c
deleted file mode 100644 (file)
index 21e57f7..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* 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 <x86/apic_defs.h>
-#include <x86/cpu.h>
-
-/* Slave Controller Edge/Level Triggered Register */
-#define PIC2_ELCR2                                     0x4D1
-#define PIC2_ELCR2_IRQ11_ECL                           (1 << 3)
-#define PIC2_ELCR2_IRQ10_ECL                           (1 << 2)
-
-/* Initial Count Register (for Timer) */
-#define LAPIC_TMICT                                    0xFEE00380
-
-/* Master/Slave PIC Data Registers */
-#define PIC1_DATA                                      0x21
-#define PIC1_DATA_DEFAULT_MASK                         0xB8
-#define PIC2_DATA                                      0xA1
-#define PIC2_DATA_DEFAULT_MASK                         0x8E
-
-extern void lcpu_start64(void *, void *) __noreturn;
-extern void _ukplat_entry(void *, void *);
-extern void *x86_bpt_pml4;
-
-static __u8 __align(16) uk_efi_bootstack[__PAGE_SIZE];
-
-static struct {
-       void *entry_fn;
-       void *bootstack;
-} uk_efi_boot_startup_args;
-
-/* Unless UEFI CSM (now dropped from the specification) is activated, our PIC's
- * are masked
- */
-static inline void unmask_8259_pic(void)
-{
-       outb(PIC1_DATA, PIC1_DATA_DEFAULT_MASK);
-       outb(PIC2_DATA, PIC2_DATA_DEFAULT_MASK);
-}
-
-/* UEFI enables the LAPIC Timer to run periodic routines, usually at 10KHz */
-static inline void lapic_timer_disable(void)
-{
-       volatile __u32 *lapic_tmict = (volatile __u32 *)LAPIC_TMICT;
-       __u32 eax, edx;
-
-       /* Check if APIC is active */
-       rdmsr(APIC_MSR_BASE, &eax, &edx);
-       if (unlikely(!(eax & APIC_BASE_EN)))
-               return;
-
-       /* Zero-ing out this register disables the LAPIC Timer */
-       *lapic_tmict = 0x0;
-}
-
-/* Unless UEFI CSM (now dropped from the specification) is activated, our PIC's
- * are masked and their interrupts mode are not configured.
- * TODO: Until we have a proper IRQ subsystem to transparently set IRQ type when
- * registering an IRQ, set the known PIIX/PIIX3 shared PCI IRQ's as
- * level-triggered
- */
-static inline void pic_8259_elcr2_level_irq10_11(void)
-{
-       outb(PIC2_ELCR2, PIC2_ELCR2_IRQ11_ECL | PIC2_ELCR2_IRQ10_ECL);
-}
-
-void __noreturn uk_efi_jmp_to_kern()
-{
-       struct ukplat_bootinfo *bi = ukplat_bootinfo_get();
-
-       if (unlikely(!bi))
-               ukplat_crash();
-
-       uk_efi_boot_startup_args.entry_fn = &_ukplat_entry;
-       uk_efi_boot_startup_args.bootstack = uk_efi_bootstack + __PAGE_SIZE;
-
-       ukplat_lcpu_disable_irq();
-       ukarch_pt_write_base((__paddr_t)&x86_bpt_pml4);
-       unmask_8259_pic();
-       lapic_timer_disable();
-       pic_8259_elcr2_level_irq10_11();
-       lcpu_start64(&uk_efi_boot_startup_args, bi);
-}