mirror of https://gitee.com/openkylin/linux.git
perfcounters: add fixed-mode PMC enumeration
Enumerate fixed-mode PMCs based on CPUID, and feed that into the perfcounter code. Does not use fixed-mode PMCs yet. Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
eb2b861810
commit
703e937c83
|
@ -41,6 +41,29 @@ union cpuid10_eax {
|
||||||
unsigned int full;
|
unsigned int full;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union cpuid10_edx {
|
||||||
|
struct {
|
||||||
|
unsigned int num_counters_fixed:4;
|
||||||
|
unsigned int reserved:28;
|
||||||
|
} split;
|
||||||
|
unsigned int full;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixed-purpose performance counters:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Instr_Retired.Any: */
|
||||||
|
#define MSR_ARCH_PERFMON_FIXED_CTR0 0x309
|
||||||
|
|
||||||
|
/* CPU_CLK_Unhalted.Core: */
|
||||||
|
#define MSR_ARCH_PERFMON_FIXED_CTR1 0x30a
|
||||||
|
|
||||||
|
/* CPU_CLK_Unhalted.Ref: */
|
||||||
|
#define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_PERF_COUNTERS
|
#ifdef CONFIG_PERF_COUNTERS
|
||||||
extern void init_hw_perf_counters(void);
|
extern void init_hw_perf_counters(void);
|
||||||
extern void perf_counters_lapic_init(int nmi);
|
extern void perf_counters_lapic_init(int nmi);
|
||||||
|
|
|
@ -27,6 +27,8 @@ static bool perf_counters_initialized __read_mostly;
|
||||||
static int nr_hw_counters __read_mostly;
|
static int nr_hw_counters __read_mostly;
|
||||||
static u32 perf_counter_mask __read_mostly;
|
static u32 perf_counter_mask __read_mostly;
|
||||||
|
|
||||||
|
static int nr_hw_counters_fixed __read_mostly;
|
||||||
|
|
||||||
struct cpu_hw_counters {
|
struct cpu_hw_counters {
|
||||||
struct perf_counter *generic[X86_PMC_MAX_GENERIC];
|
struct perf_counter *generic[X86_PMC_MAX_GENERIC];
|
||||||
unsigned long used[BITS_TO_LONGS(X86_PMC_MAX_GENERIC)];
|
unsigned long used[BITS_TO_LONGS(X86_PMC_MAX_GENERIC)];
|
||||||
|
@ -519,8 +521,9 @@ static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
|
||||||
void __init init_hw_perf_counters(void)
|
void __init init_hw_perf_counters(void)
|
||||||
{
|
{
|
||||||
union cpuid10_eax eax;
|
union cpuid10_eax eax;
|
||||||
unsigned int unused;
|
|
||||||
unsigned int ebx;
|
unsigned int ebx;
|
||||||
|
unsigned int unused;
|
||||||
|
union cpuid10_edx edx;
|
||||||
|
|
||||||
if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
|
if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
|
||||||
return;
|
return;
|
||||||
|
@ -529,14 +532,14 @@ void __init init_hw_perf_counters(void)
|
||||||
* Check whether the Architectural PerfMon supports
|
* Check whether the Architectural PerfMon supports
|
||||||
* Branch Misses Retired Event or not.
|
* Branch Misses Retired Event or not.
|
||||||
*/
|
*/
|
||||||
cpuid(10, &(eax.full), &ebx, &unused, &unused);
|
cpuid(10, &eax.full, &ebx, &unused, &edx.full);
|
||||||
if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
|
if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printk(KERN_INFO "Intel Performance Monitoring support detected.\n");
|
printk(KERN_INFO "Intel Performance Monitoring support detected.\n");
|
||||||
|
|
||||||
printk(KERN_INFO "... version: %d\n", eax.split.version_id);
|
printk(KERN_INFO "... version: %d\n", eax.split.version_id);
|
||||||
printk(KERN_INFO "... num_counters: %d\n", eax.split.num_counters);
|
printk(KERN_INFO "... num counters: %d\n", eax.split.num_counters);
|
||||||
nr_hw_counters = eax.split.num_counters;
|
nr_hw_counters = eax.split.num_counters;
|
||||||
if (nr_hw_counters > X86_PMC_MAX_GENERIC) {
|
if (nr_hw_counters > X86_PMC_MAX_GENERIC) {
|
||||||
nr_hw_counters = X86_PMC_MAX_GENERIC;
|
nr_hw_counters = X86_PMC_MAX_GENERIC;
|
||||||
|
@ -546,8 +549,16 @@ void __init init_hw_perf_counters(void)
|
||||||
perf_counter_mask = (1 << nr_hw_counters) - 1;
|
perf_counter_mask = (1 << nr_hw_counters) - 1;
|
||||||
perf_max_counters = nr_hw_counters;
|
perf_max_counters = nr_hw_counters;
|
||||||
|
|
||||||
printk(KERN_INFO "... bit_width: %d\n", eax.split.bit_width);
|
printk(KERN_INFO "... bit width: %d\n", eax.split.bit_width);
|
||||||
printk(KERN_INFO "... mask_length: %d\n", eax.split.mask_length);
|
printk(KERN_INFO "... mask length: %d\n", eax.split.mask_length);
|
||||||
|
|
||||||
|
nr_hw_counters_fixed = edx.split.num_counters_fixed;
|
||||||
|
if (nr_hw_counters_fixed > X86_PMC_MAX_FIXED) {
|
||||||
|
nr_hw_counters_fixed = X86_PMC_MAX_FIXED;
|
||||||
|
WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!",
|
||||||
|
nr_hw_counters_fixed, X86_PMC_MAX_FIXED);
|
||||||
|
}
|
||||||
|
printk(KERN_INFO "... fixed counters: %d\n", nr_hw_counters_fixed);
|
||||||
|
|
||||||
perf_counters_initialized = true;
|
perf_counters_initialized = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue