/*ARGSUSED*/
static int
kcpc_cpu_setup(cpu_setup_t what, int cpuid, void *arg)
{
	pg_cmt_t	*chip_pg;
	int		active_cpus_cnt;

	if (what != CPU_ON)
		return (0);

	/*
	 * If any CPU-bound contexts exist, we don't need to invalidate
	 * anything, as no per-LWP contexts can coexist.
	 */
	if (kcpc_cpuctx)
		return (0);

	/*
	 * If this chip now has more than 1 active cpu, we must invalidate all
	 * contexts in the system.
	 */
	chip_pg = (pg_cmt_t *)pghw_find_pg(cpu[cpuid], PGHW_CHIP);
	if (chip_pg != NULL) {
		active_cpus_cnt = GROUP_SIZE(&chip_pg->cmt_cpus_actv);
		if (active_cpus_cnt > 1)
			kcpc_invalidate_all();
	}

	return (0);
}
Example #2
0
/*ARGSUSED1*/
static int
kcpc_open(dev_t *dev, int flags, int otyp, cred_t *cr)
{
	processorid_t	cpuid;
	int		error;

	ASSERT(pcbe_ops != NULL);

	if ((error = secpolicy_cpc_cpu(cr)) != 0)
		return (error);
	if (getminor(*dev) != KCPC_MINOR_SHARED)
		return (ENXIO);
	if ((cpuid = curthread->t_bind_cpu) == PBIND_NONE)
		return (EINVAL);
	if (cpuid > max_cpuid)
		return (EINVAL);

	rw_enter(&kcpc_cpuctx_lock, RW_WRITER);
	if (++kcpc_cpuctx == 1) {
		ASSERT(kcpc_cpumap == NULL);

		/*
		 * Bail out if DTrace is already using the counters.
		 */
		if (dtrace_cpc_in_use) {
			kcpc_cpuctx--;
			rw_exit(&kcpc_cpuctx_lock);
			return (EAGAIN);
		}
		kcpc_cpumap = kmem_zalloc(BT_SIZEOFMAP(max_cpuid + 1),
		    KM_SLEEP);
		/*
		 * When this device is open for processor-based contexts,
		 * no further lwp-based contexts can be created.
		 *
		 * Since this is the first open, ensure that all existing
		 * contexts are invalidated.
		 */
		kcpc_invalidate_all();
	} else if (BT_TEST(kcpc_cpumap, cpuid)) {
		kcpc_cpuctx--;
		rw_exit(&kcpc_cpuctx_lock);
		return (EAGAIN);
	} else if (kcpc_hw_cpu_hook(cpuid, kcpc_cpumap) != 0) {
		kcpc_cpuctx--;
		rw_exit(&kcpc_cpuctx_lock);
		return (EACCES);
	}
	BT_SET(kcpc_cpumap, cpuid);
	rw_exit(&kcpc_cpuctx_lock);

	*dev = makedevice(getmajor(*dev), (minor_t)cpuid);

	return (0);
}