From e4df77904867c6d38f896eeb9e2b8413a32be510 Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Sun, 9 Aug 2026 21:51:16 +0200 Subject: [PATCH] entry: enable SYSCALL on the UEFI hand-off path The 32-bit entry sets EFER.SCE on its way into long mode. entry64uefi skips that bootstrap entirely, because firmware has already done the mode switch -- and with it skipped the one bit in there that is not about paging. UEFI has no reason to set SCE and does not, so the kernel came up with SYSCALL disabled. Nothing noticed until the UEFI path first got far enough to run a user program, at which point the first sysretq raised #UD: "unexpected trap 6 ... rip " in pid 1, at zero ticks. Read-modify-write, because LME and LMA are already set by firmware and have to stay. Co-Authored-By: Claude Opus 5 --- kernel/arch/x86_64/entry.S | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/kernel/arch/x86_64/entry.S b/kernel/arch/x86_64/entry.S index 9c4757b..64eabc3 100644 --- a/kernel/arch/x86_64/entry.S +++ b/kernel/arch/x86_64/entry.S @@ -163,6 +163,23 @@ gdt64_end: */ .global entry64uefi entry64uefi: + /* Enable SYSCALL/SYSRET. + * + * The 32-bit entry above sets EFER.SCE on its way into long mode. This path + * skips all of that, because firmware has already done the mode switch -- and + * with it skips the one bit that is not about paging. UEFI has no reason to + * set SCE and does not, so the kernel came up with SYSCALL disabled and the + * first sysretq back to user space raised #UD: "unexpected trap 6 ... rip + * " in pid 1, at zero ticks. It stayed hidden until this + * path first got far enough to run a user program. + * + * Read-modify-write: LME and LMA are already set by firmware and must stay. + */ + mov $MSR_EFER, %ecx + rdmsr + bts $0, %eax + wrmsr + lgdt (gdtr64 - mboot_header + mboot_load_addr) movq $(entry64low - mboot_header + mboot_load_addr), %rax pushq $8 /* the 64-bit code selector in gdt64 */