diff options
Diffstat (limited to 'arch/x86/machine')
-rw-r--r-- | arch/x86/machine/cpu.h | 2 | ||||
-rw-r--r-- | arch/x86/machine/pmu_amd.c | 15 | ||||
-rw-r--r-- | arch/x86/machine/pmu_intel.c | 24 |
3 files changed, 31 insertions, 10 deletions
diff --git a/arch/x86/machine/cpu.h b/arch/x86/machine/cpu.h index 719a6a5..3b7db61 100644 --- a/arch/x86/machine/cpu.h +++ b/arch/x86/machine/cpu.h @@ -218,7 +218,7 @@ struct cpu_tss { uint16_t iobp_base; } __packed; -#define CPU_VENDOR_STR_SIZE 13 +#define CPU_VENDOR_STR_SIZE 13 #define CPU_MODEL_NAME_SIZE 49 #define CPU_VENDOR_UNKNOWN 0 diff --git a/arch/x86/machine/pmu_amd.c b/arch/x86/machine/pmu_amd.c index b8b4c78..49b8d7e 100644 --- a/arch/x86/machine/pmu_amd.c +++ b/arch/x86/machine/pmu_amd.c @@ -109,14 +109,16 @@ static void pmu_amd_info(void) { log_info("pmu: driver: amd, nr_pmcs: %u, pmc_width: %u\n", - PMU_AMD_NR_PMCS, PMU_AMD_PMC_WIDTH); + PMU_AMD_NR_PMCS, PMU_AMD_PMC_WIDTH); } static int pmu_amd_translate(unsigned int *raw_event_idp, unsigned int event_id) { assert(event_id < ARRAY_SIZE(pmu_amd_generic_events)); + *raw_event_idp = pmu_amd_generic_events[event_id]; + return 0; } @@ -131,12 +133,14 @@ pmu_amd_alloc(unsigned int *pmc_idp, unsigned int raw_event_id) pmu = pmu_amd_get(); - if (pmu->pmc_bm == 0) + if (pmu->pmc_bm == 0) { return EAGAIN; + } pmc_id = __builtin_ffs(pmu->pmc_bm) - 1; pmu->pmc_bm &= ~(1U << pmc_id); *pmc_idp = pmc_id; + return 0; } @@ -150,7 +154,9 @@ pmu_amd_free(unsigned int pmc_id) pmu = pmu_amd_get(); mask = (1U << pmc_id); + assert(!(pmu->pmc_bm & mask)); + pmu->pmc_bm |= mask; } @@ -179,6 +185,7 @@ static void pmu_amd_stop(unsigned int pmc_id) { assert(pmc_id < PMU_AMD_NR_PMCS); + cpu_set_msr(PMU_AMD_MSR_PERFEVTSEL0 + pmc_id, 0, 0); } @@ -190,6 +197,7 @@ pmu_amd_read(unsigned int pmc_id) assert(pmc_id < PMU_AMD_NR_PMCS); cpu_get_msr(PMU_AMD_MSR_PERCTR0 + pmc_id, &high, &low); + return (((uint64_t)high << 32) | low); } @@ -207,8 +215,9 @@ pmu_amd_setup(void) } /* Support AMD Family 10h processors and later */ - if (cpu->family < 16) + if (cpu->family < 16) { return ENODEV; + } pmu = pmu_amd_get(); pmu->pmc_bm = (1U << PMU_AMD_NR_PMCS) - 1; diff --git a/arch/x86/machine/pmu_intel.c b/arch/x86/machine/pmu_intel.c index 4671a9f..20d7aa2 100644 --- a/arch/x86/machine/pmu_intel.c +++ b/arch/x86/machine/pmu_intel.c @@ -129,8 +129,9 @@ pmu_intel_info(void) static int pmu_intel_translate(unsigned int *raw_event_idp, unsigned event_id) { - if (event_id >= ARRAY_SIZE(pmu_intel_raw_events)) + if (event_id >= ARRAY_SIZE(pmu_intel_raw_events)) { return EINVAL; + } *raw_event_idp = pmu_intel_raw_events[event_id]; @@ -144,15 +145,18 @@ pmu_intel_alloc(unsigned int *pmc_idp, unsigned int raw_event_id) unsigned int pmc_id; unsigned int hw_event_id; - pmu = pmu_intel_get(); assert(raw_event_id < ARRAY_SIZE(pmu_intel_event_codes)); + + pmu = pmu_intel_get(); hw_event_id = pmu_intel_event_codes[raw_event_id].hw_event_id; - if (!(pmu->events & hw_event_id)) + if (!(pmu->events & hw_event_id)) { return EINVAL; + } - if (pmu->pmc_bm == 0) + if (pmu->pmc_bm == 0) { return EAGAIN; + } pmc_id = __builtin_ffs(pmu->pmc_bm) - 1; pmu->pmc_bm &= ~(1U << pmc_id); @@ -168,7 +172,9 @@ pmu_intel_free(unsigned int pmc_id) pmu = pmu_intel_get(); mask = (1U << pmc_id); + assert(!(pmu->pmc_bm & mask)); + pmu->pmc_bm |= mask; } @@ -179,6 +185,7 @@ pmu_intel_start(unsigned int pmc_id, unsigned int raw_event_id) uint32_t evtsel; assert(raw_event_id < ARRAY_SIZE(pmu_intel_event_codes)); + code = &pmu_intel_event_codes[raw_event_id]; /* TODO Handle PERFMON_EF_KERN/PERFMON_EF_USER */ @@ -202,6 +209,7 @@ pmu_intel_read(unsigned int pmc_id) uint32_t high, low; cpu_get_msr(PMU_INTEL_MSR_PMC0 + pmc_id, &high, &low); + return (((uint64_t)high << 32) | low); } @@ -220,15 +228,17 @@ pmu_intel_setup(void) return 0; } - if (cpu->cpuid_max_basic < eax) + if (cpu->cpuid_max_basic < eax) { return ENODEV; + } pmu = pmu_intel_get(); cpu_cpuid(&eax, &ebx, &ecx, &edx); pmu->version = eax & PMU_INTEL_ID_VERSION_MASK; - if ((pmu->version == 0) || (pmu->version > 3)) + if ((pmu->version == 0) || (pmu->version > 3)) { return ENODEV; + } pmu->nr_pmcs = (eax & PMU_INTEL_ID_NR_PMCS_MASK) >> PMU_INTEL_ID_NR_PMCS_OFFSET; @@ -236,7 +246,9 @@ pmu_intel_setup(void) pmu->pmc_width = (eax & PMU_INTEL_ID_PMC_WIDTH_MASK) >> PMU_INTEL_ID_PMC_WIDTH_OFFSET; ev_len = (eax & PMU_INTEL_ID_EVLEN_MASK) >> PMU_INTEL_ID_EVLEN_OFFSET; + assert(ev_len <= PMU_INTEL_ID_EVLEN_MAX); + pmu->events = ~ebx & ((1U << ev_len) - 1); pmu_driver.info = pmu_intel_info; |