1255736Sdavidch/* 2265411Sdavidcs * Copyright 2018, J��r��me Duval, jerome.duval@gmail.com. 3255736Sdavidch * Copyright 2002-2020, Axel D��rfler, axeld@pinc-software.de. 4255736Sdavidch * Distributed under the terms of the MIT License. 5255736Sdavidch * 6255736Sdavidch * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7255736Sdavidch * Distributed under the terms of the NewOS License. 8255736Sdavidch */ 9255736Sdavidch 10255736Sdavidch 11255736Sdavidch/*! This is main - initializes the kernel and launches the launch_daemon */ 12255736Sdavidch 13255736Sdavidch 14255736Sdavidch#include <string.h> 15255736Sdavidch 16255736Sdavidch#include <FindDirectory.h> 17255736Sdavidch#include <OS.h> 18255736Sdavidch 19255736Sdavidch#include <arch/platform.h> 20255736Sdavidch#include <boot_device.h> 21255736Sdavidch#include <boot_item.h> 22255736Sdavidch#include <boot_splash.h> 23255736Sdavidch#include <commpage.h> 24255736Sdavidch#ifdef _COMPAT_MODE 25255736Sdavidch# include <commpage_compat.h> 26255736Sdavidch#endif 27255736Sdavidch#include <condition_variable.h> 28255736Sdavidch#include <cpu.h> 29255736Sdavidch#include <debug.h> 30255736Sdavidch#include <DPC.h> 31255736Sdavidch#include <elf.h> 32255736Sdavidch#include <find_directory_private.h> 33255736Sdavidch#include <fs/devfs.h> 34255736Sdavidch#include <fs/KPath.h> 35255736Sdavidch#include <int.h> 36255736Sdavidch#include <kdevice_manager.h> 37255736Sdavidch#include <kdriver_settings.h> 38255736Sdavidch#include <kernel_daemon.h> 39255736Sdavidch#include <kmodule.h> 40255736Sdavidch#include <kscheduler.h> 41255736Sdavidch#include <ksyscalls.h> 42255736Sdavidch#include <ksystem_info.h> 43255736Sdavidch#include <lock.h> 44255736Sdavidch#include <low_resource_manager.h> 45255736Sdavidch#include <messaging.h> 46255736Sdavidch#include <Notifications.h> 47255736Sdavidch#include <port.h> 48255736Sdavidch#include <posix/realtime_sem.h> 49255736Sdavidch#include <posix/xsi_message_queue.h> 50255736Sdavidch#include <posix/xsi_semaphore.h> 51255736Sdavidch#include <real_time_clock.h> 52255736Sdavidch#include <sem.h> 53255736Sdavidch#include <smp.h> 54281855Srodrigc#include <stack_protector.h> 55255736Sdavidch#include <system_profiler.h> 56255736Sdavidch#include <team.h> 57255736Sdavidch#include <timer.h> 58255736Sdavidch#include <user_debugger.h> 59255736Sdavidch#include <user_mutex.h> 60255736Sdavidch#include <vfs.h> 61266979Smarcel#include <vm/vm.h> 62255736Sdavidch#include <boot/kernel_args.h> 63255736Sdavidch 64255736Sdavidch#include "vm/VMAnonymousCache.h" 65255736Sdavidch 66255736Sdavidch 67255736Sdavidch//#define TRACE_BOOT 68255736Sdavidch#ifdef TRACE_BOOT 69255736Sdavidch# define TRACE(x...) dprintf("INIT: " x) 70255736Sdavidch#else 71255736Sdavidch# define TRACE(x...) ; 72255736Sdavidch#endif 73255736Sdavidch 74255736Sdavidch 75255736Sdavidchvoid *__dso_handle; 76255736Sdavidch 77255736Sdavidchbool gKernelStartup = true; 78255736Sdavidchbool gKernelShutdown = false; 79255736Sdavidch 80255736Sdavidchstatic kernel_args sKernelArgs; 81255736Sdavidchstatic uint32 sCpuRendezvous; 82255736Sdavidchstatic uint32 sCpuRendezvous2; 83255736Sdavidchstatic uint32 sCpuRendezvous3; 84255736Sdavidch 85255736Sdavidchstatic int32 main2(void *); 86255736Sdavidch 87255736Sdavidch 88255736Sdavidchstatic void 89255736Sdavidchnon_boot_cpu_init(void* args, int currentCPU) 90255736Sdavidch{ 91255736Sdavidch kernel_args* kernelArgs = (kernel_args*)args; 92255736Sdavidch if (currentCPU != 0) 93255736Sdavidch cpu_init_percpu(kernelArgs, currentCPU); 94255736Sdavidch} 95255736Sdavidch 96255736Sdavidch 97255736Sdavidchextern "C" int 98255736Sdavidch_start(kernel_args *bootKernelArgs, int currentCPU) 99255736Sdavidch{ 100255736Sdavidch if (bootKernelArgs->version == CURRENT_KERNEL_ARGS_VERSION 101255736Sdavidch && bootKernelArgs->kernel_args_size == kernel_args_size_v1) { 102255736Sdavidch sKernelArgs.ucode_data = NULL; 103255736Sdavidch sKernelArgs.ucode_data_size = 0; 104255736Sdavidch } else if (bootKernelArgs->kernel_args_size != sizeof(kernel_args) 105255736Sdavidch || bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) { 106255736Sdavidch // This is something we cannot handle right now - release kernels 107255736Sdavidch // should always be able to handle the kernel_args of earlier 108255736Sdavidch // released kernels. 109255736Sdavidch debug_early_boot_message("Version mismatch between boot loader and " 110255736Sdavidch "kernel!\n"); 111255736Sdavidch return -1; 112255736Sdavidch } 113255736Sdavidch 114255736Sdavidch smp_set_num_cpus(bootKernelArgs->num_cpus); 115255736Sdavidch 116255736Sdavidch // wait for all the cpus to get here 117255736Sdavidch smp_cpu_rendezvous(&sCpuRendezvous); 118255736Sdavidch 119255736Sdavidch // the passed in kernel args are in a non-allocated range of memory 120255736Sdavidch if (currentCPU == 0) 121255736Sdavidch memcpy(&sKernelArgs, bootKernelArgs, bootKernelArgs->kernel_args_size); 122255736Sdavidch 123255736Sdavidch smp_cpu_rendezvous(&sCpuRendezvous2); 124255736Sdavidch 125255736Sdavidch // do any pre-booting cpu config 126255736Sdavidch cpu_preboot_init_percpu(&sKernelArgs, currentCPU); 127255736Sdavidch thread_preboot_init_percpu(&sKernelArgs, currentCPU); 128255736Sdavidch 129255736Sdavidch // if we're not a boot cpu, spin here until someone wakes us up 130255736Sdavidch if (smp_trap_non_boot_cpus(currentCPU, &sCpuRendezvous3)) { 131255736Sdavidch // init platform 132255736Sdavidch arch_platform_init(&sKernelArgs); 133255736Sdavidch 134255736Sdavidch // setup debug output 135255736Sdavidch debug_init(&sKernelArgs); 136255736Sdavidch set_dprintf_enabled(true); 137255736Sdavidch dprintf("Welcome to kernel debugger output!\n"); 138255736Sdavidch dprintf("Haiku revision: %s, debug level: %d\n", get_haiku_revision(), 139255736Sdavidch KDEBUG_LEVEL); 140255736Sdavidch 141255736Sdavidch // init modules 142255736Sdavidch TRACE("init CPU\n"); 143255736Sdavidch cpu_init(&sKernelArgs); 144255736Sdavidch cpu_init_percpu(&sKernelArgs, currentCPU); 145255736Sdavidch TRACE("init interrupts\n"); 146255736Sdavidch int_init(&sKernelArgs); 147255736Sdavidch 148255736Sdavidch TRACE("init VM\n"); 149255736Sdavidch vm_init(&sKernelArgs); 150255736Sdavidch // Before vm_init_post_sem() is called, we have to make sure that 151255736Sdavidch // the boot loader allocated region is not used anymore 152255736Sdavidch boot_item_init(); 153255736Sdavidch debug_init_post_vm(&sKernelArgs); 154255736Sdavidch low_resource_manager_init(); 155255736Sdavidch 156255736Sdavidch // now we can use the heap and create areas 157255736Sdavidch arch_platform_init_post_vm(&sKernelArgs); 158255736Sdavidch lock_debug_init(); 159255736Sdavidch TRACE("init driver_settings\n"); 160255736Sdavidch driver_settings_init(&sKernelArgs); 161255736Sdavidch debug_init_post_settings(&sKernelArgs); 162255736Sdavidch TRACE("init notification services\n"); 163255736Sdavidch notifications_init(); 164255736Sdavidch TRACE("init teams\n"); 165255736Sdavidch team_init(&sKernelArgs); 166255736Sdavidch TRACE("init ELF loader\n"); 167255736Sdavidch elf_init(&sKernelArgs); 168255736Sdavidch TRACE("init modules\n"); 169255736Sdavidch module_init(&sKernelArgs); 170255736Sdavidch TRACE("init semaphores\n"); 171255736Sdavidch haiku_sem_init(&sKernelArgs); 172255736Sdavidch TRACE("init interrupts post vm\n"); 173255736Sdavidch int_init_post_vm(&sKernelArgs); 174255736Sdavidch cpu_init_post_vm(&sKernelArgs); 175255736Sdavidch commpage_init(); 176255736Sdavidch#ifdef _COMPAT_MODE 177255736Sdavidch commpage_compat_init(); 178255736Sdavidch#endif 179255736Sdavidch call_all_cpus_sync(non_boot_cpu_init, &sKernelArgs); 180255736Sdavidch 181255736Sdavidch TRACE("init system info\n"); 182255736Sdavidch system_info_init(&sKernelArgs); 183255736Sdavidch 184255736Sdavidch TRACE("init SMP\n"); 185255736Sdavidch smp_init(&sKernelArgs); 186255736Sdavidch cpu_build_topology_tree(); 187255736Sdavidch TRACE("init timer\n"); 188255736Sdavidch timer_init(&sKernelArgs); 189255736Sdavidch TRACE("init real time clock\n"); 190255736Sdavidch rtc_init(&sKernelArgs); 191255736Sdavidch timer_init_post_rtc(); 192255736Sdavidch 193255736Sdavidch TRACE("init condition variables\n"); 194255736Sdavidch condition_variable_init(); 195255736Sdavidch 196255736Sdavidch // now we can create and use semaphores 197255736Sdavidch TRACE("init VM semaphores\n"); 198255736Sdavidch vm_init_post_sem(&sKernelArgs); 199255736Sdavidch TRACE("init generic syscall\n"); 200255736Sdavidch generic_syscall_init(); 201255736Sdavidch smp_init_post_generic_syscalls(); 202255736Sdavidch TRACE("init scheduler\n"); 203255736Sdavidch scheduler_init(); 204255736Sdavidch TRACE("init threads\n"); 205255736Sdavidch thread_init(&sKernelArgs); 206255736Sdavidch TRACE("init kernel daemons\n"); 207255736Sdavidch kernel_daemon_init(); 208255736Sdavidch TRACE("init stack protector\n"); 209255736Sdavidch stack_protector_init(); 210255736Sdavidch arch_platform_init_post_thread(&sKernelArgs); 211255736Sdavidch 212255736Sdavidch TRACE("init I/O interrupts\n"); 213255736Sdavidch int_init_io(&sKernelArgs); 214255736Sdavidch TRACE("init VM threads\n"); 215255736Sdavidch vm_init_post_thread(&sKernelArgs); 216255736Sdavidch low_resource_manager_init_post_thread(); 217255736Sdavidch TRACE("init DPC\n"); 218255736Sdavidch dpc_init(); 219255736Sdavidch TRACE("init VFS\n"); 220255736Sdavidch vfs_init(&sKernelArgs); 221255736Sdavidch#if ENABLE_SWAP_SUPPORT 222255736Sdavidch TRACE("init swap support\n"); 223255736Sdavidch swap_init(); 224255736Sdavidch#endif 225255736Sdavidch TRACE("init POSIX semaphores\n"); 226255736Sdavidch realtime_sem_init(); 227255736Sdavidch xsi_sem_init(); 228255736Sdavidch xsi_msg_init(); 229255736Sdavidch 230255736Sdavidch // Start a thread to finish initializing the rest of the system. Note, 231255736Sdavidch // it won't be scheduled before calling scheduler_start() (on any CPU). 232255736Sdavidch TRACE("spawning main2 thread\n"); 233255736Sdavidch thread_id thread = spawn_kernel_thread(&main2, "main2", 234255736Sdavidch B_NORMAL_PRIORITY, NULL); 235255736Sdavidch resume_thread(thread); 236255736Sdavidch 237255736Sdavidch // We're ready to start the scheduler and enable interrupts on all CPUs. 238255736Sdavidch scheduler_enable_scheduling(); 239255736Sdavidch 240255736Sdavidch // bring up the AP cpus in a lock step fashion 241255736Sdavidch TRACE("waking up AP cpus\n"); 242255736Sdavidch sCpuRendezvous = sCpuRendezvous2 = 0; 243255736Sdavidch smp_wake_up_non_boot_cpus(); 244255736Sdavidch smp_cpu_rendezvous(&sCpuRendezvous); // wait until they're booted 245255736Sdavidch 246255736Sdavidch // exit the kernel startup phase (mutexes, etc work from now on out) 247255736Sdavidch TRACE("exiting kernel startup\n"); 248255736Sdavidch gKernelStartup = false; 249255736Sdavidch 250255736Sdavidch smp_cpu_rendezvous(&sCpuRendezvous2); 251255736Sdavidch // release the AP cpus to go enter the scheduler 252255736Sdavidch 253255736Sdavidch TRACE("starting scheduler on cpu 0 and enabling interrupts\n"); 254255736Sdavidch scheduler_start(); 255255736Sdavidch enable_interrupts(); 256255736Sdavidch } else { 257255736Sdavidch // lets make sure we're in sync with the main cpu 258255736Sdavidch // the boot processor has probably been sending us 259255736Sdavidch // tlb sync messages all along the way, but we've 260255736Sdavidch // been ignoring them 261255736Sdavidch arch_cpu_global_TLB_invalidate(); 262255736Sdavidch 263255736Sdavidch // this is run for each non boot processor after they've been set loose 264255736Sdavidch smp_per_cpu_init(&sKernelArgs, currentCPU); 265255736Sdavidch 266255736Sdavidch // wait for all other AP cpus to get to this point 267255736Sdavidch smp_cpu_rendezvous(&sCpuRendezvous); 268255736Sdavidch smp_cpu_rendezvous(&sCpuRendezvous2); 269255736Sdavidch 270255736Sdavidch // welcome to the machine 271255736Sdavidch scheduler_start(); 272255736Sdavidch enable_interrupts(); 273255736Sdavidch } 274255736Sdavidch 275255736Sdavidch#ifdef TRACE_BOOT 276255736Sdavidch // We disable interrupts for this dprintf(), since otherwise dprintf() 277255736Sdavidch // would acquires a mutex, which is something we must not do in an idle 278255736Sdavidch // thread, or otherwise the scheduler would be seriously unhappy. 279255736Sdavidch disable_interrupts(); 280255736Sdavidch TRACE("main: done... begin idle loop on cpu %d\n", currentCPU); 281255736Sdavidch enable_interrupts(); 282255736Sdavidch#endif 283255736Sdavidch 284255736Sdavidch for (;;) 285255736Sdavidch cpu_idle(); 286255736Sdavidch 287255736Sdavidch return 0; 288255736Sdavidch} 289255736Sdavidch 290255736Sdavidch 291255736Sdavidchstatic int32 292255736Sdavidchmain2(void* /*unused*/) 293255736Sdavidch{ 294255736Sdavidch TRACE("start of main2: initializing devices\n"); 295255736Sdavidch 296255736Sdavidch#if SYSTEM_PROFILER 297255736Sdavidch start_system_profiler(SYSTEM_PROFILE_SIZE, SYSTEM_PROFILE_STACK_DEPTH, 298255736Sdavidch SYSTEM_PROFILE_INTERVAL); 299255736Sdavidch#endif 300255736Sdavidch boot_splash_init(sKernelArgs.boot_splash); 301255736Sdavidch 302255736Sdavidch commpage_init_post_cpus(); 303255736Sdavidch#ifdef _COMPAT_MODE 304255736Sdavidch commpage_compat_init_post_cpus(); 305255736Sdavidch#endif 306255736Sdavidch 307255736Sdavidch TRACE("init ports\n"); 308255736Sdavidch port_init(&sKernelArgs); 309255736Sdavidch 310255736Sdavidch TRACE("init user mutex\n"); 311255736Sdavidch user_mutex_init(); 312255736Sdavidch 313255736Sdavidch TRACE("init system notifications\n"); 314255736Sdavidch system_notifications_init(); 315255736Sdavidch 316255736Sdavidch TRACE("Init modules\n"); 317255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES); 318255736Sdavidch module_init_post_threads(); 319255736Sdavidch 320255736Sdavidch // init userland debugging 321255736Sdavidch TRACE("Init Userland debugging\n"); 322255736Sdavidch init_user_debug(); 323255736Sdavidch 324255736Sdavidch // init the messaging service 325255736Sdavidch TRACE("Init Messaging Service\n"); 326255736Sdavidch init_messaging_service(); 327255736Sdavidch 328255736Sdavidch /* bootstrap all the filesystems */ 329255736Sdavidch TRACE("Bootstrap file systems\n"); 330255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_2_BOOTSTRAP_FS); 331255736Sdavidch vfs_bootstrap_file_systems(); 332255736Sdavidch 333255736Sdavidch TRACE("Init Device Manager\n"); 334255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_3_INIT_DEVICES); 335255736Sdavidch device_manager_init(&sKernelArgs); 336255736Sdavidch 337255736Sdavidch TRACE("Add preloaded old-style drivers\n"); 338255736Sdavidch legacy_driver_add_preloaded(&sKernelArgs); 339255736Sdavidch 340255736Sdavidch int_init_post_device_manager(&sKernelArgs); 341255736Sdavidch 342255736Sdavidch TRACE("Mount boot file system\n"); 343255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_4_MOUNT_BOOT_FS); 344255736Sdavidch vfs_mount_boot_file_system(&sKernelArgs); 345255736Sdavidch 346255736Sdavidch#if ENABLE_SWAP_SUPPORT 347255736Sdavidch TRACE("swap_init_post_modules\n"); 348255736Sdavidch swap_init_post_modules(); 349255736Sdavidch#endif 350255736Sdavidch 351255736Sdavidch // CPU specific modules may now be available 352255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_5_INIT_CPU_MODULES); 353255736Sdavidch cpu_init_post_modules(&sKernelArgs); 354255736Sdavidch 355255736Sdavidch TRACE("vm_init_post_modules\n"); 356255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_6_INIT_VM_MODULES); 357255736Sdavidch vm_init_post_modules(&sKernelArgs); 358255736Sdavidch 359255736Sdavidch TRACE("debug_init_post_modules\n"); 360255736Sdavidch debug_init_post_modules(&sKernelArgs); 361255736Sdavidch 362255736Sdavidch TRACE("device_manager_init_post_modules\n"); 363255736Sdavidch device_manager_init_post_modules(&sKernelArgs); 364255736Sdavidch 365255736Sdavidch boot_splash_set_stage(BOOT_SPLASH_STAGE_7_RUN_BOOT_SCRIPT); 366255736Sdavidch boot_splash_uninit(); 367255736Sdavidch // NOTE: We could introduce a syscall to draw more icons indicating 368255736Sdavidch // stages in the boot script itself. Then we should not free the image. 369255736Sdavidch // In that case we should copy it over to the kernel heap, so that we 370255736Sdavidch // can still free the kernel args. 371255736Sdavidch 372255736Sdavidch // The boot splash screen is the last user of the kernel args. 373255736Sdavidch // Note: don't confuse the kernel_args structure (which is never freed) 374255736Sdavidch // with the kernel args ranges it contains (and which are freed here). 375255736Sdavidch vm_free_kernel_args(&sKernelArgs); 376255736Sdavidch 377255736Sdavidch // start the init process 378255736Sdavidch { 379255736Sdavidch KPath serverPath; 380255736Sdavidch status_t status = __find_directory(B_SYSTEM_SERVERS_DIRECTORY, 381255736Sdavidch gBootDevice, false, serverPath.LockBuffer(), 382255736Sdavidch serverPath.BufferSize()); 383255736Sdavidch if (status != B_OK) 384255736Sdavidch dprintf("main2: find_directory() failed: %s\n", strerror(status)); 385255736Sdavidch serverPath.UnlockBuffer(); 386255736Sdavidch status = serverPath.Append("/launch_daemon"); 387255736Sdavidch if (status != B_OK) { 388255736Sdavidch dprintf("main2: constructing path to launch_daemon failed: %s\n", 389255736Sdavidch strerror(status)); 390255736Sdavidch } 391255736Sdavidch 392255736Sdavidch const char* args[] = { serverPath.Path(), NULL }; 393255736Sdavidch int32 argc = 1; 394255736Sdavidch thread_id thread; 395255736Sdavidch 396255736Sdavidch thread = load_image(argc, args, NULL); 397255736Sdavidch if (thread >= B_OK) { 398255736Sdavidch resume_thread(thread); 399255736Sdavidch TRACE("launch_daemon started\n"); 400255736Sdavidch } else { 401255736Sdavidch dprintf("error starting \"%s\" error = %" B_PRId32 " \n", 402255736Sdavidch args[0], thread); 403255736Sdavidch } 404255736Sdavidch } 405255736Sdavidch 406255736Sdavidch return 0; 407255736Sdavidch} 408255736Sdavidch 409255736Sdavidch