X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/bd504ef0e0b883cdd7917b73b3574eb9ce669905..d26ffc64f583ab2d29df48f13518685602bc8832:/osfmk/kern/startup.c diff --git a/osfmk/kern/startup.c b/osfmk/kern/startup.c index e17631376..c9cfd5167 100644 --- a/osfmk/kern/startup.c +++ b/osfmk/kern/startup.c @@ -80,19 +80,28 @@ #include #include #include +#include #include #include #include #include #include +#if CONFIG_SCHED_SFI +#include +#endif #include #include #include #include -#include +#if CONFIG_TELEMETRY +#include +#endif #include #include #include +#include +#include +#include #include #include #include @@ -104,7 +113,31 @@ #include #include #include +#include #include +#include +#include + +#include +#include +#include +#include +#include + + +#if CONFIG_ATM +#include +#endif + +#if CONFIG_CSR +#include +#endif + +#include + +#if ALTERNATE_DEBUGGER +#include +#endif #if MACH_KDP #include @@ -112,10 +145,23 @@ #if CONFIG_MACF #include +#if CONFIG_VNGUARD +extern void vnguard_policy_init(void); +#endif #endif -#if CONFIG_COUNTERS -#include +#if KPC +#include +#endif + +#if HYPERVISOR +#include +#endif + +#include + +#if defined(__arm__) || defined(__arm64__) +#include // for arm_vm_prot_finalize #endif #include @@ -128,12 +174,23 @@ extern void cpu_userwindow_init(int); extern void cpu_physwindow_init(int); #endif +#if CONFIG_ECC_LOGGING +#include +#endif + +#if (defined(__i386__) || defined(__x86_64__)) && CONFIG_VMX +#include +#endif + // libkern/OSKextLib.cpp extern void OSKextRemoveKextBootstrap(void); void scale_setup(void); extern void bsd_scale_setup(int); extern unsigned int semaphore_max; +extern void stackshot_init(void); +extern void ktrace_init(void); +extern void oslog_init(void); /* * Running in virtual memory, on the interrupt stack. @@ -144,24 +201,54 @@ extern int serverperfmode; /* size of kernel trace buffer, disabled by default */ unsigned int new_nkdbufs = 0; unsigned int wake_nkdbufs = 0; +unsigned int write_trace_on_panic = 0; +static char trace_typefilter[64] = { 0 }; +unsigned int trace_wrap = 0; +boolean_t trace_serial = FALSE; +boolean_t early_boot_complete = FALSE; /* mach leak logging */ int log_leaks = 0; -int turn_on_log_leaks = 0; +static inline void +kernel_bootstrap_log(const char *message) +{ +// kprintf("kernel_bootstrap: %s\n", message); + kernel_debug_string_early(message); +} + +static inline void +kernel_bootstrap_thread_log(const char *message) +{ +// kprintf("kernel_bootstrap_thread: %s\n", message); + kernel_debug_string_early(message); +} void kernel_early_bootstrap(void) { + /* serverperfmode is needed by timer setup */ + if (PE_parse_boot_argn("serverperfmode", &serverperfmode, sizeof (serverperfmode))) { + serverperfmode = 1; + } lck_mod_init(); /* * Initialize the timer callout world */ - timer_call_initialize(); + timer_call_init(); + +#if CONFIG_SCHED_SFI + /* + * Configure SFI classes + */ + sfi_early_init(); +#endif } +extern boolean_t IORamDiskBSDRoot(void); +extern kern_return_t cpm_preallocate_early(void); void kernel_bootstrap(void) @@ -172,25 +259,24 @@ kernel_bootstrap(void) printf("%s\n", version); /* log kernel version */ -#define kernel_bootstrap_kprintf(x...) /* kprintf("kernel_bootstrap: " x) */ - if (PE_parse_boot_argn("-l", namep, sizeof (namep))) /* leaks logging */ - turn_on_log_leaks = 1; + log_leaks = 1; PE_parse_boot_argn("trace", &new_nkdbufs, sizeof (new_nkdbufs)); - PE_parse_boot_argn("trace_wake", &wake_nkdbufs, sizeof (wake_nkdbufs)); + PE_parse_boot_argn("trace_panic", &write_trace_on_panic, sizeof(write_trace_on_panic)); + PE_parse_boot_arg_str("trace_typefilter", trace_typefilter, sizeof(trace_typefilter)); + PE_parse_boot_argn("trace_wrap", &trace_wrap, sizeof(trace_wrap)); - /* i386_vm_init already checks for this ; do it aagin anyway */ - if (PE_parse_boot_argn("serverperfmode", &serverperfmode, sizeof (serverperfmode))) { - serverperfmode = 1; - } scale_setup(); - kernel_bootstrap_kprintf("calling vm_mem_bootstrap\n"); + kernel_bootstrap_log("vm_mem_bootstrap"); vm_mem_bootstrap(); - kernel_bootstrap_kprintf("calling vm_mem_init\n"); + kernel_bootstrap_log("cs_init"); + cs_init(); + + kernel_bootstrap_log("vm_mem_init"); vm_mem_init(); machine_info.memory_size = (uint32_t)mem_size; @@ -198,35 +284,68 @@ kernel_bootstrap(void) machine_info.major_version = version_major; machine_info.minor_version = version_minor; - kernel_bootstrap_kprintf("calling sched_init\n"); + oslog_init(); + +#if KASAN + kernel_bootstrap_log("kasan_late_init"); + kasan_late_init(); +#endif + +#if CONFIG_TELEMETRY + kernel_bootstrap_log("telemetry_init"); + telemetry_init(); +#endif + +#if CONFIG_CSR + kernel_bootstrap_log("csr_init"); + csr_init(); +#endif + + if (PE_i_can_has_debugger(NULL) && + PE_parse_boot_argn("-show_pointers", &namep, sizeof (namep))) { + doprnt_hide_pointers = FALSE; + } + + kernel_bootstrap_log("console_init"); + console_init(); + + kernel_bootstrap_log("stackshot_init"); + stackshot_init(); + + kernel_bootstrap_log("sched_init"); sched_init(); - kernel_bootstrap_kprintf("calling wait_queue_bootstrap\n"); - wait_queue_bootstrap(); + kernel_bootstrap_log("ltable_bootstrap"); + ltable_bootstrap(); - kernel_bootstrap_kprintf("calling ipc_bootstrap\n"); + kernel_bootstrap_log("waitq_bootstrap"); + waitq_bootstrap(); + + kernel_bootstrap_log("ipc_bootstrap"); ipc_bootstrap(); #if CONFIG_MACF + kernel_bootstrap_log("mac_policy_init"); mac_policy_init(); #endif - kernel_bootstrap_kprintf("calling ipc_init\n"); + + kernel_bootstrap_log("ipc_init"); ipc_init(); /* * As soon as the virtual memory system is up, we record * that this CPU is using the kernel pmap. */ - kernel_bootstrap_kprintf("calling PMAP_ACTIVATE_KERNEL\n"); + kernel_bootstrap_log("PMAP_ACTIVATE_KERNEL"); PMAP_ACTIVATE_KERNEL(master_cpu); - kernel_bootstrap_kprintf("calling mapping_free_prime\n"); + kernel_bootstrap_log("mapping_free_prime"); mapping_free_prime(); /* Load up with temporary mapping blocks */ - kernel_bootstrap_kprintf("calling machine_init\n"); + kernel_bootstrap_log("machine_init"); machine_init(); - kernel_bootstrap_kprintf("calling clock_init\n"); + kernel_bootstrap_log("clock_init"); clock_init(); ledger_init(); @@ -234,24 +353,52 @@ kernel_bootstrap(void) /* * Initialize the IPC, task, and thread subsystems. */ - kernel_bootstrap_kprintf("calling task_init\n"); + +#if CONFIG_COALITIONS + kernel_bootstrap_log("coalitions_init"); + coalitions_init(); +#endif + + kernel_bootstrap_log("task_init"); task_init(); - kernel_bootstrap_kprintf("calling thread_init\n"); + kernel_bootstrap_log("thread_init"); thread_init(); - + +#if CONFIG_ATM + /* Initialize the Activity Trace Resource Manager. */ + kernel_bootstrap_log("atm_init"); + atm_init(); +#endif + kernel_bootstrap_log("mach_init_activity_id"); + mach_init_activity_id(); + + /* Initialize the BANK Manager. */ + kernel_bootstrap_log("bank_init"); + bank_init(); + + kernel_bootstrap_log("ipc_pthread_priority_init"); + ipc_pthread_priority_init(); + + /* initialize the corpse config based on boot-args */ + corpses_init(); + + /* initialize host_statistics */ + host_statistics_init(); + /* * Create a kernel thread to execute the kernel bootstrap. */ - kernel_bootstrap_kprintf("calling kernel_thread_create\n"); + kernel_bootstrap_log("kernel_thread_create"); result = kernel_thread_create((thread_continue_t)kernel_bootstrap_thread, NULL, MAXPRI_KERNEL, &thread); if (result != KERN_SUCCESS) panic("kernel_bootstrap: result = %08X\n", result); thread->state = TH_RUN; + thread->last_made_runnable_time = mach_absolute_time(); thread_deallocate(thread); - kernel_bootstrap_kprintf("calling load_context - done\n"); + kernel_bootstrap_log("load_context - done"); load_context(thread); /*NOTREACHED*/ } @@ -259,6 +406,10 @@ kernel_bootstrap(void) int kth_started = 0; vm_offset_t vm_kernel_addrperm; +vm_offset_t buf_kernel_addrperm; +vm_offset_t vm_kernel_addrperm_ext; +uint64_t vm_kernel_addrhash_salt; +uint64_t vm_kernel_addrhash_salt_ext; /* * Now running in a thread. Kick off other services, @@ -270,7 +421,7 @@ kernel_bootstrap_thread(void) processor_t processor = current_processor(); #define kernel_bootstrap_thread_kprintf(x...) /* kprintf("kernel_bootstrap_thread: " x) */ - kernel_bootstrap_thread_kprintf("calling idle_thread_create\n"); + kernel_bootstrap_thread_log("idle_thread_create"); /* * Create the idle processor thread. */ @@ -282,38 +433,53 @@ kernel_bootstrap_thread(void) * * Start up the scheduler services. */ - kernel_bootstrap_thread_kprintf("calling sched_startup\n"); + kernel_bootstrap_thread_log("sched_startup"); sched_startup(); /* * Thread lifecycle maintenance (teardown, stack allocation) */ - kernel_bootstrap_thread_kprintf("calling thread_daemon_init\n"); + kernel_bootstrap_thread_log("thread_daemon_init"); thread_daemon_init(); - + + /* Create kernel map entry reserve */ + vm_kernel_reserved_entry_init(); + /* * Thread callout service. */ - kernel_bootstrap_thread_kprintf("calling thread_call_initialize\n"); + kernel_bootstrap_thread_log("thread_call_initialize"); thread_call_initialize(); - + /* * Remain on current processor as * additional processors come online. */ - kernel_bootstrap_thread_kprintf("calling thread_bind\n"); + kernel_bootstrap_thread_log("thread_bind"); thread_bind(processor); +#if __arm64__ + if (IORamDiskBSDRoot()) { + cpm_preallocate_early(); + } +#endif /* __arm64__ */ + + /* + * Initialize ipc thread call support. + */ + kernel_bootstrap_thread_log("ipc_thread_call_init"); + ipc_thread_call_init(); + /* * Kick off memory mapping adjustments. */ - kernel_bootstrap_thread_kprintf("calling mapping_adjust\n"); + kernel_bootstrap_thread_log("mapping_adjust"); mapping_adjust(); /* * Create the clock service. */ - kernel_bootstrap_thread_kprintf("calling clock_service_create\n"); + kernel_bootstrap_thread_log("clock_service_create"); clock_service_create(); /* @@ -322,7 +488,7 @@ kernel_bootstrap_thread(void) device_service_create(); kth_started = 1; - + #if (defined(__i386__) || defined(__x86_64__)) && NCOPY_WINDOWS > 0 /* * Create and initialize the physical copy window for processor 0 @@ -331,29 +497,72 @@ kernel_bootstrap_thread(void) cpu_physwindow_init(0); #endif - vm_kernel_reserved_entry_init(); + -#if MACH_KDP - kernel_bootstrap_kprintf("calling kdp_init\n"); +#if MACH_KDP + kernel_bootstrap_log("kdp_init"); kdp_init(); #endif -#if CONFIG_COUNTERS - pmc_bootstrap(); +#if ALTERNATE_DEBUGGER + alternate_debugger_init(); #endif -#if (defined(__i386__) || defined(__x86_64__)) - if (turn_on_log_leaks && !new_nkdbufs) - new_nkdbufs = 200000; - start_kern_tracing(new_nkdbufs, FALSE); - if (turn_on_log_leaks) - log_leaks = 1; +#if KPC + kpc_init(); +#endif + +#if CONFIG_ECC_LOGGING + ecc_log_init(); +#endif + +#if HYPERVISOR + hv_support_init(); +#endif + +#if CONFIG_TELEMETRY + kernel_bootstrap_log("bootprofile_init"); + bootprofile_init(); +#endif + +#if (defined(__i386__) || defined(__x86_64__)) && CONFIG_VMX + vmx_init(); +#endif + + kernel_bootstrap_thread_log("ktrace_init"); + ktrace_init(); + + kdebug_init(new_nkdbufs, trace_typefilter, trace_wrap); + + kernel_bootstrap_log("prng_init"); + prng_cpu_init(master_cpu); + +#ifdef MACH_BSD + kernel_bootstrap_log("bsd_early_init"); + bsd_early_init(); +#endif + +#if defined(__arm64__) + ml_lockdown_init(); #endif #ifdef IOKIT + kernel_bootstrap_log("PE_init_iokit"); PE_init_iokit(); #endif - + + assert(ml_get_interrupts_enabled() == FALSE); + + /* + * Past this point, kernel subsystems that expect to operate with + * interrupts or preemption enabled may begin enforcement. + */ + early_boot_complete = TRUE; + +#if INTERRUPT_MASKED_DEBUG + // Reset interrupts masked timeout before we enable interrupts + ml_spin_debug_clear_self(); +#endif (void) spllo(); /* Allow interruptions */ #if (defined(__i386__) || defined(__x86_64__)) && NCOPY_WINDOWS > 0 @@ -367,14 +576,6 @@ kernel_bootstrap_thread(void) cpu_userwindow_init(0); #endif -#if (!defined(__i386__) && !defined(__x86_64__)) - if (turn_on_log_leaks && !new_nkdbufs) - new_nkdbufs = 200000; - start_kern_tracing(new_nkdbufs, FALSE); - if (turn_on_log_leaks) - log_leaks = 1; -#endif - /* * Initialize the shared region module. */ @@ -383,17 +584,50 @@ kernel_bootstrap_thread(void) vm_commpage_text_init(); #if CONFIG_MACF + kernel_bootstrap_log("mac_policy_initmach"); mac_policy_initmach(); +#if CONFIG_VNGUARD + vnguard_policy_init(); +#endif +#endif + +#if defined(__arm__) || defined(__arm64__) +#if CONFIG_KERNEL_INTEGRITY + machine_lockdown_preflight(); +#endif + /* + * Finalize protections on statically mapped pages now that comm page mapping is established. + */ + arm_vm_prot_finalize(PE_state.bootArgs); +#endif + +#if CONFIG_SCHED_SFI + kernel_bootstrap_log("sfi_init"); + sfi_init(); #endif /* - * Initialize the global used for permuting kernel + * Initialize the globals used for permuting kernel * addresses that may be exported to userland as tokens - * using VM_KERNEL_ADDRPERM(). Force the random number - * to be odd to avoid mapping a non-zero + * using VM_KERNEL_ADDRPERM()/VM_KERNEL_ADDRPERM_EXTERNAL(). + * Force the random number to be odd to avoid mapping a non-zero * word-aligned address to zero via addition. + * Note: at this stage we can use the cryptographically secure PRNG + * rather than early_random(). */ - vm_kernel_addrperm = (vm_offset_t)early_random() | 1; + read_random(&vm_kernel_addrperm, sizeof(vm_kernel_addrperm)); + vm_kernel_addrperm |= 1; + read_random(&buf_kernel_addrperm, sizeof(buf_kernel_addrperm)); + buf_kernel_addrperm |= 1; + read_random(&vm_kernel_addrperm_ext, sizeof(vm_kernel_addrperm_ext)); + vm_kernel_addrperm_ext |= 1; + read_random(&vm_kernel_addrhash_salt, sizeof(vm_kernel_addrhash_salt)); + read_random(&vm_kernel_addrhash_salt_ext, sizeof(vm_kernel_addrhash_salt_ext)); + + vm_set_restrictions(); + + + /* * Start the user bootstrap. @@ -408,6 +642,11 @@ kernel_bootstrap_thread(void) */ OSKextRemoveKextBootstrap(); + /* + * Get rid of pages used for early boot tracing. + */ + kdebug_free_early_buf(); + serial_keyboard_init(); /* Start serial keyboard if wanted */ vm_page_init_local_q(); @@ -481,7 +720,7 @@ processor_start_thread(void *machine_param) * * Start the first thread on a processor. */ -static void +static void __attribute__((noreturn)) load_context( thread_t thread) { @@ -490,10 +729,10 @@ load_context( #define load_context_kprintf(x...) /* kprintf("load_context: " x) */ - load_context_kprintf("calling machine_set_current_thread\n"); + load_context_kprintf("machine_set_current_thread\n"); machine_set_current_thread(thread); - load_context_kprintf("calling processor_up\n"); + load_context_kprintf("processor_up\n"); processor_up(processor); PMAP_ACTIVATE_KERNEL(processor->cpu_id); @@ -503,10 +742,10 @@ load_context( * should never occur since the thread is expected * to have reserved stack. */ - load_context_kprintf("thread %p, stack %x, stackptr %x\n", thread, + load_context_kprintf("thread %p, stack %lx, stackptr %lx\n", thread, thread->kernel_stack, thread->machine.kstackptr); if (!thread->kernel_stack) { - load_context_kprintf("calling stack_alloc_try\n"); + load_context_kprintf("stack_alloc_try\n"); if (!stack_alloc_try(thread)) panic("load_context"); } @@ -516,11 +755,12 @@ load_context( * running for load calculations. */ if (!(thread->state & TH_IDLE)) - sched_run_incr(); + sched_run_incr(thread); processor->active_thread = thread; - processor->current_pri = thread->sched_pri; - processor->current_thmode = thread->sched_mode; + processor_state_update_explicit(processor, thread->sched_pri, + SFI_CLASS_KERNEL, PSET_SMP, thread_get_perfcontrol_class(thread)); + processor->starting_pri = thread->sched_pri; processor->deadline = UINT64_MAX; thread->last_processor = processor; @@ -531,9 +771,10 @@ load_context( timer_start(&PROCESSOR_DATA(processor, system_state), processor->last_dispatch); PROCESSOR_DATA(processor, current_state) = &PROCESSOR_DATA(processor, system_state); + PMAP_ACTIVATE_USER(thread, processor->cpu_id); - load_context_kprintf("calling machine_load_context\n"); + load_context_kprintf("machine_load_context\n"); machine_load_context(thread); /*NOTREACHED*/ } @@ -552,8 +793,15 @@ scale_setup() if (scale > 16) scale = 16; task_max_base = 2500; - } else if ((uint64_t)sane_size >= (uint64_t)(3 * 1024 * 1024 *1024ULL)) - scale = 2; + /* Raise limits for machines with >= 3GB */ + } else if ((uint64_t)sane_size >= (uint64_t)(3 * 1024 * 1024 *1024ULL)) { + if ((uint64_t)sane_size < (uint64_t)(8 * 1024 * 1024 *1024ULL)) { + scale = 2; + } else { + /* limit to 64GB */ + scale = MIN(16, (int)((uint64_t)sane_size / (uint64_t)(4 * 1024 * 1024 *1024ULL))); + } + } task_max = MAX(task_max, task_max_base * scale);