/*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); }
/*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); }