| 
					
				 | 
			
			
				@@ -307,3 +307,196 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	hwpcb->ksp = (unsigned long)ipcb + sizeof(union thread_union) - 16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	hwpcb->usp = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	hwpcb->ptbr = ipcb->ptbr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwpcb->pcc = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwpcb->asn = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwpcb->unique = virt_to_phys(ipcb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwpcb->flags = ipcb->flags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwpcb->res1 = hwpcb->res2 = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	      hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	      cpuid, idle->state, ipcb->flags)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Setup HWRPB fields that SRM uses to activate secondary CPU */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwrpb->CPU_restart = __smp_callin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwrpb->CPU_restart_data = (unsigned long) __smp_callin; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Recalculate and update the HWRPB checksum */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	hwrpb_update_checksum(hwrpb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Send a "start" command to the specified processor. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* SRM III 3.4.1.3 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	cpu->flags |= 0x22;	/* turn on Context Valid and Restart Capable */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	cpu->flags &= ~1;	/* turn off Bootstrap In Progress */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	wmb(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	send_secondary_console_msg("START\r\n", cpuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Wait 10 seconds for an ACK from the console.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	timeout = jiffies + 10*HZ; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	while (time_before(jiffies, timeout)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (cpu->flags & 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			goto started; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		udelay(10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		barrier(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ started: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Bring one cpu online. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int __cpuinit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+smp_boot_one_cpu(int cpuid, struct task_struct *idle) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long timeout; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Signal the secondary to wait a moment.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	smp_secondary_alive = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Whirrr, whirrr, whirrrrrrrrr... */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (secondary_cpu_start(cpuid, idle)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Notify the secondary CPU it can run calibrate_delay.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mb(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	smp_secondary_alive = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* We've been acked by the console; wait one second for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	   the task to start up for real.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	timeout = jiffies + 1*HZ; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	while (time_before(jiffies, timeout)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (smp_secondary_alive == 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			goto alive; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		udelay(10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		barrier(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* We failed to boot the CPU.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ alive: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Another "Red Snapper". */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Called from setup_arch.  Detect an SMP system and which processors 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * are present. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void __init 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+setup_smp(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct percpu_struct *cpubase, *cpu; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (boot_cpuid != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		       boot_cpuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (hwrpb->nr_processors > 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		int boot_cpu_palrev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DBGS(("setup_smp: nr_processors %ld\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		      hwrpb->nr_processors)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		cpubase = (struct percpu_struct *) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			((char*)hwrpb + hwrpb->processor_offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		boot_cpu_palrev = cpubase->pal_revision; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for (i = 0; i < hwrpb->nr_processors; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			cpu = (struct percpu_struct *) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				((char *)cpubase + i*hwrpb->processor_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ((cpu->flags & 0x1cc) == 0x1cc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				smp_num_probed++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				set_cpu_possible(i, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				set_cpu_present(i, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				cpu->pal_revision = boot_cpu_palrev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			      i, cpu->flags, cpu->type)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			      i, cpu->pal_revision)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		smp_num_probed = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       smp_num_probed, cpumask_bits(cpu_present_mask)[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Called by smp_init prepare the secondaries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void __init 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+smp_prepare_cpus(unsigned int max_cpus) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Take care of some initial bookkeeping.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	memset(ipi_data, 0, sizeof(ipi_data)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	current_thread_info()->cpu = boot_cpuid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	smp_store_cpu_info(boot_cpuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	smp_setup_percpu_timer(boot_cpuid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Nothing to do on a UP box, or when told not to.  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (smp_num_probed == 1 || max_cpus == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		init_cpu_possible(cpumask_of(boot_cpuid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		init_cpu_present(cpumask_of(boot_cpuid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		printk(KERN_INFO "SMP mode deactivated.\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	printk(KERN_INFO "SMP starting up secondaries.\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	smp_num_cpus = smp_num_probed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+smp_prepare_boot_cpu(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int __cpuinit 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+__cpu_up(unsigned int cpu, struct task_struct *tidle) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	smp_boot_one_cpu(cpu, tidle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return cpu_online(cpu) ? 0 : -ENOSYS; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void __init 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+smp_cpus_done(unsigned int max_cpus) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int cpu; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	unsigned long bogosum = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for(cpu = 0; cpu < NR_CPUS; cpu++)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (cpu_online(cpu)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			bogosum += cpu_data[cpu].loops_per_jiffy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	printk(KERN_INFO "SMP: Total of %d processors activated " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       "(%lu.%02lu BogoMIPS).\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       num_online_cpus(),  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       (bogosum + 2500) / (500000/HZ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       ((bogosum + 2500) / (5000/HZ)) % 100); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void 
			 |