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
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 $< > $@)
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
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
--- /dev/null
+/* 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);
+}
+++ /dev/null
-/* 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);
-}