FreeBSD/sys/dev/hwpmc/hwpmc_amd.c
/*
 * Check if a given allocation is feasible.
 */
Check if a given allocation is feasible.
Check if a given allocation is feasible .
static int
amd_allocate_pmc(int cpu, int ri, struct pmc *pm,
    const struct pmc_op_pmcallocate *a)
{
	int i;
	uint32_t allowed_unitmask, caps, config, unitmask;
	enum pmc_event pe;
	const struct pmc_descr *pd;
	(void) cpu;
	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
	    ("[amd,%d] illegal CPU value %d", __LINE__, cpu));
	KASSERT(ri >= 0 && ri < AMD_NPMCS,
	    ("[amd,%d] illegal row index %d", __LINE__, ri));
	pd = &amd_pmcdesc[ri].pm_descr;
	if (pd->pd_class != a->pm_class)
		return EINVAL;
	caps = pm->pm_caps;
	PMCDBG2(MDP,ALL,1,"amd-allocate ri=%d caps=0x%x", ri, caps);
	if ((pd->pd_caps & caps) != caps)
		return EPERM;
	pe = a->pm_ev;
	config = allowed_unitmask = 0;
	for (i = 0; i < amd_event_codes_size; i++)
		if (amd_event_codes[i].pe_ev == pe) {
			config =
			    AMD_PMC_TO_EVENTMASK(amd_event_codes[i].pe_code);
			allowed_unitmask =
			    AMD_PMC_TO_UNITMASK(amd_event_codes[i].pe_mask);
			break;
		}
	if (i == amd_event_codes_size)
		return EINVAL;
	unitmask = a->pm_md.pm_amd.pm_amd_config & AMD_PMC_UNITMASK;
	if (unitmask & ~allowed_unitmask) 
		return EINVAL;
	if (unitmask && (caps & PMC_CAP_QUALIFIER))
		config |= unitmask;
	if (caps & PMC_CAP_THRESHOLD)
		config |= a->pm_md.pm_amd.pm_amd_config & AMD_PMC_COUNTERMASK;
	if (caps & PMC_CAP_USER)
		config |= AMD_PMC_USR;
	if (caps & PMC_CAP_SYSTEM)
		config |= AMD_PMC_OS;
	if ((caps & (PMC_CAP_USER|PMC_CAP_SYSTEM)) == 0)
		config |= (AMD_PMC_USR|AMD_PMC_OS);
	if (caps & PMC_CAP_EDGE)
		config |= AMD_PMC_EDGE;
	if (caps & PMC_CAP_INVERT)
		config |= AMD_PMC_INVERT;
	if (caps & PMC_CAP_INTERRUPT)
		config |= AMD_PMC_INT;
	pm->pm_md.pm_amd.pm_amd_evsel = config; 
	PMCDBG2(MDP,ALL,2,"amd-allocate ri=%d -> config=0x%x", ri, config);
	return 0;
}
static int amd_allocate_pmc ( int cpu , int ri , struct pmc * pm , const struct pmc_op_pmcallocate * a ) { int i ; uint32_t allowed_unitmask , caps , config , unitmask ; enum pmc_event pe ; const struct pmc_descr * pd ; ( void ) cpu ; KASSERT ( cpu >= 0 && cpu < pmc_cpu_max ( ) , ( " " , __LINE__ , cpu ) ) ; KASSERT ( ri >= 0 && ri < AMD_NPMCS , ( " " , __LINE__ , ri ) ) ; pd = & amd_pmcdesc [ ri ] . pm_descr ; if ( pd -> pd_class != a -> pm_class ) return EINVAL ; caps = pm -> pm_caps ; PMCDBG2 ( MDP , ALL , 1 , " " , ri , caps ) ; if ( ( pd -> pd_caps & caps ) != caps ) return EPERM ; pe = a -> pm_ev ; config = allowed_unitmask = 0 ; for ( i = 0 ; i < amd_event_codes_size ; i ++ ) if ( amd_event_codes [ i ] . pe_ev == pe ) { config = AMD_PMC_TO_EVENTMASK ( amd_event_codes [ i ] . pe_code ) ; allowed_unitmask = AMD_PMC_TO_UNITMASK ( amd_event_codes [ i ] . pe_mask ) ; break ; } if ( i == amd_event_codes_size ) return EINVAL ; unitmask = a -> pm_md . pm_amd . pm_amd_config & AMD_PMC_UNITMASK ; if ( unitmask & ~ allowed_unitmask ) return EINVAL ; if ( unitmask && ( caps & PMC_CAP_QUALIFIER ) ) config |= unitmask ; if ( caps & PMC_CAP_THRESHOLD ) config |= a -> pm_md . pm_amd . pm_amd_config & AMD_PMC_COUNTERMASK ; if ( caps & PMC_CAP_USER ) config |= AMD_PMC_USR ; if ( caps & PMC_CAP_SYSTEM ) config |= AMD_PMC_OS ; if ( ( caps & ( PMC_CAP_USER | PMC_CAP_SYSTEM ) ) == 0 ) config |= ( AMD_PMC_USR | AMD_PMC_OS ) ; if ( caps & PMC_CAP_EDGE ) config |= AMD_PMC_EDGE ; if ( caps & PMC_CAP_INVERT ) config |= AMD_PMC_INVERT ; if ( caps & PMC_CAP_INTERRUPT ) config |= AMD_PMC_INT ; pm -> pm_md . pm_amd . pm_amd_evsel = config ; PMCDBG2 ( MDP , ALL , 2 , " " , ri , config ) ; return 0 ; }
Check if a given allocation is feasible.
Check if a given allocation is feasible .
/* check class match */ /* map ev to the correct event mask code */ /* disallow reserved bits */ /* set at least one of the 'usr' or 'os' caps */ /* save config value */