/* Tell the hardware to boot TP1 - runs on TP0 */
static void brcmstb_boot_secondary(int cpu, struct task_struct *idle)
{
	brcmstb_smp_boot_sp = __KSTK_TOS(idle);
	brcmstb_smp_boot_gp = (unsigned long)task_thread_info(idle);
	mb();

	/*
	 * TP1 initial boot sequence:
	 *   brcm_reset_nmi_vec @ a000_0000 ->
	 *   brcmstb_tp1_entry ->
	 *   brcm_upper_tlb_setup (cached function call) ->
	 *   start_secondary (cached jump)
	 *
	 * TP1 warm restart sequence:
	 *   play_dead WAIT loop ->
	 *   brcm_tp1_int_vec @ BRCM_WARM_RESTART_VEC ->
	 *   eret to play_dead ->
	 *   brcmstb_tp1_reentry ->
	 *   start_secondary
	 *
	 * Vector relocation code is in arch/mips/brcmstb/prom.c
	 * Actual boot vectors are in arch/mips/brcmstb/vector.S
	 */

	printk(KERN_INFO "SMP: Booting CPU%d...\n", cpu);

	/* warm restart */
	brcmstb_send_ipi_single(1, 0);

#if defined(CONFIG_BMIPS4380)
	set_c0_brcm_cmt_ctrl(0x01);
#elif defined(CONFIG_BMIPS5000)
	write_c0_brcm_action(0x9);
#endif
}
Example #2
0
/**
 * Firmware CPU startup hook
 *
 */
static int octeon_boot_secondary(int cpu, struct task_struct *idle)
{
	int count;

	pr_info("SMP: Booting CPU%02d (CoreId %2d)...\n", cpu,
		cpu_logical_map(cpu));

	octeon_processor_sp = __KSTK_TOS(idle);
	octeon_processor_gp = (unsigned long)(task_thread_info(idle));
	octeon_processor_boot = cpu_logical_map(cpu);
	mb();

	count = 10000;
	while (octeon_processor_sp && count) {
		/* Waiting for processor to get the SP and GP */
		udelay(1);
		count--;
	}
	if (count == 0) {
		pr_err("Secondary boot timeout\n");
		return -ETIMEDOUT;
	}

	return 0;
}
Example #3
0
/*
 * Launch a slave into smp_bootstrap().  It doesn't take an argument, and we
 * set sp to the kernel stack of the newly created idle process, gp to the proc
 * struct so that current_thread_info() will work.
 */
static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle)
{
	unsigned long gp = (unsigned long)task_thread_info(idle);
	unsigned long sp = __KSTK_TOS(idle);

	LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
		(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
		0, (void *) sp, (void *) gp);
}
Example #4
0
/*
 * Firmware CPU startup hook
 * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
 * It launches the next * available CPU and copies some information on the
 * stack so the first thing we do is throw away that stuff and load useful
 * values into the registers ...
 */
static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
{
	unsigned long gp = (unsigned long) task_thread_info(idle);
	unsigned long sp = __KSTK_TOS(idle);

	secondary_sp = sp;
	secondary_gp = gp;

	arch_spin_unlock(&launch_lock);
}
Example #5
0
/*
 * Setup the PC, SP, and GP of a secondary processor and start it
 * running!
 */
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
	int retval;

	retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
			       __KSTK_TOS(idle),
			       (unsigned long)task_thread_info(idle), 0);
	if (retval != 0)
		printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
}
Example #6
0
static void __cpuinit jzsoc_boot_secondary(int cpu, struct task_struct *idle)
{
	int err;
	unsigned long flags,ctrl;


	printk("jzsoc_boot_secondary start\n");
	local_irq_save(flags);

	/* set reset bit! */
	ctrl = get_smp_ctrl();
	ctrl |= (1 << cpu);
	set_smp_ctrl(ctrl);

	/* blast all cache before booting secondary cpu */
	blast_dcache_jz();
	blast_icache_jz();

	cpm_clear_bit(15,CPM_CLKGR1);
	cpm_pwc_enable(scpu_pwc);
	preempt_disable();
	preempt_enable_no_resched();

	/* clear reset bit! */
	ctrl = get_smp_ctrl();
	ctrl &= ~(1 << cpu);
	set_smp_ctrl(ctrl);
wait:
	if (!cpumask_test_cpu(cpu, cpu_ready))
		goto wait;
	pr_info("[SMP] Booting CPU%d ...\n", cpu);
//	pr_debug("[SMP] Booting CPU%d ...\n", cpu);
	err = cpu_boot(cpu_logical_map(cpu), __KSTK_TOS(idle),
			(unsigned long)task_thread_info(idle));
	if (err != 0)
		pr_err("start_cpu(%i) returned %i\n" , cpu, err);
	local_irq_restore(flags);
}
Example #7
0
static void paravirt_boot_secondary(int cpu, struct task_struct *idle)
{
	paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle);
	smp_wmb();
	paravirt_smp_sp[cpu] = __KSTK_TOS(idle);
}
Example #8
0
/*
 * Setup the PC, SP, and GP of a secondary processor and start it
 * running!
 */
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
    register unsigned long temp;
	volatile unsigned long *start_addr = (volatile unsigned long * ) 0x80000000;
	asmlinkage void kernel_entry(void);

	// Temp fix - CFE thinks 0x80000000 points to the Linux start addr but Linux overwrites it with
	// Tlb refill handler, set it to the real Linux start addr, once TP1 is booted to
	// Linux, it will overwrite it again with the Tlb refill handler:)
    printk("TP%d: prom_boot_secondary: Adjust CFE's idea of the Linux start addr...\n", smp_processor_id());
	*start_addr = (unsigned long) &kernel_entry;

    printk("TP%d: prom_boot_secondary: switching to blocking mode...\n", smp_processor_id());
    // disable non-blocking mode
    temp = read_c0_brcm_config_0();
    temp &= ~0x20000;
    write_c0_brcm_config_0(temp);
  
    // Configure the s/w interrupt that TP0 will use to kick TP1.  By default,
    // s/w interrupt 0 will be vectored to the TP that generated it, so we need
    // to set the interrupt routing bit to make it cross over to the other TP.
    // This is bit 15 (SIR) of CP0 Reg 22 Sel 1. We also want to make h/w IRQ 1
    // go to TP1. To do this, we need to set the appropriate bit in the h/w
    // interrupt crossover. To set the h/w interrupt crossover, we need to set 
    // a different bit in that same CP0 register.  The XIR bits (31:27) 
    // control h/w IRQ 4..0, respectively.
    printk("TP%d: prom_boot_secondary: adjustting s/w interrupt crossover\n", smp_processor_id());
    
    temp = read_c0_cmt_interrupt();
    temp |= 0x00018000;
    write_c0_cmt_interrupt(temp);

    printk("TP%d: prom_boot_secondary: c0 22,1=%lx\n", smp_processor_id(),temp);
    
	// first save the boot data...
    boot_config->func_addr = (unsigned long) smp_bootstrap;      // function 
    boot_config->sp        = (unsigned long) __KSTK_TOS(idle);    // sp
    boot_config->gp        = (unsigned long) idle->thread_info;   // gp
    boot_config->arg       = 0;
     
    printk("TP%d: prom_boot_secondary: Kick off 2nd CPU, and adjust TLB serialization...\n", smp_processor_id());
    temp = read_c0_cmt_control();

    temp |= 0x01;           // Takes second CPU	out of reset

	// The following flags can be adjusted to suit performance and debugging needs
    //temp |= (1<<4);           // TP0 priority
    //temp |= (1<<5);           // TP1 priority

    // adjust tlb serialization
    temp &= ~(0x0F << 16);   // mask off old tlb serialization thingie...
//    temp |= (0x06 << 16);   // adjust tlb serialization (only exception serialization)
//    temp |= (0x04 << 16);   // adjust tlb serialization (full serialization)
//    temp |= (0x00 << 16);   // adjust tlb serialization (no serialization)
//    temp |= (0x07 << 16);   // adjust tlb serialization (USE THIS!)
    temp |= (0x01 << 16);   // adjust tlb serialization (no serialization RECOMMENDED!)
    
	temp |= (0x01 << 31);	// Debug and profile TP1 thread

    printk("TP%d: prom_boot_secondary: cp0 22,2 => %08lx\n", smp_processor_id(), temp);
    write_c0_cmt_control(temp);
}