static void __init do_boot_cpu (int sapicid) { struct task_struct *idle; int timeout, cpu; cpu = ++cpucount; /* * We can't use kernel_thread since we must avoid to * reschedule the child. */ if (fork_by_hand() < 0) panic("failed fork for CPU %d", cpu); /* * We remove it from the pidhash and the runqueue * once we got the process: */ idle = init_task.prev_task; if (!idle) panic("No idle process for CPU %d", cpu); task_set_cpu(idle, cpu); /* we schedule the first task manually */ ia64_cpu_to_sapicid[cpu] = sapicid; del_from_runqueue(idle); unhash_process(idle); init_tasks[cpu] = idle; Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); /* * Wait 10s total for the AP to start */ Dprintk("Waiting on callin_map ..."); for (timeout = 0; timeout < 100000; timeout++) { if (test_bit(cpu, &cpu_callin_map)) break; /* It has booted */ udelay(100); } Dprintk("\n"); if (test_bit(cpu, &cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ printk("CPU%d: ", cpu); /*print_cpu_info(&cpu_data[cpu]); */ printk("CPU has booted.\n"); } else { printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid); ia64_cpu_to_sapicid[cpu] = -1; cpucount--; } }
/* * Bring one cpu online. */ int __init smp_boot_one_cpu(int cpuid, int cpunum) { struct task_struct *idle; long timeout; /* * Create an idle task for this CPU. Note the address wed* give * to kernel_thread is irrelevant -- it's going to start * where OS_BOOT_RENDEVZ vector in SAL says to start. But * this gets all the other task-y sort of data structures set * up like we wish. We need to pull the just created idle task * off the run queue and stuff it into the init_tasks[] array. * Sheesh . . . */ idle = fork_by_hand(); if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); wake_up_forked_process(idle); init_idle(idle, cpunum); unhash_process(idle); idle->thread_info->cpu = cpunum; /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) */ cpu_now_booting = cpunum; /* ** boot strap code needs to know the task address since ** it also contains the process stack. */ smp_init_current_idle_task = idle ; mb(); /* ** This gets PDC to release the CPU from a very tight loop. ** See MEM_RENDEZ comments in head.S. */ __raw_writel(IRQ_OFFSET(TIMER_IRQ), cpu_data[cpunum].hpa); mb(); /* * OK, wait a bit for that CPU to finish staggering about. * Slave will set a bit when it reaches smp_cpu_init(). * Once the "monarch CPU" sees the bit change, it can move on. */ for (timeout = 0; timeout < 10000; timeout++) { if(cpu_online(cpunum)) { /* Which implies Slave has started up */ cpu_now_booting = 0; smp_init_current_idle_task = NULL; goto alive ; } udelay(100); barrier(); } put_task_struct(idle); idle = NULL; printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); return -1; alive: /* Remember the Slave data */ #if (kDEBUG>=100) printk(KERN_DEBUG "SMP: CPU:%d (num %d) came alive after %ld _us\n", cpuid, cpunum, timeout * 100); #endif /* kDEBUG */ #ifdef ENTRY_SYS_CPUS cpu_data[cpunum].state = STATE_RUNNING; #endif return 0; }