Index: lib/libpmc/libpmc_pmu_util.c =================================================================== --- lib/libpmc/libpmc_pmu_util.c +++ lib/libpmc/libpmc_pmu_util.c @@ -142,6 +142,33 @@ return (name); } +#elif defined(__powerpc64__) +typedef enum { + PMU_INVALID, + PMU_POWERPC64, +} pmu_mfr_t; + +static pmu_mfr_t +pmu_events_mfr(void) +{ + char buf[PMC_CPUID_LEN]; + size_t s = sizeof(buf); + + if (sysctlbyname("hw.model", buf, &s, + (void *)NULL, 0) != -1) { + if (strcasestr(buf, "IBM POWER9") != NULL || + strcasestr(buf, "IBM POWER8") != NULL) + return PMU_POWERPC64; + } + + return PMU_INVALID; +} + +static const char * +pmu_alias_get(const char *name) +{ + return (name); +} #elif defined(__aarch64__) @@ -571,6 +598,37 @@ 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; + pmu_mfr_t mfr; + int idx = -1; + + if ((mfr = pmu_events_mfr()) == PMU_INVALID){ + return (ENOENT); + } + + 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 = ped.ped_event; + pm->pm_class = PMC_CLASS_POWER8; + return (0); +} + #elif defined(__aarch64__) int Index: sys/dev/hwpmc/hwpmc_power8.c =================================================================== --- sys/dev/hwpmc/hwpmc_power8.c +++ sys/dev/hwpmc/hwpmc_power8.c @@ -43,135 +43,6 @@ #define POWER8_MAX_PMCS 6 -static struct pmc_ppc_event power8_event_codes[] = { - {PMC_EV_POWER8_INSTR_COMPLETED, - .pe_flags = PMC_FLAG_PMC5, - .pe_code = 0x00 - }, - /* - * PMC1 can also count cycles, but as PMC6 can only count cycles - * it's better to always use it and leave PMC1 free to count - * other events. - */ - {PMC_EV_POWER8_CYCLES, - .pe_flags = PMC_FLAG_PMC6, - .pe_code = 0xf0 - }, - {PMC_EV_POWER8_CYCLES_WITH_INSTRS_COMPLETED, - .pe_flags = PMC_FLAG_PMC1, - .pe_code = 0xf2 - }, - {PMC_EV_POWER8_FPU_INSTR_COMPLETED, - .pe_flags = PMC_FLAG_PMC1, - .pe_code = 0xf4 - }, - {PMC_EV_POWER8_ERAT_INSTR_MISS, - .pe_flags = PMC_FLAG_PMC1, - .pe_code = 0xf6 - }, - {PMC_EV_POWER8_CYCLES_IDLE, - .pe_flags = PMC_FLAG_PMC1, - .pe_code = 0xf8 - }, - {PMC_EV_POWER8_CYCLES_WITH_ANY_THREAD_RUNNING, - .pe_flags = PMC_FLAG_PMC1, - .pe_code = 0xfa - }, - {PMC_EV_POWER8_STORE_COMPLETED, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xf0 - }, - {PMC_EV_POWER8_INSTR_DISPATCHED, - .pe_flags = PMC_FLAG_PMC2 | PMC_FLAG_PMC3, - .pe_code = 0xf2 - }, - {PMC_EV_POWER8_CYCLES_RUNNING, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xf4 - }, - {PMC_EV_POWER8_ERAT_DATA_MISS, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xf6 - }, - {PMC_EV_POWER8_EXTERNAL_INTERRUPT, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xf8 - }, - {PMC_EV_POWER8_BRANCH_TAKEN, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xfa - }, - {PMC_EV_POWER8_L1_INSTR_MISS, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xfc - }, - {PMC_EV_POWER8_L2_LOAD_MISS, - .pe_flags = PMC_FLAG_PMC2, - .pe_code = 0xfe - }, - {PMC_EV_POWER8_STORE_NO_REAL_ADDR, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xf0 - }, - {PMC_EV_POWER8_INSTR_COMPLETED_WITH_ALL_THREADS_RUNNING, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xf4 - }, - {PMC_EV_POWER8_L1_LOAD_MISS, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xf6 - }, - {PMC_EV_POWER8_TIMEBASE_EVENT, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xf8 - }, - {PMC_EV_POWER8_L3_INSTR_MISS, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xfa - }, - {PMC_EV_POWER8_TLB_DATA_MISS, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xfc - }, - {PMC_EV_POWER8_L3_LOAD_MISS, - .pe_flags = PMC_FLAG_PMC3, - .pe_code = 0xfe - }, - {PMC_EV_POWER8_LOAD_NO_REAL_ADDR, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xf0 - }, - {PMC_EV_POWER8_CYCLES_WITH_INSTRS_DISPATCHED, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xf2 - }, - {PMC_EV_POWER8_CYCLES_RUNNING_PURR_INC, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xf4 - }, - {PMC_EV_POWER8_BRANCH_MISPREDICTED, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xf6 - }, - {PMC_EV_POWER8_PREFETCHED_INSTRS_DISCARDED, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xf8 - }, - {PMC_EV_POWER8_INSTR_COMPLETED_RUNNING, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xfa - }, - {PMC_EV_POWER8_TLB_INSTR_MISS, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xfc - }, - {PMC_EV_POWER8_CACHE_LOAD_MISS, - .pe_flags = PMC_FLAG_PMC4, - .pe_code = 0xfe - } -}; -static size_t power8_event_codes_size = nitems(power8_event_codes); - static void power8_set_pmc(int cpu, int ri, int config) { @@ -275,6 +146,34 @@ 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 = 0; + + 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)); + + caps = a->pm_caps; + config = (0xFFFF & a->pm_ev); + + 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 pmc_power8_initialize(struct pmc_mdep *pmc_mdep) { @@ -291,7 +190,7 @@ pcd->pcd_pcpu_init = power8_pcpu_init; 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_start_pmc = powerpc_start_pmc; pcd->pcd_stop_pmc = powerpc_stop_pmc; @@ -304,10 +203,6 @@ pmc_mdep->pmd_npmc += POWER8_MAX_PMCS; pmc_mdep->pmd_intr = powerpc_pmc_intr; - ppc_event_codes = power8_event_codes; - 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; powerpc_set_pmc = power8_set_pmc; Index: sys/dev/hwpmc/hwpmc_powerpc.c =================================================================== --- sys/dev/hwpmc/hwpmc_powerpc.c +++ sys/dev/hwpmc/hwpmc_powerpc.c @@ -567,7 +567,6 @@ pmc_mdep->pmd_switch_in = powerpc_switch_in; pmc_mdep->pmd_switch_out = powerpc_switch_out; - switch (vers) { case MPC7447A: case MPC7448: @@ -603,6 +602,8 @@ pmc_mdep = NULL; } + snprintf(pmc_cpuid, sizeof(pmc_cpuid), "%08lx", mfpvr()); + return (pmc_mdep); } Index: sys/dev/hwpmc/pmc_events.h =================================================================== --- sys/dev/hwpmc/pmc_events.h +++ sys/dev/hwpmc/pmc_events.h @@ -1640,41 +1640,6 @@ #define PMC_EV_PPC970_FIRST PMC_EV_PPC970_INSTR_COMPLETED #define PMC_EV_PPC970_LAST PMC_EV_PPC970_ADDER -#define __PMC_EV_POWER8() \ - __PMC_EV(POWER8, CYCLES) \ - __PMC_EV(POWER8, CYCLES_WITH_INSTRS_COMPLETED) \ - __PMC_EV(POWER8, FPU_INSTR_COMPLETED) \ - __PMC_EV(POWER8, ERAT_INSTR_MISS) \ - __PMC_EV(POWER8, CYCLES_IDLE) \ - __PMC_EV(POWER8, CYCLES_WITH_ANY_THREAD_RUNNING) \ - __PMC_EV(POWER8, STORE_COMPLETED) \ - __PMC_EV(POWER8, INSTR_DISPATCHED) \ - __PMC_EV(POWER8, CYCLES_RUNNING) \ - __PMC_EV(POWER8, ERAT_DATA_MISS) \ - __PMC_EV(POWER8, EXTERNAL_INTERRUPT) \ - __PMC_EV(POWER8, BRANCH_TAKEN) \ - __PMC_EV(POWER8, L1_INSTR_MISS) \ - __PMC_EV(POWER8, L2_LOAD_MISS) \ - __PMC_EV(POWER8, STORE_NO_REAL_ADDR) \ - __PMC_EV(POWER8, INSTR_COMPLETED_WITH_ALL_THREADS_RUNNING) \ - __PMC_EV(POWER8, L1_LOAD_MISS) \ - __PMC_EV(POWER8, TIMEBASE_EVENT) \ - __PMC_EV(POWER8, L3_INSTR_MISS) \ - __PMC_EV(POWER8, TLB_DATA_MISS) \ - __PMC_EV(POWER8, L3_LOAD_MISS) \ - __PMC_EV(POWER8, LOAD_NO_REAL_ADDR) \ - __PMC_EV(POWER8, CYCLES_WITH_INSTRS_DISPATCHED) \ - __PMC_EV(POWER8, CYCLES_RUNNING_PURR_INC) \ - __PMC_EV(POWER8, BRANCH_MISPREDICTED) \ - __PMC_EV(POWER8, PREFETCHED_INSTRS_DISCARDED) \ - __PMC_EV(POWER8, INSTR_COMPLETED_RUNNING) \ - __PMC_EV(POWER8, TLB_INSTR_MISS) \ - __PMC_EV(POWER8, CACHE_LOAD_MISS) \ - __PMC_EV(POWER8, INSTR_COMPLETED) - -#define PMC_EV_POWER8_FIRST PMC_EV_POWER8_CYCLES -#define PMC_EV_POWER8_LAST PMC_EV_POWER8_INSTR_COMPLETED - #define __PMC_EV_E500() \ __PMC_EV(E500, CYCLES) \ __PMC_EV(E500, INSTR_COMPLETED) \ @@ -1889,8 +1854,6 @@ __PMC_EV_PPC7450() \ __PMC_EV_BLOCK(PPC970, 0x13100) \ __PMC_EV_PPC970() \ - __PMC_EV_BLOCK(POWER8, 0x13200) \ - __PMC_EV_POWER8() \ __PMC_EV_BLOCK(E500, 0x13300) \ __PMC_EV_E500() \ __PMC_EV_BLOCK(ARMV7, 0x14000) \