asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); printk("CPU%u: Booted secondary processor\n", cpu); setup_cpuinfo(); openrisc_clockevent_init(); notify_cpu_starting(cpu); /* * OK, now it's safe to let the boot CPU continue */ set_cpu_online(cpu, true); complete(&cpu_running); local_irq_enable(); /* * OK, it's off to the idle thread for us */ cpu_startup_entry(CPUHP_ONLINE); }
static void __cpuinit cpu_bringup(void) { int cpu; cpu_init(); touch_softlockup_watchdog(); preempt_disable(); xen_enable_sysenter(); xen_enable_syscall(); cpu = smp_processor_id(); smp_store_cpu_info(cpu); cpu_data(cpu).x86_max_cores = 1; set_cpu_sibling_map(cpu); xen_setup_cpu_clockevents(); notify_cpu_starting(cpu); set_cpu_online(cpu, true); this_cpu_write(cpu_state, CPU_ONLINE); wmb(); /* We can take interrupts now: we're officially "up". */ local_irq_enable(); wmb(); /* make sure everything is out */ }
void __cpuinit sparc_start_secondary(void *arg) { unsigned int cpu; /* * SMP booting is extremely fragile in some architectures. So run * the cpu initialization code first before anything else. */ arch_cpu_pre_starting(arg); preempt_disable(); cpu = smp_processor_id(); /* Invoke the CPU_STARTING notifier callbacks */ notify_cpu_starting(cpu); arch_cpu_pre_online(arg); /* Set the CPU in the cpu_online_mask */ set_cpu_online(cpu, true); /* Enable local interrupts now */ local_irq_enable(); wmb(); cpu_startup_entry(CPUHP_ONLINE); /* We should never reach here! */ BUG(); }
static void __cpuinit cpu_bringup(void) { int cpu; cpu_init(); touch_softlockup_watchdog(); preempt_disable(); /* PVH runs in ring 0 and allows us to do native syscalls. Yay! */ if (!xen_feature(XENFEAT_supervisor_mode_kernel)) { xen_enable_sysenter(); xen_enable_syscall(); } cpu = smp_processor_id(); smp_store_cpu_info(cpu); cpu_data(cpu).x86_max_cores = 1; set_cpu_sibling_map(cpu); xen_setup_cpu_clockevents(); notify_cpu_starting(cpu); set_cpu_online(cpu, true); this_cpu_write(cpu_state, CPU_ONLINE); wmb(); /* We can take interrupts now: we're officially "up". */ local_irq_enable(); wmb(); /* make sure everything is out */ }
/* * Bring a secondary processor online. */ void online_secondary(void) { /* * low-memory mappings have been cleared, flush them from * the local TLBs too. */ local_flush_tlb(); BUG_ON(in_interrupt()); /* This must be done before setting cpu_online_mask */ wmb(); notify_cpu_starting(smp_processor_id()); set_cpu_online(smp_processor_id(), 1); __this_cpu_write(cpu_state, CPU_ONLINE); /* Set up tile-specific state for this cpu. */ setup_cpu(0); /* Set up tile-timer clock-event device on this cpu */ setup_tile_timer(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); }
/* Activate a secondary processor. */ int __devinit start_secondary(void *unused) { unsigned int cpu = smp_processor_id(); struct device_node *l2_cache; int i, base; atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; smp_store_cpu_info(cpu); set_dec(tb_ticks_per_jiffy); preempt_disable(); cpu_callin_map[cpu] = 1; smp_ops->setup_cpu(cpu); if (smp_ops->take_timebase) smp_ops->take_timebase(); if (system_state > SYSTEM_BOOTING) snapshot_timebase(); secondary_cpu_time_init(); ipi_call_lock(); notify_cpu_starting(cpu); cpu_set(cpu, cpu_online_map); /* Update sibling maps */ base = cpu_first_thread_in_core(cpu); for (i = 0; i < threads_per_core; i++) { if (cpu_is_offline(base + i)) continue; cpu_set(cpu, per_cpu(cpu_sibling_map, base + i)); cpu_set(base + i, per_cpu(cpu_sibling_map, cpu)); /* cpu_core_map should be a superset of * cpu_sibling_map even if we don't have cache * information, so update the former here, too. */ cpu_set(cpu, per_cpu(cpu_core_map, base +i)); cpu_set(base + i, per_cpu(cpu_core_map, cpu)); } l2_cache = cpu_to_l2cache(cpu); for_each_online_cpu(i) { struct device_node *np = cpu_to_l2cache(i); if (!np) continue; if (np == l2_cache) { cpu_set(cpu, per_cpu(cpu_core_map, i)); cpu_set(i, per_cpu(cpu_core_map, cpu)); } of_node_put(np); } of_node_put(l2_cache); ipi_call_unlock(); local_irq_enable(); cpu_idle(); return 0; }
/* * Called by secondaries to update state and initialize CPU registers. */ static void __init smp_cpu_init(int cpunum) { extern int init_per_cpu(int); /* arch/parisc/kernel/processor.c */ extern void init_IRQ(void); /* arch/parisc/kernel/irq.c */ extern void start_cpu_itimer(void); /* arch/parisc/kernel/time.c */ /* Set modes and Enable floating point coprocessor */ (void) init_per_cpu(cpunum); disable_sr_hashing(); mb(); /* Well, support 2.4 linux scheme as well. */ if (cpu_online(cpunum)) { extern void machine_halt(void); /* arch/parisc.../process.c */ printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); machine_halt(); } notify_cpu_starting(cpunum); set_cpu_online(cpunum, true); /* Initialise the idle task for this CPU */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); init_IRQ(); /* make sure no IRQs are enabled or pending */ start_cpu_itimer(); }
asmlinkage void start_secondary(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; enable_mmu(); atomic_inc(&mm->mm_count); atomic_inc(&mm->mm_users); current->active_mm = mm; enter_lazy_tlb(mm, current); local_flush_tlb_all(); per_cpu_trap_init(); preempt_disable(); notify_cpu_starting(cpu); local_irq_enable(); /* Enable local timers */ local_timer_setup(cpu); calibrate_delay(); smp_store_cpu_info(cpu); set_cpu_online(cpu, true); per_cpu(cpu_state, cpu) = CPU_ONLINE; cpu_startup_entry(CPUHP_ONLINE); }
static void cpu_bringup(void) { int cpu; cpu_init(); touch_softlockup_watchdog(); preempt_disable(); /* PVH runs in ring 0 and allows us to do native syscalls. Yay! */ if (!xen_feature(XENFEAT_supervisor_mode_kernel)) { xen_enable_sysenter(); xen_enable_syscall(); } cpu = smp_processor_id(); smp_store_cpu_info(cpu); cpu_data(cpu).x86_max_cores = 1; set_cpu_sibling_map(cpu); speculative_store_bypass_ht_init(); xen_setup_cpu_clockevents(); notify_cpu_starting(cpu); set_cpu_online(cpu, true); cpu_set_state_online(cpu); /* Implies full memory barrier. */ /* We can take interrupts now: we're officially "up". */ local_irq_enable(); }
static void __cpuinit cpu_bringup(void) { int cpu; cpu_init(); touch_softlockup_watchdog(); preempt_disable(); xen_enable_sysenter(); xen_enable_syscall(); cpu = smp_processor_id(); smp_store_cpu_info(cpu); cpu_data(cpu).x86_max_cores = 1; set_cpu_sibling_map(cpu); xen_setup_cpu_clockevents(); notify_cpu_starting(cpu); ipi_call_lock(); set_cpu_online(cpu, true); ipi_call_unlock(); this_cpu_write(cpu_state, CPU_ONLINE); wmb(); local_irq_enable(); wmb(); }
/* * Activate a secondary processor. */ int __cpuinit start_secondary(void *cpuvoid) { /* Setup the cpu */ cpu_init(); preempt_disable(); /* Enable TOD clock interrupts on the secondary cpu. */ init_cpu_timer(); /* Enable cpu timer interrupts on the secondary cpu. */ init_cpu_vtimer(); /* Enable pfault pseudo page faults on this cpu. */ pfault_init(); /* call cpu notifiers */ notify_cpu_starting(smp_processor_id()); /* Mark this cpu as online */ ipi_call_lock(); set_cpu_online(smp_processor_id(), true); ipi_call_unlock(); __ctl_clear_bit(0, 28); /* Disable lowcore protection */ S390_lowcore.restart_psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA; S390_lowcore.restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler; __ctl_set_bit(0, 28); /* Enable lowcore protection */ local_irq_enable(); /* cpu_idle will call schedule for us */ cpu_idle(); return 0; }
asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); printk("CPU%u: Booted secondary processor\n", cpu); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); set_my_cpu_offset(per_cpu_offset(smp_processor_id())); cpu_set_reserved_ttbr0(); flush_tlb_all(); preempt_disable(); trace_hardirqs_off(); if (cpu_ops[cpu]->cpu_postboot) cpu_ops[cpu]->cpu_postboot(); set_cpu_online(cpu, true); complete(&cpu_running); smp_store_cpu_info(cpu); notify_cpu_starting(cpu); local_dbg_enable(); local_irq_enable(); local_fiq_enable(); cpu_startup_entry(CPUHP_ONLINE); }
/* * Activate a secondary processor. */ int __cpuinit start_secondary(void *cpuvoid) { cpu_init(); preempt_disable(); init_cpu_timer(); init_cpu_vtimer(); pfault_init(); notify_cpu_starting(smp_processor_id()); ipi_call_lock(); set_cpu_online(smp_processor_id(), true); ipi_call_unlock(); __ctl_clear_bit(0, 28); /* Disable lowcore protection */ S390_lowcore.restart_psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA; S390_lowcore.restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler; __ctl_set_bit(0, 28); /* Enable lowcore protection */ /* * Wait until the cpu which brought this one up marked it * active before enabling interrupts. */ while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask)) cpu_relax(); local_irq_enable(); /* cpu_idle will call schedule for us */ cpu_idle(); return 0; }
asmlinkage void start_secondary(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; enable_mmu(); mmgrab(mm); mmget(mm); current->active_mm = mm; #ifdef CONFIG_MMU enter_lazy_tlb(mm, current); local_flush_tlb_all(); #endif per_cpu_trap_init(); preempt_disable(); notify_cpu_starting(cpu); local_irq_enable(); calibrate_delay(); smp_store_cpu_info(cpu); set_cpu_online(cpu, true); per_cpu(cpu_state, cpu) = CPU_ONLINE; cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); }
/* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); set_my_cpu_offset(per_cpu_offset(smp_processor_id())); printk("CPU%u: Booted secondary processor\n", cpu); /* * TTBR0 is only used for the identity mapping at this stage. Make it * point to zero page to avoid speculatively fetching new entries. */ cpu_set_reserved_ttbr0(); flush_tlb_all(); preempt_disable(); trace_hardirqs_off(); if (cpu_ops[cpu]->cpu_postboot) cpu_ops[cpu]->cpu_postboot(); /* * Enable GIC and timers. */ smp_store_cpu_info(cpu); notify_cpu_starting(cpu); /* * OK, now it's safe to let the boot CPU continue. Wait for * the CPU migration code to notice that the CPU is online * before we continue. */ set_cpu_online(cpu, true); complete(&cpu_running); local_dbg_enable(); /* * Setup the percpu timer for this CPU. */ percpu_timer_setup(); local_irq_enable(); local_async_enable(); /* * OK, it's off to the idle thread for us */ cpu_startup_entry(CPUHP_ONLINE); }
/* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); printk("CPU%u: Booted secondary processor\n", cpu); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); /* * TTBR0 is only used for the identity mapping at this stage. Make it * point to zero page to avoid speculatively fetching new entries. */ cpu_set_reserved_ttbr0(); flush_tlb_all(); preempt_disable(); trace_hardirqs_off(); /* * Let the primary processor know we're out of the * pen, then head off into the C entry point */ write_pen_release(INVALID_HWID); /* * Synchronise with the boot thread. */ raw_spin_lock(&boot_lock); raw_spin_unlock(&boot_lock); /* * OK, now it's safe to let the boot CPU continue. Wait for * the CPU migration code to notice that the CPU is online * before we continue. */ set_cpu_online(cpu, true); complete(&cpu_running); /* * Enable GIC and timers. */ notify_cpu_starting(cpu); local_irq_enable(); local_fiq_enable(); /* * OK, it's off to the idle thread for us */ cpu_startup_entry(CPUHP_ONLINE); }
/* * Report back to the Boot Processor during boot time or to the caller processor * during CPU online. */ static void smp_callin(void) { int cpuid, phys_id; /* * If waken up by an INIT in an 82489DX configuration * cpu_callout_mask guarantees we don't get here before * an INIT_deassert IPI reaches our local APIC, so it is * now safe to touch our local APIC. */ cpuid = smp_processor_id(); /* * (This works even if the APIC is not enabled.) */ phys_id = read_apic_id(); /* * the boot CPU has finished the init stage and is spinning * on callin_map until we finish. We are free to set up this * CPU, first the APIC. (this is probably redundant on most * boards) */ apic_ap_setup(); /* * Save our processor parameters. Note: this information * is needed for clock calibration. */ smp_store_cpu_info(cpuid); /* * Get our bogomips. * Update loops_per_jiffy in cpu_data. Previous call to * smp_store_cpu_info() stored a value that is close but not as * accurate as the value just calculated. */ calibrate_delay(); cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy; pr_debug("Stack at about %p\n", &cpuid); /* * This must be done before setting cpu_online_mask * or calling notify_cpu_starting. */ set_cpu_sibling_map(raw_smp_processor_id()); wmb(); notify_cpu_starting(cpuid); /* * Allow the master to continue. */ cpumask_set_cpu(cpuid, cpu_callin_mask); }
/* Boot the current CPU */ void __cpuinit start_secondary(unsigned long boot_phys_offset, unsigned long fdt_paddr, unsigned long hwid) { unsigned int cpuid = init_data.cpuid; memset(get_cpu_info(), 0, sizeof (struct cpu_info)); set_processor_id(cpuid); current_cpu_data = boot_cpu_data; identify_cpu(¤t_cpu_data); init_traps(); setup_virt_paging(); mmu_init_secondary_cpu(); gic_init_secondary_cpu(); init_secondary_IRQ(); gic_route_ppis(); init_maintenance_interrupt(); init_timer_interrupt(); set_current(idle_vcpu[cpuid]); setup_cpu_sibling_map(cpuid); /* Run local notifiers */ notify_cpu_starting(cpuid); wmb(); /* Now report this CPU is up */ smp_up_cpu = MPIDR_INVALID; cpumask_set_cpu(cpuid, &cpu_online_map); wmb(); local_irq_enable(); local_abort_enable(); printk(XENLOG_DEBUG "CPU %u booted.\n", smp_processor_id()); startup_cpu_idle_loop(); }
void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); init_mmu(); #ifdef CONFIG_DEBUG_KERNEL if (boot_secondary_processors == 0) { pr_debug("%s: boot_secondary_processors:%d; Hanging cpu:%d\n", __func__, boot_secondary_processors, cpu); for (;;) __asm__ __volatile__ ("waiti " __stringify(LOCKLEVEL)); } pr_debug("%s: boot_secondary_processors:%d; Booting cpu:%d\n", __func__, boot_secondary_processors, cpu); #endif /* Init EXCSAVE1 */ secondary_trap_init(); /* All kernel threads share the same mm context. */ mmget(mm); mmgrab(mm); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); enter_lazy_tlb(mm, current); preempt_disable(); trace_hardirqs_off(); calibrate_delay(); notify_cpu_starting(cpu); secondary_init_irq(); local_timer_setup(cpu); set_cpu_online(cpu, true); local_irq_enable(); complete(&cpu_running); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); }
static void __init smp_online(void) { int cpu_id = smp_processor_id(); notify_cpu_starting(cpu_id); local_irq_enable(); /* Get our bogomips. */ calibrate_delay(); /* Save our processor parameters */ smp_store_cpu_info(cpu_id); set_cpu_online(cpu_id, true); }
/* Boot the current CPU */ void start_secondary(unsigned long boot_phys_offset, unsigned long fdt_paddr, unsigned long hwid) { unsigned int cpuid = init_data.cpuid; memset(get_cpu_info(), 0, sizeof (struct cpu_info)); set_processor_id(cpuid); identify_cpu(¤t_cpu_data); init_traps(); mmu_init_secondary_cpu(); gic_init_secondary_cpu(); init_secondary_IRQ(); init_maintenance_interrupt(); init_timer_interrupt(); set_current(idle_vcpu[cpuid]); setup_cpu_sibling_map(cpuid); /* Run local notifiers */ notify_cpu_starting(cpuid); /* * Ensure that previous writes are visible before marking the cpu as * online. */ smp_wmb(); /* Now report this CPU is up */ cpumask_set_cpu(cpuid, &cpu_online_map); local_irq_enable(); local_abort_enable(); check_local_cpu_errata(); printk(XENLOG_DEBUG "CPU %u booted.\n", smp_processor_id()); startup_cpu_idle_loop(); }
/* Boot the current CPU */ void __cpuinit start_secondary(unsigned long boot_phys_offset, unsigned long fdt_paddr, unsigned long cpuid) { struct cpuinfo_arm *c = cpu_data + cpuid; memset(get_cpu_info(), 0, sizeof (struct cpu_info)); /* TODO: handle boards where CPUIDs are not contiguous */ set_processor_id(cpuid); *c = boot_cpu_data; identify_cpu(c); /* Setup Hyp vector base */ WRITE_SYSREG((vaddr_t)hyp_traps_vector, VBAR_EL2); mmu_init_secondary_cpu(); enable_vfp(); gic_init_secondary_cpu(); init_secondary_IRQ(); gic_route_ppis(); init_maintenance_interrupt(); init_timer_interrupt(); set_current(idle_vcpu[cpuid]); setup_cpu_sibling_map(cpuid); /* Run local notifiers */ notify_cpu_starting(cpuid); wmb(); /* Now report this CPU is up */ cpumask_set_cpu(cpuid, &cpu_online_map); wmb(); local_irq_enable(); dprintk(XENLOG_DEBUG, "CPU %u booted.\n", smp_processor_id()); startup_cpu_idle_loop(); }
static int idle_proc(void *cpup) { int cpu = (int) cpup, err; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); if (err < 0) panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); os_set_fd_async(cpu_data[cpu].ipi_pipe[0]); wmb(); if (cpu_test_and_set(cpu, cpu_callin_map)) { printk(KERN_ERR "huh, CPU#%d already present??\n", cpu); BUG(); } while (!cpu_isset(cpu, smp_commenced_mask)) cpu_relax(); notify_cpu_starting(cpu); <<<<<<< HEAD
static void __cpuinit smp_callin (void) { int cpuid, phys_id, itc_master; struct cpuinfo_ia64 *last_cpuinfo, *this_cpuinfo; extern void ia64_init_itm(void); extern volatile int time_keeper_id; #ifdef CONFIG_PERFMON extern void pfm_init_percpu(void); #endif cpuid = smp_processor_id(); phys_id = hard_smp_processor_id(); itc_master = time_keeper_id; if (cpu_online(cpuid)) { printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", phys_id, cpuid); BUG(); } fix_b0_for_bsp(); /* * numa_node_id() works after this. */ set_numa_node(cpu_to_node_map[cpuid]); set_numa_mem(local_memory_node(cpu_to_node_map[cpuid])); ipi_call_lock_irq(); spin_lock(&vector_lock); /* Setup the per cpu irq handling data structures */ __setup_vector_irq(cpuid); notify_cpu_starting(cpuid); set_cpu_online(cpuid, true); per_cpu(cpu_state, cpuid) = CPU_ONLINE; spin_unlock(&vector_lock); ipi_call_unlock_irq(); smp_setup_percpu_timer(); ia64_mca_cmc_vector_setup(); /* Setup vector on AP */ #ifdef CONFIG_PERFMON pfm_init_percpu(); #endif local_irq_enable(); if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { /* * Synchronize the ITC with the BP. Need to do this after irqs are * enabled because ia64_sync_itc() calls smp_call_function_single(), which * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls * local_bh_enable(), which bugs out if irqs are not enabled... */ Dprintk("Going to syncup ITC with ITC Master.\n"); ia64_sync_itc(itc_master); } /* * Get our bogomips. */ ia64_init_itm(); /* * Delay calibration can be skipped if new processor is identical to the * previous processor. */ last_cpuinfo = cpu_data(cpuid - 1); this_cpuinfo = local_cpu_data; if (last_cpuinfo->itc_freq != this_cpuinfo->itc_freq || last_cpuinfo->proc_freq != this_cpuinfo->proc_freq || last_cpuinfo->features != this_cpuinfo->features || last_cpuinfo->revision != this_cpuinfo->revision || last_cpuinfo->family != this_cpuinfo->family || last_cpuinfo->archrev != this_cpuinfo->archrev || last_cpuinfo->model != this_cpuinfo->model) calibrate_delay(); local_cpu_data->loops_per_jiffy = loops_per_jiffy; /* * Allow the master to continue. */ cpu_set(cpuid, cpu_callin_map); Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid); }
/* Activate a secondary processor. */ int __devinit start_secondary(void *unused) { unsigned int cpu = smp_processor_id(); struct device_node *l2_cache; int i, base; atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; smp_store_cpu_info(cpu); #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) /* Clear any pending timer interrupts */ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); /* Enable decrementer interrupt */ mtspr(SPRN_TCR, TCR_DIE); #endif set_dec(tb_ticks_per_jiffy); preempt_disable(); cpu_callin_map[cpu] = 1; if (smp_ops->setup_cpu) smp_ops->setup_cpu(cpu); if (smp_ops->take_timebase) smp_ops->take_timebase(); if (system_state > SYSTEM_BOOTING) snapshot_timebase(); secondary_cpu_time_init(); ipi_call_lock(); notify_cpu_starting(cpu); set_cpu_online(cpu, true); /* Update sibling maps */ base = cpu_first_thread_in_core(cpu); for (i = 0; i < threads_per_core; i++) { if (cpu_is_offline(base + i)) continue; cpumask_set_cpu(cpu, cpu_sibling_mask(base + i)); cpumask_set_cpu(base + i, cpu_sibling_mask(cpu)); /* cpu_core_map should be a superset of * cpu_sibling_map even if we don't have cache * information, so update the former here, too. */ cpumask_set_cpu(cpu, cpu_core_mask(base + i)); cpumask_set_cpu(base + i, cpu_core_mask(cpu)); } l2_cache = cpu_to_l2cache(cpu); for_each_online_cpu(i) { struct device_node *np = cpu_to_l2cache(i); if (!np) continue; if (np == l2_cache) { cpumask_set_cpu(cpu, cpu_core_mask(i)); cpumask_set_cpu(i, cpu_core_mask(cpu)); } of_node_put(np); } of_node_put(l2_cache); ipi_call_unlock(); local_irq_enable(); cpu_idle(); return 0; }
static void __devinit smp_callin (void) { #ifdef XEN /* work around for spinlock irq assert. */ unsigned long flags; #endif int cpuid, phys_id; extern void ia64_init_itm(void); #ifdef CONFIG_PERFMON extern void pfm_init_percpu(void); #endif cpuid = smp_processor_id(); phys_id = hard_smp_processor_id(); if (cpu_online(cpuid)) { printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n", phys_id, cpuid); BUG(); } fix_b0_for_bsp(); #ifdef XEN notify_cpu_starting(cpuid); lock_ipi_calllock(&flags); #else lock_ipi_calllock(); #endif cpu_set(cpuid, cpu_online_map); #ifdef XEN unlock_ipi_calllock(flags); #else unlock_ipi_calllock(); #endif per_cpu(cpu_state, cpuid) = CPU_ONLINE; smp_setup_percpu_timer(); ia64_mca_cmc_vector_setup(); /* Setup vector on AP */ #ifdef CONFIG_PERFMON pfm_init_percpu(); #endif local_irq_enable(); if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { /* * Synchronize the ITC with the BP. Need to do this after irqs are * enabled because ia64_sync_itc() calls smp_call_function_single(), which * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls * local_bh_enable(), which bugs out if irqs are not enabled... */ Dprintk("Going to syncup ITC with BP.\n"); ia64_sync_itc(0); } /* * Get our bogomips. */ ia64_init_itm(); #ifndef XEN calibrate_delay(); #endif local_cpu_data->loops_per_jiffy = loops_per_jiffy; #ifdef CONFIG_IA32_SUPPORT ia32_gdt_init(); #endif /* * Allow the master to continue. */ cpu_set(cpuid, cpu_callin_map); Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid); }
/* Activate a secondary processor. */ __cpuinit void start_secondary(void *unused) { unsigned int cpu = smp_processor_id(); struct device_node *l2_cache; int i, base; atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; smp_store_cpu_info(cpu); set_dec(tb_ticks_per_jiffy); preempt_disable(); cpu_callin_map[cpu] = 1; if (smp_ops->setup_cpu) smp_ops->setup_cpu(cpu); if (smp_ops->take_timebase) smp_ops->take_timebase(); secondary_cpu_time_init(); #ifdef CONFIG_PPC64 if (system_state == SYSTEM_RUNNING) vdso_data->processorCount++; vdso_getcpu_init(); #endif notify_cpu_starting(cpu); set_cpu_online(cpu, true); /* Update sibling maps */ base = cpu_first_thread_sibling(cpu); for (i = 0; i < threads_per_core; i++) { if (cpu_is_offline(base + i)) continue; cpumask_set_cpu(cpu, cpu_sibling_mask(base + i)); cpumask_set_cpu(base + i, cpu_sibling_mask(cpu)); /* cpu_core_map should be a superset of * cpu_sibling_map even if we don't have cache * information, so update the former here, too. */ cpumask_set_cpu(cpu, cpu_core_mask(base + i)); cpumask_set_cpu(base + i, cpu_core_mask(cpu)); } l2_cache = cpu_to_l2cache(cpu); for_each_online_cpu(i) { struct device_node *np = cpu_to_l2cache(i); if (!np) continue; if (np == l2_cache) { cpumask_set_cpu(cpu, cpu_core_mask(i)); cpumask_set_cpu(i, cpu_core_mask(cpu)); } of_node_put(np); } of_node_put(l2_cache); local_irq_enable(); cpu_startup_entry(CPUHP_ONLINE); BUG(); }
/* * Report back to the Boot Processor during boot time or to the caller processor * during CPU online. */ static void smp_callin(void) { int cpuid, phys_id; /* * If waken up by an INIT in an 82489DX configuration * we may get here before an INIT-deassert IPI reaches * our local APIC. We have to wait for the IPI or we'll * lock up on an APIC access. * * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI. */ cpuid = smp_processor_id(); if (apic->wait_for_init_deassert && cpuid) while (!atomic_read(&init_deasserted)) cpu_relax(); /* * (This works even if the APIC is not enabled.) */ phys_id = read_apic_id(); /* * the boot CPU has finished the init stage and is spinning * on callin_map until we finish. We are free to set up this * CPU, first the APIC. (this is probably redundant on most * boards) */ pr_debug("CALLIN, before setup_local_APIC()\n"); if (apic->smp_callin_clear_local_apic) apic->smp_callin_clear_local_apic(); setup_local_APIC(); end_local_APIC_setup(); /* * Need to setup vector mappings before we enable interrupts. */ setup_vector_irq(smp_processor_id()); /* * Save our processor parameters. Note: this information * is needed for clock calibration. */ smp_store_cpu_info(cpuid); /* * Get our bogomips. * Update loops_per_jiffy in cpu_data. Previous call to * smp_store_cpu_info() stored a value that is close but not as * accurate as the value just calculated. */ calibrate_delay(); cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy; pr_debug("Stack at about %p\n", &cpuid); /* * This must be done before setting cpu_online_mask * or calling notify_cpu_starting. */ set_cpu_sibling_map(raw_smp_processor_id()); wmb(); notify_cpu_starting(cpuid); /* * Allow the master to continue. */ cpumask_set_cpu(cpuid, cpu_callin_mask); }
/* * Report back to the Boot Processor during boot time or to the caller processor * during CPU online. */ static void __cpuinit smp_callin(void) { int cpuid, phys_id; unsigned long timeout; /* * If waken up by an INIT in an 82489DX configuration * we may get here before an INIT-deassert IPI reaches * our local APIC. We have to wait for the IPI or we'll * lock up on an APIC access. * * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI. */ cpuid = smp_processor_id(); if (apic->wait_for_init_deassert && cpuid != 0) apic->wait_for_init_deassert(&init_deasserted); /* * (This works even if the APIC is not enabled.) */ phys_id = read_apic_id(); if (cpumask_test_cpu(cpuid, cpu_callin_mask)) { panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__, phys_id, cpuid); } pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); /* * STARTUP IPIs are fragile beasts as they might sometimes * trigger some glue motherboard logic. Complete APIC bus * silence for 1 second, this overestimates the time the * boot CPU is spending to send the up to 2 STARTUP IPIs * by a factor of two. This should be enough. */ /* * Waiting 2s total for startup (udelay is not yet working) */ timeout = jiffies + 2*HZ; while (time_before(jiffies, timeout)) { /* * Has the boot CPU finished it's STARTUP sequence? */ if (cpumask_test_cpu(cpuid, cpu_callout_mask)) break; cpu_relax(); } if (!time_before(jiffies, timeout)) { panic("%s: CPU%d started up but did not get a callout!\n", __func__, cpuid); } /* * the boot CPU has finished the init stage and is spinning * on callin_map until we finish. We are free to set up this * CPU, first the APIC. (this is probably redundant on most * boards) */ pr_debug("CALLIN, before setup_local_APIC()\n"); if (apic->smp_callin_clear_local_apic) apic->smp_callin_clear_local_apic(); setup_local_APIC(); end_local_APIC_setup(); /* * Need to setup vector mappings before we enable interrupts. */ setup_vector_irq(smp_processor_id()); /* * Save our processor parameters. Note: this information * is needed for clock calibration. */ smp_store_cpu_info(cpuid); /* * Get our bogomips. * Update loops_per_jiffy in cpu_data. Previous call to * smp_store_cpu_info() stored a value that is close but not as * accurate as the value just calculated. */ calibrate_delay(); cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy; pr_debug("Stack at about %p\n", &cpuid); /* * This must be done before setting cpu_online_mask * or calling notify_cpu_starting. */ set_cpu_sibling_map(raw_smp_processor_id()); wmb(); notify_cpu_starting(cpuid); /* * Allow the master to continue. */ cpumask_set_cpu(cpuid, cpu_callin_mask); }
/* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ atomic_inc(&mm->mm_count); current->active_mm = mm; set_my_cpu_offset(per_cpu_offset(smp_processor_id())); /* * TTBR0 is only used for the identity mapping at this stage. Make it * point to zero page to avoid speculatively fetching new entries. */ cpu_uninstall_idmap(); preempt_disable(); trace_hardirqs_off(); /* * If the system has established the capabilities, make sure * this CPU ticks all of those. If it doesn't, the CPU will * fail to come online. */ verify_local_cpu_capabilities(); if (cpu_ops[cpu]->cpu_postboot) cpu_ops[cpu]->cpu_postboot(); /* * Log the CPU info before it is marked online and might get read. */ cpuinfo_store_cpu(); /* * Enable GIC and timers. */ notify_cpu_starting(cpu); store_cpu_topology(cpu); /* * OK, now it's safe to let the boot CPU continue. Wait for * the CPU migration code to notice that the CPU is online * before we continue. */ pr_info("CPU%u: Booted secondary processor [%08x]\n", cpu, read_cpuid_id()); update_cpu_boot_status(CPU_BOOT_SUCCESS); set_cpu_online(cpu, true); complete(&cpu_running); local_irq_enable(); local_async_enable(); /* * OK, it's off to the idle thread for us */ cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); }