cpupower: Make TSC read per CPU for Mperf monitor
[ Upstream commitc2adb1877b
] System-wide TSC read could cause a drift in C0 percentage calculation. Because if first TSC is read and then one by one mperf is read for all cpus, this introduces drift between mperf reading of later CPUs and TSC reading. To lower this drift read TSC per CPU and also just after mperf read. This technique improves C0 percentage calculation in Mperf monitor. Before fix: (System 100% busy) | Mperf || RAPL || Idle_Stats PKG|CORE| CPU| C0 | Cx | Freq || pack | core || POLL | C1 | C2 0| 0| 0| 87.15| 12.85| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 0| 256| 84.62| 15.38| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 1| 1| 87.15| 12.85| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 1| 257| 84.08| 15.92| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 2| 2| 86.61| 13.39| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 2| 258| 83.26| 16.74| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 3| 3| 86.61| 13.39| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 3| 259| 83.60| 16.40| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 4| 4| 86.33| 13.67| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 4| 260| 83.33| 16.67| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 5| 5| 86.06| 13.94| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 5| 261| 83.05| 16.95| 2695||168659003|3970468|| 0.00| 0.00| 0.00 0| 6| 6| 85.51| 14.49| 2695||168659003|3970468|| 0.00| 0.00| 0.00 After fix: (System 100% busy) | Mperf || RAPL || Idle_Stats PKG|CORE| CPU| C0 | Cx | Freq || pack | core || POLL | C1 | C2 0| 0| 0| 98.03| 1.97| 2415||163295480|3811189|| 0.00| 0.00| 0.00 0| 0| 256| 98.50| 1.50| 2394||163295480|3811189|| 0.00| 0.00| 0.00 0| 1| 1| 99.99| 0.01| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 1| 257| 99.99| 0.01| 2375||163295480|3811189|| 0.00| 0.00| 0.00 0| 2| 2| 99.99| 0.01| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 2| 258|100.00| 0.00| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 3| 3|100.00| 0.00| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 3| 259| 99.99| 0.01| 2435||163295480|3811189|| 0.00| 0.00| 0.00 0| 4| 4|100.00| 0.00| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 4| 260|100.00| 0.00| 2435||163295480|3811189|| 0.00| 0.00| 0.00 0| 5| 5| 99.99| 0.01| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 5| 261|100.00| 0.00| 2435||163295480|3811189|| 0.00| 0.00| 0.00 0| 6| 6|100.00| 0.00| 2401||163295480|3811189|| 0.00| 0.00| 0.00 0| 6| 262|100.00| 0.00| 2435||163295480|3811189|| 0.00| 0.00| 0.00 Cc: Thomas Renninger <trenn@suse.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Dominik Brodowski <linux@dominikbrodowski.net> Fixes:7fe2f6399a
("cpupowerutils - cpufrequtils extended with quite some features") Signed-off-by: Wyes Karny <wyes.karny@amd.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
ce6c7befc2
commit
0d778f0cb1
|
@ -70,8 +70,8 @@ static int max_freq_mode;
|
||||||
*/
|
*/
|
||||||
static unsigned long max_frequency;
|
static unsigned long max_frequency;
|
||||||
|
|
||||||
static unsigned long long tsc_at_measure_start;
|
static unsigned long long *tsc_at_measure_start;
|
||||||
static unsigned long long tsc_at_measure_end;
|
static unsigned long long *tsc_at_measure_end;
|
||||||
static unsigned long long *mperf_previous_count;
|
static unsigned long long *mperf_previous_count;
|
||||||
static unsigned long long *aperf_previous_count;
|
static unsigned long long *aperf_previous_count;
|
||||||
static unsigned long long *mperf_current_count;
|
static unsigned long long *mperf_current_count;
|
||||||
|
@ -169,7 +169,7 @@ static int mperf_get_count_percent(unsigned int id, double *percent,
|
||||||
aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
|
aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
|
||||||
|
|
||||||
if (max_freq_mode == MAX_FREQ_TSC_REF) {
|
if (max_freq_mode == MAX_FREQ_TSC_REF) {
|
||||||
tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
|
tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
|
||||||
*percent = 100.0 * mperf_diff / tsc_diff;
|
*percent = 100.0 * mperf_diff / tsc_diff;
|
||||||
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);
|
||||||
|
@ -206,7 +206,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 - tsc_at_measure_start;
|
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, time_end);
|
||||||
max_frequency = tsc_diff / time_diff;
|
max_frequency = tsc_diff / time_diff;
|
||||||
}
|
}
|
||||||
|
@ -225,33 +225,27 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
|
||||||
static int mperf_start(void)
|
static int mperf_start(void)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
unsigned long long dbg;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &time_start);
|
clock_gettime(CLOCK_REALTIME, &time_start);
|
||||||
mperf_get_tsc(&tsc_at_measure_start);
|
|
||||||
|
|
||||||
for (cpu = 0; cpu < cpu_count; cpu++)
|
for (cpu = 0; cpu < cpu_count; cpu++) {
|
||||||
|
mperf_get_tsc(&tsc_at_measure_start[cpu]);
|
||||||
mperf_init_stats(cpu);
|
mperf_init_stats(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
mperf_get_tsc(&dbg);
|
|
||||||
dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mperf_stop(void)
|
static int mperf_stop(void)
|
||||||
{
|
{
|
||||||
unsigned long long dbg;
|
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
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);
|
|
||||||
clock_gettime(CLOCK_REALTIME, &time_end);
|
clock_gettime(CLOCK_REALTIME, &time_end);
|
||||||
|
|
||||||
mperf_get_tsc(&dbg);
|
|
||||||
dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +347,8 @@ struct cpuidle_monitor *mperf_register(void)
|
||||||
aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
|
aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
|
||||||
mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
|
mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
|
||||||
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_end = calloc(cpu_count, sizeof(unsigned long long));
|
||||||
mperf_monitor.name_len = strlen(mperf_monitor.name);
|
mperf_monitor.name_len = strlen(mperf_monitor.name);
|
||||||
return &mperf_monitor;
|
return &mperf_monitor;
|
||||||
}
|
}
|
||||||
|
@ -364,6 +359,8 @@ void mperf_unregister(void)
|
||||||
free(aperf_previous_count);
|
free(aperf_previous_count);
|
||||||
free(mperf_current_count);
|
free(mperf_current_count);
|
||||||
free(aperf_current_count);
|
free(aperf_current_count);
|
||||||
|
free(tsc_at_measure_start);
|
||||||
|
free(tsc_at_measure_end);
|
||||||
free(is_valid);
|
free(is_valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue