/* * Activate a secondary processor. */ static void notrace start_secondary(void *unused) { /* * Don't put *anything* except direct CPU state initialization * before cpu_init(), SMP booting is too fragile that we want to * limit the things done here to the most necessary things. */ if (boot_cpu_has(X86_FEATURE_PCID)) __write_cr4(__read_cr4() | X86_CR4_PCIDE); #ifdef CONFIG_X86_32 /* switch away from the initial page table */ load_cr3(swapper_pg_dir); /* * Initialize the CR4 shadow before doing anything that could * try to read it. */ cr4_init_shadow(); __flush_tlb_all(); #endif load_current_idt(); cpu_init(); x86_cpuinit.early_percpu_clock_init(); preempt_disable(); smp_callin(); enable_start_cpu0 = 0; /* otherwise gcc will move up smp_processor_id before the cpu_init */ barrier(); /* * Check TSC synchronization with the boot CPU: */ check_tsc_sync_target(); speculative_store_bypass_ht_init(); /* * Lock vector_lock, set CPU online and bring the vector * allocator online. Online must be set with vector_lock held * to prevent a concurrent irq setup/teardown from seeing a * half valid vector space. */ lock_vector_lock(); set_cpu_online(smp_processor_id(), true); lapic_online(); unlock_vector_lock(); cpu_set_state_online(smp_processor_id()); x86_platform.nmi_init(); /* enable local interrupts */ local_irq_enable(); /* to prevent fake stack check failure in clock setup */ boot_init_stack_canary(); x86_cpuinit.setup_percpu_clockev(); wmb(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); }
void __init setup_real_mode(void) { u16 real_mode_seg; const u32 *rel; u32 count; unsigned char *base; unsigned long phys_base; struct trampoline_header *trampoline_header; size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); #ifdef CONFIG_X86_64 u64 *trampoline_pgd; u64 efer; #endif base = (unsigned char *)real_mode_header; memcpy(base, real_mode_blob, size); phys_base = __pa(base); real_mode_seg = phys_base >> 4; rel = (u32 *) real_mode_relocs; /* 16-bit segment relocations. */ count = *rel++; while (count--) { u16 *seg = (u16 *) (base + *rel++); *seg = real_mode_seg; } /* 32-bit linear relocations. */ count = *rel++; while (count--) { u32 *ptr = (u32 *) (base + *rel++); *ptr += phys_base; } /* Must be perfomed *after* relocation. */ trampoline_header = (struct trampoline_header *) __va(real_mode_header->trampoline_header); #ifdef CONFIG_X86_32 trampoline_header->start = __pa_symbol(ktla_ktva(startup_32_smp)); #ifdef CONFIG_PAX_KERNEXEC trampoline_header->start -= LOAD_PHYSICAL_ADDR; #endif trampoline_header->boot_cs = __BOOT_CS; trampoline_header->gdt_limit = __BOOT_DS + 7; trampoline_header->gdt_base = __pa_symbol(boot_gdt); #else /* * Some AMD processors will #GP(0) if EFER.LMA is set in WRMSR * so we need to mask it out. */ rdmsrl(MSR_EFER, efer); trampoline_header->efer = efer & ~EFER_LMA; trampoline_header->start = (u64) secondary_startup_64; trampoline_cr4_features = &trampoline_header->cr4; *trampoline_cr4_features = __read_cr4(); trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd & ~_PAGE_NX; trampoline_pgd[511] = init_level4_pgt[511].pgd; #endif }