Skip to content
Snippets Groups Projects
Commit de82306f authored by He Rongguang's avatar He Rongguang Committed by Frieder Schrempf
Browse files

cpupower: fix TSC MHz calculation


[ Upstream commit 9d6c0e58514f8b57cd9c2c755e41623d6a966025 ]

Commit 'cpupower: Make TSC read per CPU for Mperf monitor' (c2adb187)
changes TSC counter reads per cpu, but left time diff global (from start
of all cpus to end of all cpus), thus diff(time) is too large for a
cpu's tsc counting, resulting in far less than acutal TSC_Mhz and thus
`cpupower monitor` showing far less than actual cpu realtime frequency.

/proc/cpuinfo shows frequency:
cat /proc/cpuinfo | egrep -e 'processor' -e 'MHz'
...
processor : 171
cpu MHz   : 4108.498
...

before fix (System 100% busy):
    | Mperf              || Idle_Stats
 CPU| C0   | Cx   | Freq  || POLL | C1   | C2
 171|  0.77| 99.23|  2279||  0.00|  0.00|  0.00

after fix (System 100% busy):
    | Mperf              || Idle_Stats
 CPU| C0   | Cx   | Freq  || POLL | C1   | C2
 171|  0.46| 99.54|  4095||  0.00|  0.00|  0.00

Fixes: c2adb187 ("cpupower: Make TSC read per CPU for Mperf monitor")
Signed-off-by: default avatarHe Rongguang <herongguang@linux.alibaba.com>
Signed-off-by: default avatarShuah Khan <skhan@linuxfoundation.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 063d5b69
No related branches found
No related tags found
1 merge request!191🤖 Sync Bot: Update v6.1-ktn to Latest Stable Kernel (v6.1.129)
...@@ -33,7 +33,7 @@ static int mperf_get_count_percent(unsigned int self_id, double *percent, ...@@ -33,7 +33,7 @@ static int mperf_get_count_percent(unsigned int self_id, double *percent,
unsigned int cpu); unsigned int cpu);
static int mperf_get_count_freq(unsigned int id, unsigned long long *count, static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
unsigned int cpu); unsigned int cpu);
static struct timespec time_start, time_end; static struct timespec *time_start, *time_end;
static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = { static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
{ {
...@@ -174,7 +174,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent, ...@@ -174,7 +174,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n", dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
mperf_cstates[id].name, mperf_diff, tsc_diff); mperf_cstates[id].name, mperf_diff, tsc_diff);
} else if (max_freq_mode == MAX_FREQ_SYSFS) { } else if (max_freq_mode == MAX_FREQ_SYSFS) {
timediff = max_frequency * timespec_diff_us(time_start, time_end); timediff = max_frequency * timespec_diff_us(time_start[cpu], time_end[cpu]);
*percent = 100.0 * mperf_diff / timediff; *percent = 100.0 * mperf_diff / timediff;
dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n", dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
mperf_cstates[id].name, mperf_diff, timediff); mperf_cstates[id].name, mperf_diff, timediff);
...@@ -207,7 +207,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count, ...@@ -207,7 +207,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
if (max_freq_mode == MAX_FREQ_TSC_REF) { if (max_freq_mode == MAX_FREQ_TSC_REF) {
/* Calculate max_freq from TSC count */ /* Calculate max_freq from TSC count */
tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu]; tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
time_diff = timespec_diff_us(time_start, time_end); time_diff = timespec_diff_us(time_start[cpu], time_end[cpu]);
max_frequency = tsc_diff / time_diff; max_frequency = tsc_diff / time_diff;
} }
...@@ -226,9 +226,8 @@ static int mperf_start(void) ...@@ -226,9 +226,8 @@ static int mperf_start(void)
{ {
int cpu; int cpu;
clock_gettime(CLOCK_REALTIME, &time_start);
for (cpu = 0; cpu < cpu_count; cpu++) { for (cpu = 0; cpu < cpu_count; cpu++) {
clock_gettime(CLOCK_REALTIME, &time_start[cpu]);
mperf_get_tsc(&tsc_at_measure_start[cpu]); mperf_get_tsc(&tsc_at_measure_start[cpu]);
mperf_init_stats(cpu); mperf_init_stats(cpu);
} }
...@@ -243,9 +242,9 @@ static int mperf_stop(void) ...@@ -243,9 +242,9 @@ static int mperf_stop(void)
for (cpu = 0; cpu < cpu_count; cpu++) { for (cpu = 0; cpu < cpu_count; cpu++) {
mperf_measure_stats(cpu); mperf_measure_stats(cpu);
mperf_get_tsc(&tsc_at_measure_end[cpu]); mperf_get_tsc(&tsc_at_measure_end[cpu]);
clock_gettime(CLOCK_REALTIME, &time_end[cpu]);
} }
clock_gettime(CLOCK_REALTIME, &time_end);
return 0; return 0;
} }
...@@ -349,6 +348,8 @@ struct cpuidle_monitor *mperf_register(void) ...@@ -349,6 +348,8 @@ struct cpuidle_monitor *mperf_register(void)
aperf_current_count = calloc(cpu_count, sizeof(unsigned long long)); aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long)); tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long)); tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
time_start = calloc(cpu_count, sizeof(struct timespec));
time_end = calloc(cpu_count, sizeof(struct timespec));
mperf_monitor.name_len = strlen(mperf_monitor.name); mperf_monitor.name_len = strlen(mperf_monitor.name);
return &mperf_monitor; return &mperf_monitor;
} }
...@@ -361,6 +362,8 @@ void mperf_unregister(void) ...@@ -361,6 +362,8 @@ void mperf_unregister(void)
free(aperf_current_count); free(aperf_current_count);
free(tsc_at_measure_start); free(tsc_at_measure_start);
free(tsc_at_measure_end); free(tsc_at_measure_end);
free(time_start);
free(time_end);
free(is_valid); free(is_valid);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment