powerpc64: add Power8 and Power9 PMCs
Add support to allocate Power8 and 9 PMCs. Submitted by: Leonardo Bianconi <leonardo.bianconi@eldorado.org.br> Reviewed by: mhorne Sponsored by: Instituto de Pesquisas Eldorado (eldorado.org.br) Differential Revision: https://reviews.freebsd.org/D31109
This commit is contained in:
parent
d2dc4548eb
commit
b48a2770d4
@ -142,6 +142,13 @@ pmu_alias_get(const char *name)
|
|||||||
|
|
||||||
return (name);
|
return (name);
|
||||||
}
|
}
|
||||||
|
#elif defined(__powerpc64__)
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
pmu_alias_get(const char *name)
|
||||||
|
{
|
||||||
|
return (name);
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
|
||||||
@ -571,6 +578,33 @@ pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
|
|||||||
return (pmc_pmu_amd_pmcallocate(event_name, pm, &ped));
|
return (pmc_pmu_amd_pmcallocate(event_name, pm, &ped));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(__powerpc64__)
|
||||||
|
|
||||||
|
int
|
||||||
|
pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
|
||||||
|
{
|
||||||
|
const struct pmu_event *pe;
|
||||||
|
struct pmu_event_desc ped;
|
||||||
|
int idx = -1;
|
||||||
|
|
||||||
|
bzero(&pm->pm_md, sizeof(pm->pm_md));
|
||||||
|
pm->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
|
||||||
|
event_name = pmu_alias_get(event_name);
|
||||||
|
|
||||||
|
if ((pe = pmu_event_get(NULL, event_name, &idx)) == NULL)
|
||||||
|
return (ENOENT);
|
||||||
|
if (pe->event == NULL)
|
||||||
|
return (ENOENT);
|
||||||
|
if (pmu_parse_event(&ped, pe->event))
|
||||||
|
return (ENOENT);
|
||||||
|
|
||||||
|
assert(ped.ped_event >= 0);
|
||||||
|
pm->pm_ev = idx;
|
||||||
|
pm->pm_md.pm_event = ped.ped_event;
|
||||||
|
pm->pm_class = PMC_CLASS_POWER8;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -43,6 +43,12 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#define POWER8_MAX_PMCS 6
|
#define POWER8_MAX_PMCS 6
|
||||||
|
|
||||||
|
#define PM_EVENT_CODE(pe) (pe & 0xffff)
|
||||||
|
#define PM_EVENT_COUNTER(pe) ((pe >> 16) & 0xffff)
|
||||||
|
|
||||||
|
#define PM_CYC 0x1e
|
||||||
|
#define PM_INST_CMPL 0x02
|
||||||
|
|
||||||
static struct pmc_ppc_event power8_event_codes[] = {
|
static struct pmc_ppc_event power8_event_codes[] = {
|
||||||
{PMC_EV_POWER8_INSTR_COMPLETED,
|
{PMC_EV_POWER8_INSTR_COMPLETED,
|
||||||
.pe_flags = PMC_FLAG_PMC5,
|
.pe_flags = PMC_FLAG_PMC5,
|
||||||
@ -275,6 +281,54 @@ power8_resume_pmc(bool ie)
|
|||||||
mtspr(SPR_MMCR0, mmcr0);
|
mtspr(SPR_MMCR0, mmcr0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
power8_allocate_pmc(int cpu, int ri, struct pmc *pm,
|
||||||
|
const struct pmc_op_pmcallocate *a)
|
||||||
|
{
|
||||||
|
uint32_t caps, config, counter, pe;
|
||||||
|
|
||||||
|
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
||||||
|
("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
|
||||||
|
KASSERT(ri >= 0 && ri < ppc_max_pmcs,
|
||||||
|
("[powerpc,%d] illegal row index %d", __LINE__, ri));
|
||||||
|
|
||||||
|
pe = a->pm_md.pm_event;
|
||||||
|
counter = PM_EVENT_COUNTER(pe);
|
||||||
|
config = PM_EVENT_CODE(pe);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PMC5 and PMC6 are not programmable and always count instructions
|
||||||
|
* completed and cycles, respectively.
|
||||||
|
*
|
||||||
|
* When counter is 0 any of the 4 programmable PMCs may be used for
|
||||||
|
* the specified event, otherwise it must match ri + 1.
|
||||||
|
*/
|
||||||
|
if (counter == 0 && config == PM_INST_CMPL)
|
||||||
|
counter = 5;
|
||||||
|
else if (counter == 0 && config == PM_CYC)
|
||||||
|
counter = 6;
|
||||||
|
else if (counter > 4)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
if (counter != 0 && counter != ri + 1)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
caps = a->pm_caps;
|
||||||
|
|
||||||
|
if (caps & PMC_CAP_SYSTEM)
|
||||||
|
config |= POWERPC_PMC_KERNEL_ENABLE;
|
||||||
|
if (caps & PMC_CAP_USER)
|
||||||
|
config |= POWERPC_PMC_USER_ENABLE;
|
||||||
|
if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
|
||||||
|
config |= POWERPC_PMC_ENABLE;
|
||||||
|
|
||||||
|
pm->pm_md.pm_powerpc.pm_powerpc_evsel = config;
|
||||||
|
|
||||||
|
PMCDBG3(MDP,ALL,1,"powerpc-allocate cpu=%d ri=%d -> config=0x%x",
|
||||||
|
cpu, ri, config);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
|
pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
|
||||||
{
|
{
|
||||||
@ -291,7 +345,7 @@ pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
|
|||||||
|
|
||||||
pcd->pcd_pcpu_init = power8_pcpu_init;
|
pcd->pcd_pcpu_init = power8_pcpu_init;
|
||||||
pcd->pcd_pcpu_fini = power8_pcpu_fini;
|
pcd->pcd_pcpu_fini = power8_pcpu_fini;
|
||||||
pcd->pcd_allocate_pmc = powerpc_allocate_pmc;
|
pcd->pcd_allocate_pmc = power8_allocate_pmc;
|
||||||
pcd->pcd_release_pmc = powerpc_release_pmc;
|
pcd->pcd_release_pmc = powerpc_release_pmc;
|
||||||
pcd->pcd_start_pmc = powerpc_start_pmc;
|
pcd->pcd_start_pmc = powerpc_start_pmc;
|
||||||
pcd->pcd_stop_pmc = powerpc_stop_pmc;
|
pcd->pcd_stop_pmc = powerpc_stop_pmc;
|
||||||
@ -304,10 +358,7 @@ pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
|
|||||||
pmc_mdep->pmd_npmc += POWER8_MAX_PMCS;
|
pmc_mdep->pmd_npmc += POWER8_MAX_PMCS;
|
||||||
pmc_mdep->pmd_intr = powerpc_pmc_intr;
|
pmc_mdep->pmd_intr = powerpc_pmc_intr;
|
||||||
|
|
||||||
ppc_event_codes = power8_event_codes;
|
|
||||||
ppc_event_codes_size = power8_event_codes_size;
|
ppc_event_codes_size = power8_event_codes_size;
|
||||||
ppc_event_first = PMC_EV_POWER8_FIRST;
|
|
||||||
ppc_event_last = PMC_EV_POWER8_LAST;
|
|
||||||
ppc_max_pmcs = POWER8_MAX_PMCS;
|
ppc_max_pmcs = POWER8_MAX_PMCS;
|
||||||
|
|
||||||
powerpc_set_pmc = power8_set_pmc;
|
powerpc_set_pmc = power8_set_pmc;
|
||||||
|
@ -603,6 +603,9 @@ pmc_md_initialize()
|
|||||||
pmc_mdep = NULL;
|
pmc_mdep = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the value for kern.hwpmc.cpuid */
|
||||||
|
snprintf(pmc_cpuid, sizeof(pmc_cpuid), "%08lx", mfpvr());
|
||||||
|
|
||||||
return (pmc_mdep);
|
return (pmc_mdep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define PMC_MDEP_CLASS_INDEX_POWERPC 1
|
#define PMC_MDEP_CLASS_INDEX_POWERPC 1
|
||||||
|
|
||||||
union pmc_md_op_pmcallocate {
|
union pmc_md_op_pmcallocate {
|
||||||
|
uint32_t pm_event;
|
||||||
uint64_t __pad[4];
|
uint64_t __pad[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user