arch/parisc/kernel/smp.c

Source file repositories/reference/linux-study-clean/arch/parisc/kernel/smp.c

File Facts

System
Linux kernel
Corpus path
arch/parisc/kernel/smp.c
Extension
.c
Size
11219 bytes
Lines
508
Domain
Architecture Layer
Bucket
arch/parisc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

* Do what start_kernel() and main() do for boot strap processor (aka monarch)
 */
void smp_callin(unsigned long pdce_proc)
{
	int slave_id = cpu_now_booting;

#ifdef CONFIG_64BIT
	WARN_ON(((unsigned long)(PAGE0->mem_pdc_hi) << 32
			| PAGE0->mem_pdc) != pdce_proc);
#endif

	smp_cpu_init(slave_id);

	flush_cache_all_local(); /* start with known state */
	flush_tlb_all_local(NULL);

	local_irq_enable();  /* Interrupts have been off until now */

	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);

	/* NOTREACHED */
	panic("smp_callin() AAAAaaaaahhhh....\n");
}

/*
 * Bring one cpu online.
 */
static int smp_boot_one_cpu(int cpuid, struct task_struct *idle)
{
	const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid);
	long timeout;

#ifdef CONFIG_HOTPLUG_CPU
	int i;

	/* reset irq statistics for this CPU */
	memset(&per_cpu(irq_stat, cpuid), 0, sizeof(irq_cpustat_t));
	for (i = 0; i < NR_IRQS; i++) {
		struct irq_desc *desc = irq_to_desc(i);

		if (desc && desc->kstat_irqs)
			*per_cpu_ptr(desc->kstat_irqs, cpuid) = (struct irqstat) { };
	}
#endif

	/* wait until last booting CPU has started. */
	while (cpu_now_booting)
		;

	/* Let _start know what logical CPU we're booting
	** (offset into init_tasks[],cpu_data[])
	*/
	cpu_now_booting = cpuid;

	/* 
	** boot strap code needs to know the task address since
	** it also contains the process stack.
	*/
	smp_init_current_idle_task = idle ;
	mb();

	printk(KERN_INFO "Releasing cpu %d now, hpa=%lx\n", cpuid, p->hpa);

	/*
	** This gets PDC to release the CPU from a very tight loop.
	**
	** From the PA-RISC 2.0 Firmware Architecture Reference Specification:
	** "The MEM_RENDEZ vector specifies the location of OS_RENDEZ which 
	** is executed after receiving the rendezvous signal (an interrupt to 
	** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the 
	** contents of memory are valid."
	*/
	gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, p->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(cpuid)) {
			/* Which implies Slave has started up */
			cpu_now_booting = 0;
			goto alive ;
		}
		udelay(100);
		barrier();
	}
	printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);

Annotation

Implementation Notes