lkml.org 
[lkml]   [2022]   [Mar]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 1/4] cpufreq: amd-pstate: Add more tracepoint for AMD P-State module
    Date
    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>
    ---
    drivers/cpufreq/amd-pstate-trace.h | 22 ++++++++++-
    drivers/cpufreq/amd-pstate.c | 59 +++++++++++++++++++++++++++++-
    2 files changed, 78 insertions(+), 3 deletions(-)

    diff --git a/drivers/cpufreq/amd-pstate-trace.h b/drivers/cpufreq/amd-pstate-trace.h
    index 647505957d4f..35f38ae67fb1 100644
    --- a/drivers/cpufreq/amd-pstate-trace.h
    +++ b/drivers/cpufreq/amd-pstate-trace.h
    @@ -27,6 +27,10 @@ TRACE_EVENT(amd_pstate_perf,
    TP_PROTO(unsigned long min_perf,
    unsigned long target_perf,
    unsigned long capacity,
    + u64 freq,
    + u64 mperf,
    + u64 aperf,
    + u64 tsc,
    unsigned int cpu_id,
    bool changed,
    bool fast_switch
    @@ -35,6 +39,10 @@ TRACE_EVENT(amd_pstate_perf,
    TP_ARGS(min_perf,
    target_perf,
    capacity,
    + freq,
    + mperf,
    + aperf,
    + tsc,
    cpu_id,
    changed,
    fast_switch
    @@ -44,6 +52,10 @@ TRACE_EVENT(amd_pstate_perf,
    __field(unsigned long, min_perf)
    __field(unsigned long, target_perf)
    __field(unsigned long, capacity)
    + __field(unsigned long long, freq)
    + __field(unsigned long long, mperf)
    + __field(unsigned long long, aperf)
    + __field(unsigned long long, tsc)
    __field(unsigned int, cpu_id)
    __field(bool, changed)
    __field(bool, fast_switch)
    @@ -53,15 +65,23 @@ TRACE_EVENT(amd_pstate_perf,
    __entry->min_perf = min_perf;
    __entry->target_perf = target_perf;
    __entry->capacity = capacity;
    + __entry->freq = freq;
    + __entry->mperf = mperf;
    + __entry->aperf = aperf;
    + __entry->tsc = tsc;
    __entry->cpu_id = cpu_id;
    __entry->changed = changed;
    __entry->fast_switch = fast_switch;
    ),

    - TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu cpu_id=%u changed=%s fast_switch=%s",
    + 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",
    (unsigned long)__entry->min_perf,
    (unsigned long)__entry->target_perf,
    (unsigned long)__entry->capacity,
    + (unsigned long long)__entry->freq,
    + (unsigned long long)__entry->mperf,
    + (unsigned long long)__entry->aperf,
    + (unsigned long long)__entry->tsc,
    (unsigned int)__entry->cpu_id,
    (__entry->changed) ? "true" : "false",
    (__entry->fast_switch) ? "true" : "false"
    diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
    index 9ce75ed11f8e..7be38bc6a673 100644
    --- a/drivers/cpufreq/amd-pstate.c
    +++ b/drivers/cpufreq/amd-pstate.c
    @@ -65,6 +65,18 @@ MODULE_PARM_DESC(shared_mem,

    static struct cpufreq_driver amd_pstate_driver;

    +/**
    + * struct amd_aperf_mperf
    + * @aperf: actual performance frequency clock count
    + * @mperf: maximum performance frequency clock count
    + * @tsc: time stamp counter
    + */
    +struct amd_aperf_mperf {
    + u64 aperf;
    + u64 mperf;
    + u64 tsc;
    +};
    +
    /**
    * struct amd_cpudata - private CPU data for AMD P-State
    * @cpu: CPU number
    @@ -81,6 +93,9 @@ static struct cpufreq_driver amd_pstate_driver;
    * @min_freq: the frequency that mapped to lowest_perf
    * @nominal_freq: the frequency that mapped to nominal_perf
    * @lowest_nonlinear_freq: the frequency that mapped to lowest_nonlinear_perf
    + * @cur: Difference of Aperf/Mperf/tsc count between last and current sample
    + * @prev: Last Aperf/Mperf/tsc count value read from register
    + * @freq: current cpu frequency value
    * @boost_supported: check whether the Processor or SBIOS supports boost mode
    *
    * The amd_cpudata is key private data for each CPU thread in AMD P-State, and
    @@ -102,6 +117,10 @@ struct amd_cpudata {
    u32 nominal_freq;
    u32 lowest_nonlinear_freq;

    + struct amd_aperf_mperf cur;
    + struct amd_aperf_mperf prev;
    +
    + u64 freq;
    bool boost_supported;
    };

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

    +static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
    +{
    + u64 aperf, mperf, tsc;
    + unsigned long flags;
    +
    + local_irq_save(flags);
    + rdmsrl(MSR_IA32_APERF, aperf);
    + rdmsrl(MSR_IA32_MPERF, mperf);
    + tsc = rdtsc();
    +
    + if (cpudata->prev.mperf == mperf || cpudata->prev.tsc == tsc) {
    + local_irq_restore(flags);
    + return false;
    + }
    +
    + local_irq_restore(flags);
    +
    + cpudata->cur.aperf = aperf;
    + cpudata->cur.mperf = mperf;
    + cpudata->cur.tsc = tsc;
    + cpudata->cur.aperf -= cpudata->prev.aperf;
    + cpudata->cur.mperf -= cpudata->prev.mperf;
    + cpudata->cur.tsc -= cpudata->prev.tsc;
    +
    + cpudata->prev.aperf = aperf;
    + cpudata->prev.mperf = mperf;
    + cpudata->prev.tsc = tsc;
    +
    + cpudata->freq = div64_u64((cpudata->cur.aperf * cpu_khz), cpudata->cur.mperf);
    +
    + return true;
    +}
    +
    static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
    u32 des_perf, u32 max_perf, bool fast_switch)
    {
    @@ -226,8 +278,11 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
    value &= ~AMD_CPPC_MAX_PERF(~0L);
    value |= AMD_CPPC_MAX_PERF(max_perf);

    - trace_amd_pstate_perf(min_perf, des_perf, max_perf,
    - cpudata->cpu, (value != prev), fast_switch);
    + if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) {
    + trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
    + cpudata->cur.mperf, cpudata->cur.aperf, cpudata->cur.tsc,
    + cpudata->cpu, (value != prev), fast_switch);
    + }

    if (value == prev)
    return;
    --
    2.27.0
    \
     
     \ /
      Last update: 2022-03-09 02:26    [W:4.659 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site