Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/hwpmc/hwpmc_armv7.c
Show First 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | armv7_read_pmc(int cpu, int ri, pmc_value_t *v) | ||||
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), | KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), | ||||
("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); | ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); | ||||
KASSERT(ri >= 0 && ri < armv7_npmcs, | KASSERT(ri >= 0 && ri < armv7_npmcs, | ||||
("[armv7,%d] illegal row index %d", __LINE__, ri)); | ("[armv7,%d] illegal row index %d", __LINE__, ri)); | ||||
pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; | pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; | ||||
if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) | if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) | ||||
tmp = cp15_pmccntr_get(); | tmp = (uint32_t)cp15_pmccntr_get(); | ||||
else | else | ||||
tmp = armv7_pmcn_read(ri); | tmp = armv7_pmcn_read(ri); | ||||
tmp += 0x100000000llu * pm->pm_overflowcnt; | |||||
PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp); | PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp); | ||||
if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) | if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) | ||||
*v = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); | *v = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); | ||||
else | else | ||||
*v = tmp; | *v = tmp; | ||||
return 0; | return 0; | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | armv7_start_pmc(int cpu, int ri) | ||||
struct pmc_hw *phw; | struct pmc_hw *phw; | ||||
uint32_t config; | uint32_t config; | ||||
struct pmc *pm; | struct pmc *pm; | ||||
phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; | phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; | ||||
pm = phw->phw_pmc; | pm = phw->phw_pmc; | ||||
config = pm->pm_md.pm_armv7.pm_armv7_evsel; | config = pm->pm_md.pm_armv7.pm_armv7_evsel; | ||||
pm->pm_overflowcnt = 0; | |||||
/* | /* | ||||
* Configure the event selection. | * Configure the event selection. | ||||
*/ | */ | ||||
if (config != 0xFF) { | |||||
cp15_pmselr_set(ri); | cp15_pmselr_set(ri); | ||||
cp15_pmxevtyper_set(config); | cp15_pmxevtyper_set(config); | ||||
} else | |||||
ri = 31; | |||||
/* | /* | ||||
* Enable the PMC. | * Enable the PMC. | ||||
*/ | */ | ||||
armv7_interrupt_enable(ri); | armv7_interrupt_enable(ri); | ||||
armv7_counter_enable(ri); | armv7_counter_enable(ri); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
armv7_stop_pmc(int cpu, int ri) | armv7_stop_pmc(int cpu, int ri) | ||||
{ | { | ||||
struct pmc_hw *phw; | struct pmc_hw *phw; | ||||
struct pmc *pm; | struct pmc *pm; | ||||
uint32_t config; | |||||
phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; | phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; | ||||
pm = phw->phw_pmc; | pm = phw->phw_pmc; | ||||
config = pm->pm_md.pm_armv7.pm_armv7_evsel; | |||||
if (config == 0xFF) | |||||
ri = 31; | |||||
/* | /* | ||||
* Disable the PMCs. | * Disable the PMCs. | ||||
*/ | */ | ||||
armv7_counter_disable(ri); | armv7_counter_disable(ri); | ||||
armv7_interrupt_disable(ri); | armv7_interrupt_disable(ri); | ||||
return 0; | return 0; | ||||
Show All 30 Lines | armv7_intr(int cpu, struct trapframe *tf) | ||||
retval = 0; | retval = 0; | ||||
pc = armv7_pcpu[cpu]; | pc = armv7_pcpu[cpu]; | ||||
for (ri = 0; ri < armv7_npmcs; ri++) { | for (ri = 0; ri < armv7_npmcs; ri++) { | ||||
pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; | pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; | ||||
if (pm == NULL) | if (pm == NULL) | ||||
continue; | continue; | ||||
if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) | |||||
continue; | |||||
/* Check if counter has overflowed */ | /* Check if counter has overflowed */ | ||||
if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) | if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) | ||||
reg = (1 << 31); | reg = (1 << 31); | ||||
else | else | ||||
reg = (1 << ri); | reg = (1 << ri); | ||||
if ((cp15_pmovsr_get() & reg) == 0) { | if ((cp15_pmovsr_get() & reg) == 0) { | ||||
continue; | continue; | ||||
} | } | ||||
/* Clear Overflow Flag */ | /* Clear Overflow Flag */ | ||||
cp15_pmovsr_set(reg); | cp15_pmovsr_set(reg); | ||||
retval = 1; /* Found an interrupting PMC. */ | retval = 1; /* Found an interrupting PMC. */ | ||||
if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { | |||||
pm->pm_overflowcnt += 1; | |||||
continue; | |||||
} | |||||
if (pm->pm_state != PMC_STATE_RUNNING) | if (pm->pm_state != PMC_STATE_RUNNING) | ||||
continue; | continue; | ||||
error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, | error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, | ||||
TRAPF_USERMODE(tf)); | TRAPF_USERMODE(tf)); | ||||
if (error) | if (error) | ||||
armv7_stop_pmc(cpu, ri); | armv7_stop_pmc(cpu, ri); | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | armv7_pcpu_init(struct pmc_mdep *md, int cpu) | ||||
for (i = 0, phw = pac->pc_armv7pmcs; i < armv7_npmcs; i++, phw++) { | for (i = 0, phw = pac->pc_armv7pmcs; i < armv7_npmcs; i++, phw++) { | ||||
phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | | phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | | ||||
PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); | PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); | ||||
phw->phw_pmc = NULL; | phw->phw_pmc = NULL; | ||||
pc->pc_hwpmcs[i + first_ri] = phw; | pc->pc_hwpmcs[i + first_ri] = phw; | ||||
} | } | ||||
pmnc = 0xffffffff; | |||||
cp15_pmcnten_clr(pmnc); | |||||
cp15_pminten_clr(pmnc); | |||||
cp15_pmovsr_set(pmnc); | |||||
/* Enable unit */ | /* Enable unit */ | ||||
pmnc = cp15_pmcr_get(); | pmnc = cp15_pmcr_get(); | ||||
pmnc |= ARMV7_PMNC_ENABLE; | pmnc |= ARMV7_PMNC_ENABLE; | ||||
cp15_pmcr_set(pmnc); | cp15_pmcr_set(pmnc); | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
armv7_pcpu_fini(struct pmc_mdep *md, int cpu) | armv7_pcpu_fini(struct pmc_mdep *md, int cpu) | ||||
{ | { | ||||
uint32_t pmnc; | uint32_t pmnc; | ||||
pmnc = cp15_pmcr_get(); | pmnc = cp15_pmcr_get(); | ||||
pmnc &= ~ARMV7_PMNC_ENABLE; | pmnc &= ~ARMV7_PMNC_ENABLE; | ||||
cp15_pmcr_set(pmnc); | cp15_pmcr_set(pmnc); | ||||
pmnc = 0xffffffff; | |||||
cp15_pmcnten_clr(pmnc); | |||||
cp15_pminten_clr(pmnc); | |||||
cp15_pmovsr_set(pmnc); | |||||
return 0; | return 0; | ||||
} | } | ||||
struct pmc_mdep * | struct pmc_mdep * | ||||
pmc_armv7_initialize() | pmc_armv7_initialize() | ||||
{ | { | ||||
struct pmc_mdep *pmc_mdep; | struct pmc_mdep *pmc_mdep; | ||||
▲ Show 20 Lines • Show All 68 Lines • Show Last 20 Lines |