7 #if defined(__i386__) || defined(__x86_64__)
20 #define MSR_APERF 0xE8
21 #define MSR_MPERF 0xE7
25 #define MSR_AMD_HWCR 0xc0010015
27 enum mperf_id {
C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT };
29 static int mperf_get_count_percent(
unsigned int self_id,
double *
percent,
31 static int mperf_get_count_freq(
unsigned int id,
unsigned long long *
count,
33 static struct timespec time_start, time_end;
35 static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
38 .desc =
N_(
"Processor Core not idle"),
41 .get_count_percent = mperf_get_count_percent,
45 .desc =
N_(
"Processor Core in an idle state"),
48 .get_count_percent = mperf_get_count_percent,
53 .desc =
N_(
"Average Frequency (including boost) in MHz"),
56 .get_count = mperf_get_count_freq,
60 enum MAX_FREQ_MODE { MAX_FREQ_SYSFS, MAX_FREQ_TSC_REF };
61 static int max_freq_mode;
68 static unsigned long max_frequency;
70 static unsigned long long tsc_at_measure_start;
71 static unsigned long long tsc_at_measure_end;
72 static unsigned long long *mperf_previous_count;
73 static unsigned long long *aperf_previous_count;
74 static unsigned long long *mperf_current_count;
75 static unsigned long long *aperf_current_count;
80 static int mperf_get_tsc(
unsigned long long *
tsc)
83 ret = read_msr(0, MSR_TSC, tsc);
85 dprint(
"Reading TSC MSR failed, returning %llu\n", *tsc);
89 static int mperf_init_stats(
unsigned int cpu)
91 unsigned long long val;
95 aperf_previous_count[
cpu] =
val;
97 mperf_previous_count[
cpu] =
val;
103 static int mperf_measure_stats(
unsigned int cpu)
105 unsigned long long val;
109 aperf_current_count[
cpu] =
val;
111 mperf_current_count[
cpu] =
val;
117 static int mperf_get_count_percent(
unsigned int id,
double *
percent,
120 unsigned long long aperf_diff, mperf_diff, tsc_diff;
121 unsigned long long timediff;
126 if (
id !=
C0 &&
id != Cx)
129 mperf_diff = mperf_current_count[
cpu] - mperf_previous_count[
cpu];
130 aperf_diff = aperf_current_count[
cpu] - aperf_previous_count[
cpu];
132 if (max_freq_mode == MAX_FREQ_TSC_REF) {
133 tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
134 *percent = 100.0 * mperf_diff / tsc_diff;
135 dprint(
"%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
136 mperf_cstates[
id].
name, mperf_diff, tsc_diff);
137 }
else if (max_freq_mode == MAX_FREQ_SYSFS) {
139 *percent = 100.0 * mperf_diff / timediff;
140 dprint(
"%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
141 mperf_cstates[
id].
name, mperf_diff, timediff);
148 dprint(
"%s: previous: %llu - current: %llu - (%u)\n",
149 mperf_cstates[
id].
name, mperf_diff, aperf_diff, cpu);
150 dprint(
"%s: %f\n", mperf_cstates[
id].
name, *percent);
154 static int mperf_get_count_freq(
unsigned int id,
unsigned long long *
count,
157 unsigned long long aperf_diff, mperf_diff, time_diff, tsc_diff;
165 mperf_diff = mperf_current_count[
cpu] - mperf_previous_count[
cpu];
166 aperf_diff = aperf_current_count[
cpu] - aperf_previous_count[
cpu];
168 if (max_freq_mode == MAX_FREQ_TSC_REF) {
170 tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
172 max_frequency = tsc_diff / time_diff;
175 *count = max_frequency * ((double)aperf_diff / mperf_diff);
176 dprint(
"%s: Average freq based on %s maximum frequency:\n",
177 mperf_cstates[
id].
name,
178 (max_freq_mode == MAX_FREQ_TSC_REF) ?
"TSC calculated" :
"sysfs read");
179 dprint(
"%max_frequency: %lu", max_frequency);
180 dprint(
"aperf_diff: %llu\n", aperf_diff);
181 dprint(
"mperf_diff: %llu\n", mperf_diff);
182 dprint(
"avg freq: %llu\n", *count);
186 static int mperf_start(
void)
189 unsigned long long dbg;
192 mperf_get_tsc(&tsc_at_measure_start);
195 mperf_init_stats(cpu);
198 dprint(
"TSC diff: %llu\n", dbg - tsc_at_measure_start);
202 static int mperf_stop(
void)
204 unsigned long long dbg;
208 mperf_measure_stats(cpu);
210 mperf_get_tsc(&tsc_at_measure_end);
214 dprint(
"TSC diff: %llu\n", dbg - tsc_at_measure_end);
234 static int init_maxfreq_mode(
void)
237 unsigned long long hwcr;
254 ret = read_msr(0, MSR_AMD_HWCR, &hwcr);
260 dprint(
"TSC read 0x%x failed - assume TSC working\n",
263 }
else if (1 & (hwcr >> 24)) {
264 max_freq_mode = MAX_FREQ_TSC_REF;
272 max_freq_mode = MAX_FREQ_TSC_REF;
277 dprint(
"Cannot retrieve max freq from cpufreq kernel "
281 max_freq_mode = MAX_FREQ_SYSFS;
303 if (init_maxfreq_mode())
307 is_valid = calloc(cpu_count,
sizeof(
int));
308 mperf_previous_count = calloc(cpu_count,
sizeof(
unsigned long long));
309 aperf_previous_count = calloc(cpu_count,
sizeof(
unsigned long long));
310 mperf_current_count = calloc(cpu_count,
sizeof(
unsigned long long));
311 aperf_current_count = calloc(cpu_count,
sizeof(
unsigned long long));
313 mperf_monitor.name_len =
strlen(mperf_monitor.name);
314 return &mperf_monitor;
317 void mperf_unregister(
void)
319 free(mperf_previous_count);
320 free(aperf_previous_count);
321 free(mperf_current_count);
322 free(aperf_current_count);
328 .hw_states_num = MPERF_CSTATE_COUNT,
329 .hw_states = mperf_cstates,
330 .start = mperf_start,
332 .do_register = mperf_register,
333 .unregister = mperf_unregister,
335 .overflow_s = 922000000