diff --git a/Kernel/Arch/aarch64/Dummy.cpp b/Kernel/Arch/aarch64/Dummy.cpp index feb3d84992..e08dcd713c 100644 --- a/Kernel/Arch/aarch64/Dummy.cpp +++ b/Kernel/Arch/aarch64/Dummy.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -28,38 +29,16 @@ namespace Kernel::PCI { bool g_pci_access_io_probe_failed { false }; bool g_pci_access_is_disabled_from_commandline { true }; +void initialize() +{ + dbgln("PCI: FIXME: Enable PCI for aarch64 platforms"); + g_pci_access_io_probe_failed = true; } -// x86 init - -multiboot_module_entry_t multiboot_copy_boot_modules_array[16]; -size_t multiboot_copy_boot_modules_count; - -extern "C" { -READONLY_AFTER_INIT PhysicalAddress start_of_prekernel_image; -READONLY_AFTER_INIT PhysicalAddress end_of_prekernel_image; -READONLY_AFTER_INIT size_t physical_to_virtual_offset; -// READONLY_AFTER_INIT FlatPtr kernel_mapping_base; -READONLY_AFTER_INIT FlatPtr kernel_load_base; -READONLY_AFTER_INIT PhysicalAddress boot_pml4t; -READONLY_AFTER_INIT PhysicalAddress boot_pdpt; -READONLY_AFTER_INIT PhysicalAddress boot_pd0; -READONLY_AFTER_INIT PhysicalAddress boot_pd_kernel; -READONLY_AFTER_INIT Kernel::Memory::PageTableEntry* boot_pd_kernel_pt1023; -READONLY_AFTER_INIT char const* kernel_cmdline; -READONLY_AFTER_INIT u32 multiboot_flags; -READONLY_AFTER_INIT multiboot_memory_map_t* multiboot_memory_map; -READONLY_AFTER_INIT size_t multiboot_memory_map_count; -READONLY_AFTER_INIT multiboot_module_entry_t* multiboot_modules; -READONLY_AFTER_INIT size_t multiboot_modules_count; -READONLY_AFTER_INIT PhysicalAddress multiboot_framebuffer_addr; -READONLY_AFTER_INIT u32 multiboot_framebuffer_pitch; -READONLY_AFTER_INIT u32 multiboot_framebuffer_width; -READONLY_AFTER_INIT u32 multiboot_framebuffer_height; -READONLY_AFTER_INIT u8 multiboot_framebuffer_bpp; -READONLY_AFTER_INIT u8 multiboot_framebuffer_type; } -extern "C" { -FlatPtr kernel_mapping_base; +// kprintf.cpp +void set_serial_debug_enabled(bool) +{ + dbgln("FIXME: Add support for changing state of serial debugging"); } diff --git a/Kernel/Arch/aarch64/init.cpp b/Kernel/Arch/aarch64/init.cpp deleted file mode 100644 index 15d7dc7a71..0000000000 --- a/Kernel/Arch/aarch64/init.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2021, Nico Weber - * Copyright (c) 2021, Marcin Undak - * Copyright (c) 2021, Jesse Buhagiar - * Copyright (c) 2022, the SerenityOS developers. - * Copyright (c) 2022, Filiph Sandström - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef void (*ctor_func_t)(); -extern ctor_func_t start_heap_ctors[]; -extern ctor_func_t end_heap_ctors[]; -extern ctor_func_t start_ctors[]; -extern ctor_func_t end_ctors[]; - -// FIXME: Share this with the Intel Prekernel. -extern uintptr_t __stack_chk_guard; -uintptr_t __stack_chk_guard; - -READONLY_AFTER_INIT bool g_in_early_boot; - -namespace Kernel { - -extern "C" [[noreturn]] void halt(); -extern "C" [[noreturn]] void init(); - -ALWAYS_INLINE static Processor& bootstrap_processor() -{ - alignas(Processor) static u8 bootstrap_processor_storage[sizeof(Processor)]; - return (Processor&)bootstrap_processor_storage; -} - -Atomic g_boot_console; - -VirtualConsole* tty0; -ProcessID g_init_pid { 0 }; - -static void init_stage2(void*); -void init_stage2(void*) -{ - Process::register_new(Process::current()); - - auto firmware_version = RPi::Mailbox::the().query_firmware_version(); - dmesgln("RPi: Firmware version: {}", firmware_version); - - VirtualFileSystem::initialize(); - - StorageManagement::the().initialize(kernel_command_line().root_device(), kernel_command_line().is_force_pio(), kernel_command_line().is_nvme_polling_enabled()); - if (VirtualFileSystem::the().mount_root(StorageManagement::the().root_filesystem()).is_error()) { - PANIC("VirtualFileSystem::mount_root failed"); - } - - // Switch out of early boot mode. - g_in_early_boot = false; - - LockRefPtr thread; - auto userspace_init = kernel_command_line().userspace_init(); - auto init_args = kernel_command_line().userspace_init_args(); - - auto init_or_error = Process::try_create_user_process(thread, userspace_init, UserID(0), GroupID(0), move(init_args), {}, tty0); - if (init_or_error.is_error()) - PANIC("init_stage2: Error spawning init process: {}", init_or_error.error()); - - g_init_pid = init_or_error.value()->pid(); - - thread->set_priority(THREAD_PRIORITY_HIGH); - - Process::current().sys$exit(0); - VERIFY_NOT_REACHED(); -} - -extern "C" [[noreturn]] void init() -{ - g_in_early_boot = true; - - // FIXME: Don't hardcode this - multiboot_memory_map_t mmap[] = { - { sizeof(struct multiboot_mmap_entry) - sizeof(u32), - (u64)0x0, - (u64)0x3F000000, - MULTIBOOT_MEMORY_AVAILABLE } - }; - - multiboot_memory_map = mmap; - multiboot_memory_map_count = 1; - - dbgln("Welcome to Serenity OS!"); - dbgln("Imagine this being your ideal operating system."); - dbgln("Observed deviations from that ideal are shortcomings of your imagination."); - dbgln(); - - CommandLine::early_initialize(""); - - new (&bootstrap_processor()) Processor(); - bootstrap_processor().early_initialize(0); - - // We call the constructors of kmalloc.cpp separately, because other constructors in the Kernel - // might rely on being able to call new/kmalloc in the constructor. We do have to run the - // kmalloc constructors, because kmalloc_init relies on that. - for (ctor_func_t* ctor = start_heap_ctors; ctor < end_heap_ctors; ctor++) - (*ctor)(); - kmalloc_init(); - - bootstrap_processor().initialize(0); - - load_kernel_symbol_table(); - - CommandLine::initialize(); - - dmesgln("Starting SerenityOS..."); - - Memory::MemoryManager::initialize(0); - DeviceManagement::initialize(); - SysFSComponentRegistry::initialize(); - DeviceManagement::the().attach_null_device(*NullDevice::must_initialize()); - - // Invoke all static global constructors in the kernel. - // Note that we want to do this as early as possible. - for (ctor_func_t* ctor = start_ctors; ctor < end_ctors; ctor++) - (*ctor)(); - - RPi::Framebuffer::initialize(); - - auto& framebuffer = RPi::Framebuffer::the(); - if (framebuffer.initialized()) { - g_boot_console = &try_make_lock_ref_counted(PhysicalAddress((PhysicalPtr)framebuffer.gpu_buffer()), framebuffer.width(), framebuffer.height(), framebuffer.pitch()).value().leak_ref(); - framebuffer.draw_logo(static_cast(g_boot_console.load())->unsafe_framebuffer_data()); - } - - initialize_interrupts(); - InterruptManagement::initialize(); - Processor::enable_interrupts(); - - // Note: We have to disable interrupts otherwise Scheduler::timer_tick might be called before the scheduler is started. - Processor::disable_interrupts(); - TimeManagement::initialize(0); - - Process::initialize(); - Scheduler::initialize(); - - { - LockRefPtr init_stage2_thread; - (void)Process::create_kernel_process(init_stage2_thread, KString::must_create("init_stage2"sv), init_stage2, nullptr, THREAD_AFFINITY_DEFAULT, Process::RegisterProcess::No); - // We need to make sure we drop the reference for init_stage2_thread - // before calling into Scheduler::start, otherwise we will have a - // dangling Thread that never gets cleaned up - } - - Scheduler::start(); - - VERIFY_NOT_REACHED(); -} - -} diff --git a/Kernel/Arch/x86_64/init.cpp b/Kernel/Arch/init.cpp similarity index 90% rename from Kernel/Arch/x86_64/init.cpp rename to Kernel/Arch/init.cpp index 4188128d9e..4eb0b02048 100644 --- a/Kernel/Arch/x86_64/init.cpp +++ b/Kernel/Arch/init.cpp @@ -7,9 +7,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -59,6 +56,15 @@ #include #include +#if ARCH(X86_64) +# include +# include +# include +#elif ARCH(AARCH64) +# include +# include +#endif + // Defined in the linker script typedef void (*ctor_func_t)(); extern ctor_func_t start_heap_ctors[]; @@ -69,10 +75,12 @@ extern ctor_func_t end_ctors[]; extern uintptr_t __stack_chk_guard; READONLY_AFTER_INIT uintptr_t __stack_chk_guard __attribute__((used)); +#if ARCH(X86_64) extern "C" u8 start_of_safemem_text[]; extern "C" u8 end_of_safemem_text[]; extern "C" u8 start_of_safemem_atomic_text[]; extern "C" u8 end_of_safemem_atomic_text[]; +#endif extern "C" u8 end_of_kernel_image[]; @@ -141,10 +149,11 @@ READONLY_AFTER_INIT u8 multiboot_framebuffer_type; Atomic g_boot_console; -extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) +extern "C" [[noreturn]] UNMAP_AFTER_INIT void init([[maybe_unused]] BootInfo const& boot_info) { g_in_early_boot = true; +#if ARCH(X86_64) start_of_prekernel_image = PhysicalAddress { boot_info.start_of_prekernel_image }; end_of_prekernel_image = PhysicalAddress { boot_info.end_of_prekernel_image }; physical_to_virtual_offset = boot_info.physical_to_virtual_offset; @@ -169,6 +178,22 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) multiboot_framebuffer_height = boot_info.multiboot_framebuffer_height; multiboot_framebuffer_bpp = boot_info.multiboot_framebuffer_bpp; multiboot_framebuffer_type = boot_info.multiboot_framebuffer_type; +#elif ARCH(AARCH64) + // FIXME: For the aarch64 platforms, we should get the information by parsing a device tree instead of using multiboot. + multiboot_memory_map_t mmap[] = { + { sizeof(struct multiboot_mmap_entry) - sizeof(u32), + (u64)0x0, + (u64)0x3F000000, + MULTIBOOT_MEMORY_AVAILABLE } + }; + multiboot_memory_map = mmap; + multiboot_memory_map_count = 1; + + multiboot_module_entry_t modules[] = {}; + multiboot_modules = modules; + multiboot_modules_count = 0; + kernel_cmdline = ""; +#endif setup_serial_debug(); @@ -193,12 +218,22 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) CommandLine::initialize(); Memory::MemoryManager::initialize(0); +#if ARCH(AARCH64) + auto firmware_version = RPi::Mailbox::the().query_firmware_version(); + dmesgln("RPi: Firmware version: {}", firmware_version); + + RPi::Framebuffer::initialize(); +#endif + // NOTE: If the bootloader provided a framebuffer, then set up an initial console. // If the bootloader didn't provide a framebuffer, then set up an initial text console. // We do so we can see the output on the screen as soon as possible. if (!kernel_command_line().is_early_boot_console_disabled()) { if (!multiboot_framebuffer_addr.is_null() && multiboot_framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_RGB) { g_boot_console = &try_make_lock_ref_counted(multiboot_framebuffer_addr, multiboot_framebuffer_width, multiboot_framebuffer_height, multiboot_framebuffer_pitch).value().leak_ref(); +#if ARCH(AARCH64) + RPi::Framebuffer::the().draw_logo(static_cast(g_boot_console.load())->unsafe_framebuffer_data()); +#endif } else { g_boot_console = &Graphics::VGATextModeConsole::initialize().leak_ref(); } @@ -213,9 +248,11 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) MM.unmap_prekernel(); +#if ARCH(X86_64) // Ensure that the safemem sections are not empty. This could happen if the linker accidentally discards the sections. VERIFY(+start_of_safemem_text != +end_of_safemem_text); VERIFY(+start_of_safemem_atomic_text != +end_of_safemem_atomic_text); +#endif // Invoke all static global constructors in the kernel. // Note that we want to do this as early as possible. @@ -234,12 +271,15 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) Scheduler::initialize(); +#if ARCH(X86_64) + // FIXME: Add an abstraction for the smp related functions, instead of using ifdefs in this file. if (APIC::initialized() && APIC::the().enabled_processor_count() > 1) { // We must set up the AP boot environment before switching to a kernel process, // as pages below address USER_RANGE_BASE are only accessible through the kernel // page directory. APIC::the().setup_ap_boot_environment(); } +#endif { LockRefPtr init_stage2_thread; @@ -253,6 +293,7 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init(BootInfo const& boot_info) VERIFY_NOT_REACHED(); } +#if ARCH(X86_64) // // This is where C++ execution begins for APs, after boot.S transfers control here. // @@ -284,6 +325,7 @@ extern "C" UNMAP_AFTER_INIT void init_finished(u32 cpu) TimeManagement::initialize(cpu); } } +#endif void init_stage2(void*) { @@ -294,6 +336,7 @@ void init_stage2(void*) WorkQueue::initialize(); +#if ARCH(X86_64) if (kernel_command_line().is_smp_enabled() && APIC::initialized() && APIC::the().enabled_processor_count() > 1) { // We can't start the APs until we have a scheduler up and running. // We need to be able to process ICI messages, otherwise another @@ -301,6 +344,7 @@ void init_stage2(void*) // exhausted APIC::the().boot_aps(); } +#endif // Initialize the PCI Bus as early as possible, for early boot (PCI based) serial logging PCI::initialize(); @@ -310,13 +354,17 @@ void init_stage2(void*) VirtualFileSystem::initialize(); +#if ARCH(X86_64) if (!is_serial_debug_enabled()) (void)SerialDevice::must_create(0).leak_ref(); (void)SerialDevice::must_create(1).leak_ref(); (void)SerialDevice::must_create(2).leak_ref(); (void)SerialDevice::must_create(3).leak_ref(); +#endif +#if ARCH(X86_64) VMWareBackdoor::the(); // don't wait until first mouse packet +#endif MUST(HIDManagement::initialize()); GraphicsManagement::the().initialize(); diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index a94d124afa..205b8c157f 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -17,6 +17,7 @@ set(KERNEL_HEAP_SOURCES set(KERNEL_SOURCES AddressSanitizer.cpp + Arch/init.cpp Arch/PageFault.cpp Arch/DeferredCallPool.cpp Bus/PCI/Controller/HostController.cpp @@ -361,8 +362,6 @@ set(KERNEL_SOURCES if ("${SERENITY_ARCH}" STREQUAL "x86_64") set(KERNEL_SOURCES ${KERNEL_SOURCES} - Arch/x86_64/init.cpp - Arch/Processor.cpp Arch/x86_64/CMOS.cpp @@ -462,7 +461,6 @@ elseif("${SERENITY_ARCH}" STREQUAL "aarch64") Arch/aarch64/CPUID.cpp Arch/aarch64/CurrentTime.cpp Arch/aarch64/Dummy.cpp - Arch/aarch64/init.cpp Arch/aarch64/InterruptManagement.cpp Arch/aarch64/Interrupts.cpp Arch/aarch64/kprintf.cpp