1 /* 2 * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com. 3 * Copyright 2002-2020, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 /*! This is main - initializes the kernel and launches the launch_daemon */ 12 13 14 #include <string.h> 15 16 #include <FindDirectory.h> 17 #include <OS.h> 18 19 #include <arch/platform.h> 20 #include <boot_device.h> 21 #include <boot_item.h> 22 #include <boot_splash.h> 23 #include <commpage.h> 24 #ifdef _COMPAT_MODE 25 # include <commpage_compat.h> 26 #endif 27 #include <condition_variable.h> 28 #include <cpu.h> 29 #include <debug.h> 30 #include <DPC.h> 31 #include <elf.h> 32 #include <find_directory_private.h> 33 #include <fs/devfs.h> 34 #include <fs/KPath.h> 35 #include <int.h> 36 #include <kdevice_manager.h> 37 #include <kdriver_settings.h> 38 #include <kernel_daemon.h> 39 #include <kmodule.h> 40 #include <kscheduler.h> 41 #include <ksyscalls.h> 42 #include <ksystem_info.h> 43 #include <lock.h> 44 #include <low_resource_manager.h> 45 #include <messaging.h> 46 #include <Notifications.h> 47 #include <port.h> 48 #include <posix/realtime_sem.h> 49 #include <posix/xsi_message_queue.h> 50 #include <posix/xsi_semaphore.h> 51 #include <real_time_clock.h> 52 #include <sem.h> 53 #include <smp.h> 54 #include <system_profiler.h> 55 #include <team.h> 56 #include <timer.h> 57 #include <user_debugger.h> 58 #include <user_mutex.h> 59 #include <vfs.h> 60 #include <vm/vm.h> 61 #include <boot/kernel_args.h> 62 63 #include "vm/VMAnonymousCache.h" 64 65 66 //#define TRACE_BOOT 67 #ifdef TRACE_BOOT 68 # define TRACE(x...) dprintf("INIT: " x) 69 #else 70 # define TRACE(x...) ; 71 #endif 72 73 74 void *__dso_handle; 75 76 bool gKernelStartup = true; 77 bool gKernelShutdown = false; 78 79 static kernel_args sKernelArgs; 80 static uint32 sCpuRendezvous; 81 static uint32 sCpuRendezvous2; 82 static uint32 sCpuRendezvous3; 83 84 static int32 main2(void *); 85 86 87 static void 88 non_boot_cpu_init(void* args, int currentCPU) 89 { 90 kernel_args* kernelArgs = (kernel_args*)args; 91 if (currentCPU != 0) 92 cpu_init_percpu(kernelArgs, currentCPU); 93 } 94 95 96 extern "C" int 97 _start(kernel_args *bootKernelArgs, int currentCPU) 98 { 99 if (bootKernelArgs->version == CURRENT_KERNEL_ARGS_VERSION 100 && bootKernelArgs->kernel_args_size == kernel_args_size_v1) { 101 sKernelArgs.ucode_data = NULL; 102 sKernelArgs.ucode_data_size = 0; 103 } else if (bootKernelArgs->kernel_args_size != sizeof(kernel_args) 104 || bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) { 105 // This is something we cannot handle right now - release kernels 106 // should always be able to handle the kernel_args of earlier 107 // released kernels. 108 debug_early_boot_message("Version mismatch between boot loader and " 109 "kernel!\n"); 110 return -1; 111 } 112 113 smp_set_num_cpus(bootKernelArgs->num_cpus); 114 115 // wait for all the cpus to get here 116 smp_cpu_rendezvous(&sCpuRendezvous); 117 118 // the passed in kernel args are in a non-allocated range of memory 119 if (currentCPU == 0) 120 memcpy(&sKernelArgs, bootKernelArgs, bootKernelArgs->kernel_args_size); 121 122 smp_cpu_rendezvous(&sCpuRendezvous2); 123 124 // do any pre-booting cpu config 125 cpu_preboot_init_percpu(&sKernelArgs, currentCPU); 126 thread_preboot_init_percpu(&sKernelArgs, currentCPU); 127 128 // if we're not a boot cpu, spin here until someone wakes us up 129 if (smp_trap_non_boot_cpus(currentCPU, &sCpuRendezvous3)) { 130 // init platform 131 arch_platform_init(&sKernelArgs); 132 133 // setup debug output 134 debug_init(&sKernelArgs); 135 set_dprintf_enabled(true); 136 dprintf("Welcome to kernel debugger output!\n"); 137 dprintf("Haiku revision: %s, debug level: %d\n", get_haiku_revision(), 138 KDEBUG_LEVEL); 139 140 // init modules 141 TRACE("init CPU\n"); 142 cpu_init(&sKernelArgs); 143 cpu_init_percpu(&sKernelArgs, currentCPU); 144 TRACE("init interrupts\n"); 145 int_init(&sKernelArgs); 146 147 TRACE("init VM\n"); 148 vm_init(&sKernelArgs); 149 // Before vm_init_post_sem() is called, we have to make sure that 150 // the boot loader allocated region is not used anymore 151 boot_item_init(); 152 debug_init_post_vm(&sKernelArgs); 153 low_resource_manager_init(); 154 155 // now we can use the heap and create areas 156 arch_platform_init_post_vm(&sKernelArgs); 157 lock_debug_init(); 158 TRACE("init driver_settings\n"); 159 driver_settings_init(&sKernelArgs); 160 debug_init_post_settings(&sKernelArgs); 161 TRACE("init notification services\n"); 162 notifications_init(); 163 TRACE("init teams\n"); 164 team_init(&sKernelArgs); 165 TRACE("init ELF loader\n"); 166 elf_init(&sKernelArgs); 167 TRACE("init modules\n"); 168 module_init(&sKernelArgs); 169 TRACE("init semaphores\n"); 170 haiku_sem_init(&sKernelArgs); 171 TRACE("init interrupts post vm\n"); 172 int_init_post_vm(&sKernelArgs); 173 cpu_init_post_vm(&sKernelArgs); 174 commpage_init(); 175 #ifdef _COMPAT_MODE 176 commpage_compat_init(); 177 #endif 178 call_all_cpus_sync(non_boot_cpu_init, &sKernelArgs); 179 180 TRACE("init system info\n"); 181 system_info_init(&sKernelArgs); 182 183 TRACE("init SMP\n"); 184 smp_init(&sKernelArgs); 185 cpu_build_topology_tree(); 186 TRACE("init timer\n"); 187 timer_init(&sKernelArgs); 188 TRACE("init real time clock\n"); 189 rtc_init(&sKernelArgs); 190 timer_init_post_rtc(); 191 192 TRACE("init condition variables\n"); 193 condition_variable_init(); 194 195 // now we can create and use semaphores 196 TRACE("init VM semaphores\n"); 197 vm_init_post_sem(&sKernelArgs); 198 TRACE("init generic syscall\n"); 199 generic_syscall_init(); 200 smp_init_post_generic_syscalls(); 201 TRACE("init scheduler\n"); 202 scheduler_init(); 203 TRACE("init threads\n"); 204 thread_init(&sKernelArgs); 205 TRACE("init kernel daemons\n"); 206 kernel_daemon_init(); 207 arch_platform_init_post_thread(&sKernelArgs); 208 209 TRACE("init I/O interrupts\n"); 210 int_init_io(&sKernelArgs); 211 TRACE("init VM threads\n"); 212 vm_init_post_thread(&sKernelArgs); 213 low_resource_manager_init_post_thread(); 214 TRACE("init DPC\n"); 215 dpc_init(); 216 TRACE("init VFS\n"); 217 vfs_init(&sKernelArgs); 218 #if ENABLE_SWAP_SUPPORT 219 TRACE("init swap support\n"); 220 swap_init(); 221 #endif 222 TRACE("init POSIX semaphores\n"); 223 realtime_sem_init(); 224 xsi_sem_init(); 225 xsi_msg_init(); 226 227 // Start a thread to finish initializing the rest of the system. Note, 228 // it won't be scheduled before calling scheduler_start() (on any CPU). 229 TRACE("spawning main2 thread\n"); 230 thread_id thread = spawn_kernel_thread(&main2, "main2", 231 B_NORMAL_PRIORITY, NULL); 232 resume_thread(thread); 233 234 // We're ready to start the scheduler and enable interrupts on all CPUs. 235 scheduler_enable_scheduling(); 236 237 // bring up the AP cpus in a lock step fashion 238 TRACE("waking up AP cpus\n"); 239 sCpuRendezvous = sCpuRendezvous2 = 0; 240 smp_wake_up_non_boot_cpus(); 241 smp_cpu_rendezvous(&sCpuRendezvous); // wait until they're booted 242 243 // exit the kernel startup phase (mutexes, etc work from now on out) 244 TRACE("exiting kernel startup\n"); 245 gKernelStartup = false; 246 247 smp_cpu_rendezvous(&sCpuRendezvous2); 248 // release the AP cpus to go enter the scheduler 249 250 TRACE("starting scheduler on cpu 0 and enabling interrupts\n"); 251 scheduler_start(); 252 enable_interrupts(); 253 } else { 254 // lets make sure we're in sync with the main cpu 255 // the boot processor has probably been sending us 256 // tlb sync messages all along the way, but we've 257 // been ignoring them 258 arch_cpu_global_TLB_invalidate(); 259 260 // this is run for each non boot processor after they've been set loose 261 smp_per_cpu_init(&sKernelArgs, currentCPU); 262 263 // wait for all other AP cpus to get to this point 264 smp_cpu_rendezvous(&sCpuRendezvous); 265 smp_cpu_rendezvous(&sCpuRendezvous2); 266 267 // welcome to the machine 268 scheduler_start(); 269 enable_interrupts(); 270 } 271 272 #ifdef TRACE_BOOT 273 // We disable interrupts for this dprintf(), since otherwise dprintf() 274 // would acquires a mutex, which is something we must not do in an idle 275 // thread, or otherwise the scheduler would be seriously unhappy. 276 disable_interrupts(); 277 TRACE("main: done... begin idle loop on cpu %d\n", currentCPU); 278 enable_interrupts(); 279 #endif 280 281 for (;;) 282 cpu_idle(); 283 284 return 0; 285 } 286 287 288 static int32 289 main2(void* /*unused*/) 290 { 291 TRACE("start of main2: initializing devices\n"); 292 293 #if SYSTEM_PROFILER 294 start_system_profiler(SYSTEM_PROFILE_SIZE, SYSTEM_PROFILE_STACK_DEPTH, 295 SYSTEM_PROFILE_INTERVAL); 296 #endif 297 boot_splash_init(sKernelArgs.boot_splash); 298 299 commpage_init_post_cpus(); 300 #ifdef _COMPAT_MODE 301 commpage_compat_init_post_cpus(); 302 #endif 303 304 TRACE("init ports\n"); 305 port_init(&sKernelArgs); 306 307 TRACE("init user mutex\n"); 308 user_mutex_init(); 309 310 TRACE("init system notifications\n"); 311 system_notifications_init(); 312 313 TRACE("Init modules\n"); 314 boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES); 315 module_init_post_threads(); 316 317 // init userland debugging 318 TRACE("Init Userland debugging\n"); 319 init_user_debug(); 320 321 // init the messaging service 322 TRACE("Init Messaging Service\n"); 323 init_messaging_service(); 324 325 /* bootstrap all the filesystems */ 326 TRACE("Bootstrap file systems\n"); 327 boot_splash_set_stage(BOOT_SPLASH_STAGE_2_BOOTSTRAP_FS); 328 vfs_bootstrap_file_systems(); 329 330 TRACE("Init Device Manager\n"); 331 boot_splash_set_stage(BOOT_SPLASH_STAGE_3_INIT_DEVICES); 332 device_manager_init(&sKernelArgs); 333 334 TRACE("Add preloaded old-style drivers\n"); 335 legacy_driver_add_preloaded(&sKernelArgs); 336 337 int_init_post_device_manager(&sKernelArgs); 338 339 TRACE("Mount boot file system\n"); 340 boot_splash_set_stage(BOOT_SPLASH_STAGE_4_MOUNT_BOOT_FS); 341 vfs_mount_boot_file_system(&sKernelArgs); 342 343 #if ENABLE_SWAP_SUPPORT 344 TRACE("swap_init_post_modules\n"); 345 swap_init_post_modules(); 346 #endif 347 348 // CPU specific modules may now be available 349 boot_splash_set_stage(BOOT_SPLASH_STAGE_5_INIT_CPU_MODULES); 350 cpu_init_post_modules(&sKernelArgs); 351 352 TRACE("vm_init_post_modules\n"); 353 boot_splash_set_stage(BOOT_SPLASH_STAGE_6_INIT_VM_MODULES); 354 vm_init_post_modules(&sKernelArgs); 355 356 TRACE("debug_init_post_modules\n"); 357 debug_init_post_modules(&sKernelArgs); 358 359 TRACE("device_manager_init_post_modules\n"); 360 device_manager_init_post_modules(&sKernelArgs); 361 362 boot_splash_set_stage(BOOT_SPLASH_STAGE_7_RUN_BOOT_SCRIPT); 363 boot_splash_uninit(); 364 // NOTE: We could introduce a syscall to draw more icons indicating 365 // stages in the boot script itself. Then we should not free the image. 366 // In that case we should copy it over to the kernel heap, so that we 367 // can still free the kernel args. 368 369 // The boot splash screen is the last user of the kernel args. 370 // Note: don't confuse the kernel_args structure (which is never freed) 371 // with the kernel args ranges it contains (and which are freed here). 372 vm_free_kernel_args(&sKernelArgs); 373 374 // start the init process 375 { 376 KPath serverPath; 377 status_t status = __find_directory(B_SYSTEM_SERVERS_DIRECTORY, 378 gBootDevice, false, serverPath.LockBuffer(), 379 serverPath.BufferSize()); 380 if (status != B_OK) 381 dprintf("main2: find_directory() failed: %s\n", strerror(status)); 382 serverPath.UnlockBuffer(); 383 status = serverPath.Append("/launch_daemon"); 384 if (status != B_OK) { 385 dprintf("main2: constructing path to launch_daemon failed: %s\n", 386 strerror(status)); 387 } 388 389 const char* args[] = { serverPath.Path(), NULL }; 390 int32 argc = 1; 391 thread_id thread; 392 393 thread = load_image(argc, args, NULL); 394 if (thread >= B_OK) { 395 resume_thread(thread); 396 TRACE("launch_daemon started\n"); 397 } else { 398 dprintf("error starting \"%s\" error = %" B_PRId32 " \n", 399 args[0], thread); 400 } 401 } 402 403 return 0; 404 } 405 406