Ejemplo n.º 1
0
void smp_release_cpus(void)
{
	unsigned long *ptr;
	int i;

	if (!use_spinloop())
		return;

	DBG(" -> smp_release_cpus()\n");

	/* All secondary cpus are spinning on a common spinloop, release them
	 * all now so they can start to spin on their individual paca
	 * spinloops. For non SMP kernels, the secondary cpus never get out
	 * of the common spinloop.
	 */

	ptr  = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
			- PHYSICAL_START);
	*ptr = ppc_function_entry(generic_secondary_smp_init);

	/* And wait a bit for them to catch up */
	for (i = 0; i < 100000; i++) {
		mb();
		HMT_low();
		if (spinning_secondaries == 0)
			break;
		udelay(1);
	}
	DBG("spinning_secondaries = %d\n", spinning_secondaries);

	DBG(" <- smp_release_cpus()\n");
}
Ejemplo n.º 2
0
Archivo: smp.c Proyecto: 1800alex/linux
/**
 * smp_startup_cpu() - start the given cpu
 *
 * At boot time, there is nothing to do for primary threads which were
 * started from Open Firmware.  For anything else, call RTAS with the
 * appropriate start location.
 *
 * Returns:
 *	0	- failure
 *	1	- success
 */
static inline int smp_startup_cpu(unsigned int lcpu)
{
	int status;
	unsigned long start_here =
			__pa(ppc_function_entry(generic_secondary_smp_init));
	unsigned int pcpu;
	int start_cpu;

	if (cpumask_test_cpu(lcpu, &of_spin_map))
		/* Already started by OF and sitting in spin loop */
		return 1;

	pcpu = get_hard_smp_processor_id(lcpu);

	/* Fixup atomic count: it exited inside IRQ handler. */
	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;

	/*
	 * If the RTAS start-cpu token does not exist then presume the
	 * cpu is already spinning.
	 */
	start_cpu = rtas_token("start-cpu");
	if (start_cpu == RTAS_UNKNOWN_SERVICE)
		return 1;

	status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
	if (status != 0) {
		printk(KERN_ERR "start-cpu failed: %i\n", status);
		return 0;
	}

	return 1;
}
Ejemplo n.º 3
0
static unsigned int
ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
{
	unsigned int op;

	addr = ppc_function_entry((void *)addr);

	/* if (link) set op to 'bl' else 'b' */
	op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);

	return op;
}
Ejemplo n.º 4
0
Archivo: smp.c Proyecto: 168519/linux
/**
 * smp_startup_cpu() - start the given cpu
 *
 * At boot time, there is nothing to do for primary threads which were
 * started from Open Firmware.  For anything else, call RTAS with the
 * appropriate start location.
 *
 * Returns:
 *	0	- failure
 *	1	- success
 */
static inline int smp_startup_cpu(unsigned int lcpu)
{
	int status;
	unsigned long start_here =
			__pa(ppc_function_entry(generic_secondary_smp_init));
	unsigned int pcpu;
	int start_cpu;

	if (cpumask_test_cpu(lcpu, of_spin_mask))
		/* Already started by OF and sitting in spin loop */
		return 1;

	pcpu = get_hard_smp_processor_id(lcpu);

	/* Check to see if the CPU out of FW already for kexec */
	if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){
		cpumask_set_cpu(lcpu, of_spin_mask);
		return 1;
	}

	/* Fixup atomic count: it exited inside IRQ handler. */
	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;
#ifdef CONFIG_HOTPLUG_CPU
	if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE)
		goto out;
#endif
	/* 
	 * If the RTAS start-cpu token does not exist then presume the
	 * cpu is already spinning.
	 */
	start_cpu = rtas_token("start-cpu");
	if (start_cpu == RTAS_UNKNOWN_SERVICE)
		return 1;

	status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, pcpu);
	if (status != 0) {
		printk(KERN_ERR "start-cpu failed: %i\n", status);
		return 0;
	}

#ifdef CONFIG_HOTPLUG_CPU
out:
#endif
	return 1;
}
Ejemplo n.º 5
0
int pnv_smp_kick_cpu(int nr)
{
	unsigned int pcpu = get_hard_smp_processor_id(nr);
	unsigned long start_here =
			__pa(ppc_function_entry(generic_secondary_smp_init));
	long rc;

	BUG_ON(nr < 0 || nr >= NR_CPUS);

	/*
	 * If we already started or OPALv2 is not supported, we just
	 * kick the CPU via the PACA
	 */
	if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2))
		goto kick;

	/*
	 * At this point, the CPU can either be spinning on the way in
	 * from kexec or be inside OPAL waiting to be started for the
	 * first time. OPAL v3 allows us to query OPAL to know if it
	 * has the CPUs, so we do that
	 */
	if (firmware_has_feature(FW_FEATURE_OPALv3)) {
		uint8_t status;

		rc = opal_query_cpu_status(pcpu, &status);
		if (rc != OPAL_SUCCESS) {
			pr_warn("OPAL Error %ld querying CPU %d state\n",
				rc, nr);
			return -ENODEV;
		}

		/*
		 * Already started, just kick it, probably coming from
		 * kexec and spinning
		 */
		if (status == OPAL_THREAD_STARTED)
			goto kick;

		/*
		 * Available/inactive, let's kick it
		 */
		if (status == OPAL_THREAD_INACTIVE) {
			pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n",
				 nr, pcpu);
			rc = opal_start_cpu(pcpu, start_here);
			if (rc != OPAL_SUCCESS) {
				pr_warn("OPAL Error %ld starting CPU %d\n",
					rc, nr);
				return -ENODEV;
			}
		} else {
			/*
			 * An unavailable CPU (or any other unknown status)
			 * shouldn't be started. It should also
			 * not be in the possible map but currently it can
			 * happen
			 */
			pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable"
				 " (status %d)...\n", nr, pcpu, status);
			return -ENODEV;
		}
	} else {
		/*
		 * On OPAL v2, we just kick it and hope for the best,
		 * we must not test the error from opal_start_cpu() or
		 * we would fail to get CPUs from kexec.
		 */
		opal_start_cpu(pcpu, start_here);
	}
 kick:
	return smp_generic_kick_cpu(nr);
}