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