From 5100dabb9682bb021bb85beeae1c0fa23a5a6db5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 23 Feb 2021 19:25:58 +0100 Subject: [PATCH] Kernel: Copy the kernel command line to a good location at boot When building the kernel with -O2, we somehow ended up with the kernel command line outside of the lower 8MB of physical memory. Since we don't map that area in our initial page table setup, we would triple fault when trying to parse the command line. This patch sidesteps the issue by copying the (first 4KB of) the kernel command line to a buffer in a known safe location at boot. --- Kernel/Arch/i386/Boot/boot.S | 17 +++++++++++++++++ Kernel/init.cpp | 8 +++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Kernel/Arch/i386/Boot/boot.S b/Kernel/Arch/i386/Boot/boot.S index 717b3fd00a..e068815a60 100644 --- a/Kernel/Arch/i386/Boot/boot.S +++ b/Kernel/Arch/i386/Boot/boot.S @@ -31,6 +31,10 @@ stack_bottom: .skip 32768 stack_top: +.global kernel_cmdline +kernel_cmdline: +.skip 4096 + .section .page_tables, "aw", @nobits .align 4096 .global boot_pdpt @@ -93,6 +97,19 @@ start: cli cld + /* We don't know where the bootloader might have put the command line. + * It might be at an inconvenient location that we're not about to map, + * so let's just copy it to a convenient location while we have the whole + * memory space identity-mapped anyway. :^) + */ + + movl %ebx, %esi + addl $16, %esi + movl (%esi), %esi + movl $1024, %ecx + movl $(kernel_cmdline - 0xc0000000), %edi + rep movsl + /* clear pdpt */ movl $(boot_pdpt - 0xc0000000), %edi movl $1024, %ecx diff --git a/Kernel/init.cpp b/Kernel/init.cpp index fff7ec64b7..da56ae12db 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -91,6 +91,8 @@ extern "C" u8* end_of_safemem_atomic_text; multiboot_module_entry_t multiboot_copy_boot_modules_array[16]; size_t multiboot_copy_boot_modules_count; +extern "C" const char kernel_cmdline[4096]; + namespace Kernel { [[noreturn]] static void init_stage2(void*); @@ -122,7 +124,7 @@ extern "C" UNMAP_AFTER_INIT [[noreturn]] void init() // We need to copy the command line before kmalloc is initialized, // as it may overwrite parts of multiboot! - CommandLine::early_initialize(reinterpret_cast(low_physical_to_virtual(multiboot_info_ptr->cmdline))); + CommandLine::early_initialize(kernel_cmdline); memcpy(multiboot_copy_boot_modules_array, (u8*)low_physical_to_virtual(multiboot_info_ptr->mods_addr), multiboot_info_ptr->mods_count * sizeof(multiboot_module_entry_t)); multiboot_copy_boot_modules_count = multiboot_info_ptr->mods_count; s_bsp_processor.early_initialize(0); @@ -328,9 +330,9 @@ UNMAP_AFTER_INIT void setup_serial_debug() // serial_debug will output all the klog() and dbgln() data to COM1 at // 8-N-1 57600 baud. this is particularly useful for debugging the boot // process on live hardware. - u32 cmdline = low_physical_to_virtual(multiboot_info_ptr->cmdline); - if (cmdline && StringView(reinterpret_cast(cmdline)).contains("serial_debug")) + if (StringView(kernel_cmdline).contains("serial_debug")) { set_serial_debug(true); + } } extern "C" {