예제 #1
0
파일: subr_smp.c 프로젝트: AhmadTux/freebsd
static int
smp_topo_addleaf(struct cpu_group *parent, struct cpu_group *child, int share,
    int count, int flags, int start)
{
	char cpusetbuf[CPUSETBUFSIZ], cpusetbuf2[CPUSETBUFSIZ];
	cpuset_t mask;
	int i;

	CPU_ZERO(&mask);
	for (i = 0; i < count; i++, start++)
		CPU_SET(start, &mask);
	child->cg_parent = parent;
	child->cg_child = NULL;
	child->cg_children = 0;
	child->cg_level = share;
	child->cg_count = count;
	child->cg_flags = flags;
	child->cg_mask = mask;
	parent->cg_children++;
	for (; parent != NULL; parent = parent->cg_parent) {
		if (CPU_OVERLAP(&parent->cg_mask, &child->cg_mask))
			panic("Duplicate children in %p.  mask (%s) child (%s)",
			    parent,
			    cpusetobj_strprint(cpusetbuf, &parent->cg_mask),
			    cpusetobj_strprint(cpusetbuf2, &child->cg_mask));
		CPU_OR(&parent->cg_mask, &child->cg_mask);
		parent->cg_count += child->cg_count;
	}

	return (start);
}
예제 #2
0
파일: subr_smp.c 프로젝트: AhmadTux/freebsd
struct cpu_group *
smp_topo(void)
{
	char cpusetbuf[CPUSETBUFSIZ], cpusetbuf2[CPUSETBUFSIZ];
	struct cpu_group *top;

	/*
	 * Check for a fake topology request for debugging purposes.
	 */
	switch (smp_topology) {
	case 1:
		/* Dual core with no sharing.  */
		top = smp_topo_1level(CG_SHARE_NONE, 2, 0);
		break;
	case 2:
		/* No topology, all cpus are equal. */
		top = smp_topo_none();
		break;
	case 3:
		/* Dual core with shared L2.  */
		top = smp_topo_1level(CG_SHARE_L2, 2, 0);
		break;
	case 4:
		/* quad core, shared l3 among each package, private l2.  */
		top = smp_topo_1level(CG_SHARE_L3, 4, 0);
		break;
	case 5:
		/* quad core,  2 dualcore parts on each package share l2.  */
		top = smp_topo_2level(CG_SHARE_NONE, 2, CG_SHARE_L2, 2, 0);
		break;
	case 6:
		/* Single-core 2xHTT */
		top = smp_topo_1level(CG_SHARE_L1, 2, CG_FLAG_HTT);
		break;
	case 7:
		/* quad core with a shared l3, 8 threads sharing L2.  */
		top = smp_topo_2level(CG_SHARE_L3, 4, CG_SHARE_L2, 8,
		    CG_FLAG_SMT);
		break;
	default:
		/* Default, ask the system what it wants. */
		top = cpu_topo();
		break;
	}
	/*
	 * Verify the returned topology.
	 */
	if (top->cg_count != mp_ncpus)
		panic("Built bad topology at %p.  CPU count %d != %d",
		    top, top->cg_count, mp_ncpus);
	if (CPU_CMP(&top->cg_mask, &all_cpus))
		panic("Built bad topology at %p.  CPU mask (%s) != (%s)",
		    top, cpusetobj_strprint(cpusetbuf, &top->cg_mask),
		    cpusetobj_strprint(cpusetbuf2, &all_cpus));
	return (top);
}
예제 #3
0
파일: subr_smp.c 프로젝트: vkhromov/freebsd
/*
 * When called the executing CPU will send an IPI to all other CPUs
 *  requesting that they halt execution.
 *
 * Usually (but not necessarily) called with 'other_cpus' as its arg.
 *
 *  - Signals all CPUs in map to stop.
 *  - Waits for each to stop.
 *
 * Returns:
 *  -1: error
 *   0: NA
 *   1: ok
 *
 */
static int
generic_stop_cpus(cpuset_t map, u_int type)
{
#ifdef KTR
	char cpusetbuf[CPUSETBUFSIZ];
#endif
	static volatile u_int stopping_cpu = NOCPU;
	int i;
	volatile cpuset_t *cpus;

	KASSERT(
#if defined(__amd64__) || defined(__i386__)
	    type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
#else
	    type == IPI_STOP || type == IPI_STOP_HARD,
#endif
	    ("%s: invalid stop type", __func__));

	if (!smp_started)
		return (0);

	CTR2(KTR_SMP, "stop_cpus(%s) with %u type",
	    cpusetobj_strprint(cpusetbuf, &map), type);

	if (stopping_cpu != PCPU_GET(cpuid))
		while (atomic_cmpset_int(&stopping_cpu, NOCPU,
		    PCPU_GET(cpuid)) == 0)
			while (stopping_cpu != NOCPU)
				cpu_spinwait(); /* spin */

	/* send the stop IPI to all CPUs in map */
	ipi_selected(map, type);

#if defined(__amd64__) || defined(__i386__)
	if (type == IPI_SUSPEND)
		cpus = &suspended_cpus;
	else
#endif
		cpus = &stopped_cpus;

	i = 0;
	while (!CPU_SUBSET(cpus, &map)) {
		/* spin */
		cpu_spinwait();
		i++;
		if (i == 100000000) {
			printf("timeout stopping cpus\n");
			break;
		}
	}

	stopping_cpu = NOCPU;
	return (1);
}
예제 #4
0
static int
sysctl_debug_ktr_cpumask(SYSCTL_HANDLER_ARGS)
{
    char lktr_cpumask_str[CPUSETBUFSIZ];
    cpuset_t imask;
    int error;

    cpusetobj_strprint(lktr_cpumask_str, &ktr_cpumask);
    error = sysctl_handle_string(oidp, lktr_cpumask_str,
                                 sizeof(lktr_cpumask_str), req);
    if (error != 0 || req->newptr == NULL)
        return (error);
    if (cpusetobj_strscan(&imask, lktr_cpumask_str) == -1)
        return (EINVAL);
    CPU_COPY(&imask, &ktr_cpumask);

    return (error);
}
예제 #5
0
파일: subr_smp.c 프로젝트: AhmadTux/freebsd
/*
 * Called by a CPU to restart stopped CPUs. 
 *
 * Usually (but not necessarily) called with 'stopped_cpus' as its arg.
 *
 *  - Signals all CPUs in map to restart.
 *  - Waits for each to restart.
 *
 * Returns:
 *  -1: error
 *   0: NA
 *   1: ok
 */
int
restart_cpus(cpuset_t map)
{
#ifdef KTR
	char cpusetbuf[CPUSETBUFSIZ];
#endif

	if (!smp_started)
		return 0;

	CTR1(KTR_SMP, "restart_cpus(%s)", cpusetobj_strprint(cpusetbuf, &map));

	/* signal other cpus to restart */
	CPU_COPY_STORE_REL(&map, &started_cpus);

	/* wait for each to clear its bit */
	while (CPU_OVERLAP(&stopped_cpus, &map))
		cpu_spinwait();

	return 1;
}
예제 #6
0
/*
 * Called by a CPU to restart stopped CPUs. 
 *
 * Usually (but not necessarily) called with 'stopped_cpus' as its arg.
 *
 *  - Signals all CPUs in map to restart.
 *  - Waits for each to restart.
 *
 * Returns:
 *  -1: error
 *   0: NA
 *   1: ok
 */
static int
generic_restart_cpus(cpuset_t map, u_int type)
{
#ifdef KTR
	char cpusetbuf[CPUSETBUFSIZ];
#endif
	volatile cpuset_t *cpus;

	KASSERT(
#if defined(__amd64__) || defined(__i386__)
	    type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
#else
	    type == IPI_STOP || type == IPI_STOP_HARD,
#endif
	    ("%s: invalid stop type", __func__));

	if (!smp_started)
		return 0;

	CTR1(KTR_SMP, "restart_cpus(%s)", cpusetobj_strprint(cpusetbuf, &map));

#if defined(__amd64__) || defined(__i386__)
	if (type == IPI_SUSPEND)
		cpus = &suspended_cpus;
	else
#endif
		cpus = &stopped_cpus;

	/* signal other cpus to restart */
	CPU_COPY_STORE_REL(&map, &started_cpus);

	/* wait for each to clear its bit */
	while (CPU_OVERLAP(cpus, &map))
		cpu_spinwait();

	return 1;
}
예제 #7
0
/*
 * When called the executing CPU will send an IPI to all other CPUs
 *  requesting that they halt execution.
 *
 * Usually (but not necessarily) called with 'other_cpus' as its arg.
 *
 *  - Signals all CPUs in map to stop.
 *  - Waits for each to stop.
 *
 * Returns:
 *  -1: error
 *   0: NA
 *   1: ok
 *
 */
static int
generic_stop_cpus(cpuset_t map, u_int type)
{
#ifdef KTR
	char cpusetbuf[CPUSETBUFSIZ];
#endif
	static volatile u_int stopping_cpu = NOCPU;
	int i;
	volatile cpuset_t *cpus;

	KASSERT(
#if defined(__amd64__) || defined(__i386__)
	    type == IPI_STOP || type == IPI_STOP_HARD || type == IPI_SUSPEND,
#else
	    type == IPI_STOP || type == IPI_STOP_HARD,
#endif
	    ("%s: invalid stop type", __func__));

	if (!smp_started)
		return (0);

	CTR2(KTR_SMP, "stop_cpus(%s) with %u type",
	    cpusetobj_strprint(cpusetbuf, &map), type);

#if defined(__amd64__) || defined(__i386__)
	/*
	 * When suspending, ensure there are are no IPIs in progress.
	 * IPIs that have been issued, but not yet delivered (e.g.
	 * not pending on a vCPU when running under virtualization)
	 * will be lost, violating FreeBSD's assumption of reliable
	 * IPI delivery.
	 */
	if (type == IPI_SUSPEND)
		mtx_lock_spin(&smp_ipi_mtx);
#endif

	if (stopping_cpu != PCPU_GET(cpuid))
		while (atomic_cmpset_int(&stopping_cpu, NOCPU,
		    PCPU_GET(cpuid)) == 0)
			while (stopping_cpu != NOCPU)
				cpu_spinwait(); /* spin */

	/* send the stop IPI to all CPUs in map */
	ipi_selected(map, type);

#if defined(__amd64__) || defined(__i386__)
	if (type == IPI_SUSPEND)
		cpus = &suspended_cpus;
	else
#endif
		cpus = &stopped_cpus;

	i = 0;
	while (!CPU_SUBSET(cpus, &map)) {
		/* spin */
		cpu_spinwait();
		i++;
		if (i == 100000000) {
			printf("timeout stopping cpus\n");
			break;
		}
	}

#if defined(__amd64__) || defined(__i386__)
	if (type == IPI_SUSPEND)
		mtx_unlock_spin(&smp_ipi_mtx);
#endif

	stopping_cpu = NOCPU;
	return (1);
}