Skip to content

Commit 23c296f

Browse files
JinzhouSurafaeljw
authored andcommitted
cpufreq: amd-pstate: Add more tracepoint for AMD P-State module
Add frequency, mperf, aperf and tsc in the trace. This can be used to debug and tune the performance of AMD P-state driver. Use the time difference between amd_pstate_update to calculate CPU frequency. There could be sleep in arch_freq_get_on_cpu, so do not use it here. Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com> Co-developed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent a1b6f48 commit 23c296f

2 files changed

Lines changed: 78 additions & 3 deletions

File tree

drivers/cpufreq/amd-pstate-trace.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ TRACE_EVENT(amd_pstate_perf,
2727
TP_PROTO(unsigned long min_perf,
2828
unsigned long target_perf,
2929
unsigned long capacity,
30+
u64 freq,
31+
u64 mperf,
32+
u64 aperf,
33+
u64 tsc,
3034
unsigned int cpu_id,
3135
bool changed,
3236
bool fast_switch
@@ -35,6 +39,10 @@ TRACE_EVENT(amd_pstate_perf,
3539
TP_ARGS(min_perf,
3640
target_perf,
3741
capacity,
42+
freq,
43+
mperf,
44+
aperf,
45+
tsc,
3846
cpu_id,
3947
changed,
4048
fast_switch
@@ -44,6 +52,10 @@ TRACE_EVENT(amd_pstate_perf,
4452
__field(unsigned long, min_perf)
4553
__field(unsigned long, target_perf)
4654
__field(unsigned long, capacity)
55+
__field(unsigned long long, freq)
56+
__field(unsigned long long, mperf)
57+
__field(unsigned long long, aperf)
58+
__field(unsigned long long, tsc)
4759
__field(unsigned int, cpu_id)
4860
__field(bool, changed)
4961
__field(bool, fast_switch)
@@ -53,15 +65,23 @@ TRACE_EVENT(amd_pstate_perf,
5365
__entry->min_perf = min_perf;
5466
__entry->target_perf = target_perf;
5567
__entry->capacity = capacity;
68+
__entry->freq = freq;
69+
__entry->mperf = mperf;
70+
__entry->aperf = aperf;
71+
__entry->tsc = tsc;
5672
__entry->cpu_id = cpu_id;
5773
__entry->changed = changed;
5874
__entry->fast_switch = fast_switch;
5975
),
6076

61-
TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu cpu_id=%u changed=%s fast_switch=%s",
77+
TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u changed=%s fast_switch=%s",
6278
(unsigned long)__entry->min_perf,
6379
(unsigned long)__entry->target_perf,
6480
(unsigned long)__entry->capacity,
81+
(unsigned long long)__entry->freq,
82+
(unsigned long long)__entry->mperf,
83+
(unsigned long long)__entry->aperf,
84+
(unsigned long long)__entry->tsc,
6585
(unsigned int)__entry->cpu_id,
6686
(__entry->changed) ? "true" : "false",
6787
(__entry->fast_switch) ? "true" : "false"

drivers/cpufreq/amd-pstate.c

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ MODULE_PARM_DESC(shared_mem,
6565

6666
static struct cpufreq_driver amd_pstate_driver;
6767

68+
/**
69+
* struct amd_aperf_mperf
70+
* @aperf: actual performance frequency clock count
71+
* @mperf: maximum performance frequency clock count
72+
* @tsc: time stamp counter
73+
*/
74+
struct amd_aperf_mperf {
75+
u64 aperf;
76+
u64 mperf;
77+
u64 tsc;
78+
};
79+
6880
/**
6981
* struct amd_cpudata - private CPU data for AMD P-State
7082
* @cpu: CPU number
@@ -81,6 +93,9 @@ static struct cpufreq_driver amd_pstate_driver;
8193
* @min_freq: the frequency that mapped to lowest_perf
8294
* @nominal_freq: the frequency that mapped to nominal_perf
8395
* @lowest_nonlinear_freq: the frequency that mapped to lowest_nonlinear_perf
96+
* @cur: Difference of Aperf/Mperf/tsc count between last and current sample
97+
* @prev: Last Aperf/Mperf/tsc count value read from register
98+
* @freq: current cpu frequency value
8499
* @boost_supported: check whether the Processor or SBIOS supports boost mode
85100
*
86101
* The amd_cpudata is key private data for each CPU thread in AMD P-State, and
@@ -102,6 +117,10 @@ struct amd_cpudata {
102117
u32 nominal_freq;
103118
u32 lowest_nonlinear_freq;
104119

120+
struct amd_aperf_mperf cur;
121+
struct amd_aperf_mperf prev;
122+
123+
u64 freq;
105124
bool boost_supported;
106125
};
107126

@@ -211,6 +230,39 @@ static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
211230
max_perf, fast_switch);
212231
}
213232

233+
static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
234+
{
235+
u64 aperf, mperf, tsc;
236+
unsigned long flags;
237+
238+
local_irq_save(flags);
239+
rdmsrl(MSR_IA32_APERF, aperf);
240+
rdmsrl(MSR_IA32_MPERF, mperf);
241+
tsc = rdtsc();
242+
243+
if (cpudata->prev.mperf == mperf || cpudata->prev.tsc == tsc) {
244+
local_irq_restore(flags);
245+
return false;
246+
}
247+
248+
local_irq_restore(flags);
249+
250+
cpudata->cur.aperf = aperf;
251+
cpudata->cur.mperf = mperf;
252+
cpudata->cur.tsc = tsc;
253+
cpudata->cur.aperf -= cpudata->prev.aperf;
254+
cpudata->cur.mperf -= cpudata->prev.mperf;
255+
cpudata->cur.tsc -= cpudata->prev.tsc;
256+
257+
cpudata->prev.aperf = aperf;
258+
cpudata->prev.mperf = mperf;
259+
cpudata->prev.tsc = tsc;
260+
261+
cpudata->freq = div64_u64((cpudata->cur.aperf * cpu_khz), cpudata->cur.mperf);
262+
263+
return true;
264+
}
265+
214266
static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
215267
u32 des_perf, u32 max_perf, bool fast_switch)
216268
{
@@ -226,8 +278,11 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
226278
value &= ~AMD_CPPC_MAX_PERF(~0L);
227279
value |= AMD_CPPC_MAX_PERF(max_perf);
228280

229-
trace_amd_pstate_perf(min_perf, des_perf, max_perf,
230-
cpudata->cpu, (value != prev), fast_switch);
281+
if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) {
282+
trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
283+
cpudata->cur.mperf, cpudata->cur.aperf, cpudata->cur.tsc,
284+
cpudata->cpu, (value != prev), fast_switch);
285+
}
231286

232287
if (value == prev)
233288
return;

0 commit comments

Comments
 (0)