Пример #1
0
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--;
	}
}
Пример #2
0
/*
 * 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;
}