mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Merge branch 'pm-tools'
Merge power management utilities changes for 5.18-rc1: - Add tracer tool for the amd-pstate driver (Jinzhou Su). - Fix PC6 displaying in turbostat on some systems (Artem Bityutskiy). - Add AMD P-State support to the cpupower utility (Huang Rui). * pm-tools: Documentation: amd-pstate: add tracer tool introduction tools/power/x86/amd_pstate_tracer: Add tracer tool for AMD P-state tools/power/x86/intel_pstate_tracer: make tracer as a module cpufreq: amd-pstate: Add more tracepoint for AMD P-State module turbostat: fix PC6 displaying on some systems cpupower: Add "perf" option to print AMD P-State information cpupower: Add function to print AMD P-State performance capabilities cpupower: Move print_speed function into misc helper cpupower: Enable boost state support for AMD P-State module cpupower: Add AMD P-State sysfs definition and access helper cpupower: Introduce ACPI CPPC library cpupower: Add the function to get the sysfs value from specific table cpupower: Initial AMD P-State capability cpupower: Add the function to check AMD P-State enabled cpupower: Add AMD P-State capability flag tools/power/cpupower/{ToDo => TODO}: Rename the todo file tools: cpupower: fix typo in cpupower-idle-set(1) manpage
This commit is contained in:
commit
ec3d8b8365
@ -369,6 +369,32 @@ governor (for the policies it is attached to), or by the ``CPUFreq`` core (for t
|
||||
policies with other scaling governors).
|
||||
|
||||
|
||||
Tracer Tool
|
||||
-------------
|
||||
|
||||
``amd_pstate_tracer.py`` can record and parse ``amd-pstate`` trace log, then
|
||||
generate performance plots. This utility can be used to debug and tune the
|
||||
performance of ``amd-pstate`` driver. The tracer tool needs to import intel
|
||||
pstate tracer.
|
||||
|
||||
Tracer tool located in ``linux/tools/power/x86/amd_pstate_tracer``. It can be
|
||||
used in two ways. If trace file is available, then directly parse the file
|
||||
with command ::
|
||||
|
||||
./amd_pstate_trace.py [-c cpus] -t <trace_file> -n <test_name>
|
||||
|
||||
Or generate trace file with root privilege, then parse and plot with command ::
|
||||
|
||||
sudo ./amd_pstate_trace.py [-c cpus] -n <test_name> -i <interval> [-m kbytes]
|
||||
|
||||
The test result can be found in ``results/test_name``. Following is the example
|
||||
about part of the output. ::
|
||||
|
||||
common_cpu common_secs common_usecs min_perf des_perf max_perf freq mperf apef tsc load duration_ms sample_num elapsed_time common_comm
|
||||
CPU_005 712 116384 39 49 166 0.7565 9645075 2214891 38431470 25.1 11.646 469 2.496 kworker/5:0-40
|
||||
CPU_006 712 116408 39 49 166 0.6769 8950227 1839034 37192089 24.06 11.272 470 2.496 kworker/6:0-1264
|
||||
|
||||
|
||||
Reference
|
||||
===========
|
||||
|
||||
|
@ -1002,6 +1002,7 @@ L: linux-pm@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/admin-guide/pm/amd-pstate.rst
|
||||
F: drivers/cpufreq/amd-pstate*
|
||||
F: tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
|
||||
|
||||
AMD PTDMA DRIVER
|
||||
M: Sanjay R Mehta <sanju.mehta@amd.com>
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -143,9 +143,9 @@ UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
|
||||
utils/helpers/bitmask.h \
|
||||
utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
|
||||
|
||||
LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h
|
||||
LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
|
||||
LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
|
||||
LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h lib/acpi_cppc.h
|
||||
LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c lib/acpi_cppc.c
|
||||
LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o lib/acpi_cppc.o
|
||||
LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
|
||||
|
||||
override CFLAGS += -pipe
|
||||
|
59
tools/power/cpupower/lib/acpi_cppc.c
Normal file
59
tools/power/cpupower/lib/acpi_cppc.c
Normal file
@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cpupower_intern.h"
|
||||
#include "acpi_cppc.h"
|
||||
|
||||
/* ACPI CPPC sysfs access ***********************************************/
|
||||
|
||||
static int acpi_cppc_read_file(unsigned int cpu, const char *fname,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/acpi_cppc/%s",
|
||||
cpu, fname);
|
||||
return cpupower_read_sysfs(path, buf, buflen);
|
||||
}
|
||||
|
||||
static const char * const acpi_cppc_value_files[] = {
|
||||
[HIGHEST_PERF] = "highest_perf",
|
||||
[LOWEST_PERF] = "lowest_perf",
|
||||
[NOMINAL_PERF] = "nominal_perf",
|
||||
[LOWEST_NONLINEAR_PERF] = "lowest_nonlinear_perf",
|
||||
[LOWEST_FREQ] = "lowest_freq",
|
||||
[NOMINAL_FREQ] = "nominal_freq",
|
||||
[REFERENCE_PERF] = "reference_perf",
|
||||
[WRAPAROUND_TIME] = "wraparound_time"
|
||||
};
|
||||
|
||||
unsigned long acpi_cppc_get_data(unsigned int cpu, enum acpi_cppc_value which)
|
||||
{
|
||||
unsigned long long value;
|
||||
unsigned int len;
|
||||
char linebuf[MAX_LINE_LEN];
|
||||
char *endp;
|
||||
|
||||
if (which >= MAX_CPPC_VALUE_FILES)
|
||||
return 0;
|
||||
|
||||
len = acpi_cppc_read_file(cpu, acpi_cppc_value_files[which],
|
||||
linebuf, sizeof(linebuf));
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
value = strtoull(linebuf, &endp, 0);
|
||||
|
||||
if (endp == linebuf || errno == ERANGE)
|
||||
return 0;
|
||||
|
||||
return value;
|
||||
}
|
21
tools/power/cpupower/lib/acpi_cppc.h
Normal file
21
tools/power/cpupower/lib/acpi_cppc.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __ACPI_CPPC_H__
|
||||
#define __ACPI_CPPC_H__
|
||||
|
||||
enum acpi_cppc_value {
|
||||
HIGHEST_PERF,
|
||||
LOWEST_PERF,
|
||||
NOMINAL_PERF,
|
||||
LOWEST_NONLINEAR_PERF,
|
||||
LOWEST_FREQ,
|
||||
NOMINAL_FREQ,
|
||||
REFERENCE_PERF,
|
||||
WRAPAROUND_TIME,
|
||||
MAX_CPPC_VALUE_FILES
|
||||
};
|
||||
|
||||
unsigned long acpi_cppc_get_data(unsigned int cpu,
|
||||
enum acpi_cppc_value which);
|
||||
|
||||
#endif /* _ACPI_CPPC_H */
|
@ -83,20 +83,21 @@ static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
|
||||
[STATS_NUM_TRANSITIONS] = "stats/total_trans"
|
||||
};
|
||||
|
||||
|
||||
static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
|
||||
enum cpufreq_value which)
|
||||
unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu,
|
||||
const char **table,
|
||||
unsigned int index,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned long value;
|
||||
unsigned int len;
|
||||
char linebuf[MAX_LINE_LEN];
|
||||
char *endp;
|
||||
|
||||
if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
|
||||
if (!table || index >= size || !table[index])
|
||||
return 0;
|
||||
|
||||
len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
|
||||
linebuf, sizeof(linebuf));
|
||||
len = sysfs_cpufreq_read_file(cpu, table[index], linebuf,
|
||||
sizeof(linebuf));
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
@ -109,6 +110,14 @@ static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
|
||||
enum cpufreq_value which)
|
||||
{
|
||||
return cpufreq_get_sysfs_value_from_table(cpu, cpufreq_value_files,
|
||||
which,
|
||||
MAX_CPUFREQ_VALUE_READ_FILES);
|
||||
}
|
||||
|
||||
/* read access to files which contain one string */
|
||||
|
||||
enum cpufreq_string {
|
||||
@ -124,7 +133,7 @@ static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
|
||||
|
||||
|
||||
static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
|
||||
enum cpufreq_string which)
|
||||
enum cpufreq_string which)
|
||||
{
|
||||
char linebuf[MAX_LINE_LEN];
|
||||
char *result;
|
||||
|
@ -203,6 +203,18 @@ int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
|
||||
int cpufreq_set_frequency(unsigned int cpu,
|
||||
unsigned long target_frequency);
|
||||
|
||||
/*
|
||||
* get the sysfs value from specific table
|
||||
*
|
||||
* Read the value with the sysfs file name from specific table. Does
|
||||
* only work if the cpufreq driver has the specific sysfs interfaces.
|
||||
*/
|
||||
|
||||
unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu,
|
||||
const char **table,
|
||||
unsigned int index,
|
||||
unsigned int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -53,6 +53,9 @@ human\-readable output for the \-f, \-w, \-s and \-y parameters.
|
||||
\fB\-n\fR \fB\-\-no-rounding\fR
|
||||
Output frequencies and latencies without rounding off values.
|
||||
.TP
|
||||
\fB\-c\fR \fB\-\-perf\fR
|
||||
Get performances and frequencies capabilities of CPPC, by reading it from hardware (only available on the hardware with CPPC).
|
||||
.TP
|
||||
.SH "REMARKS"
|
||||
.LP
|
||||
By default only values of core zero are displayed. How to display settings of
|
||||
|
@ -4,7 +4,7 @@
|
||||
cpupower\-idle\-set \- Utility to set cpu idle state specific kernel options
|
||||
.SH "SYNTAX"
|
||||
.LP
|
||||
cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
|
||||
cpupower [ \-c cpulist ] idle\-set [\fIoptions\fP]
|
||||
.SH "DESCRIPTION"
|
||||
.LP
|
||||
The cpupower idle\-set subcommand allows to set cpu idle, also called cpu
|
||||
|
@ -84,43 +84,6 @@ static void proc_cpufreq_output(void)
|
||||
}
|
||||
|
||||
static int no_rounding;
|
||||
static void print_speed(unsigned long speed)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
if (no_rounding) {
|
||||
if (speed > 1000000)
|
||||
printf("%u.%06u GHz", ((unsigned int) speed/1000000),
|
||||
((unsigned int) speed%1000000));
|
||||
else if (speed > 1000)
|
||||
printf("%u.%03u MHz", ((unsigned int) speed/1000),
|
||||
(unsigned int) (speed%1000));
|
||||
else
|
||||
printf("%lu kHz", speed);
|
||||
} else {
|
||||
if (speed > 1000000) {
|
||||
tmp = speed%10000;
|
||||
if (tmp >= 5000)
|
||||
speed += 10000;
|
||||
printf("%u.%02u GHz", ((unsigned int) speed/1000000),
|
||||
((unsigned int) (speed%1000000)/10000));
|
||||
} else if (speed > 100000) {
|
||||
tmp = speed%1000;
|
||||
if (tmp >= 500)
|
||||
speed += 1000;
|
||||
printf("%u MHz", ((unsigned int) speed/1000));
|
||||
} else if (speed > 1000) {
|
||||
tmp = speed%100;
|
||||
if (tmp >= 50)
|
||||
speed += 100;
|
||||
printf("%u.%01u MHz", ((unsigned int) speed/1000),
|
||||
((unsigned int) (speed%1000)/100));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void print_duration(unsigned long duration)
|
||||
{
|
||||
unsigned long tmp;
|
||||
@ -183,9 +146,12 @@ static int get_boost_mode_x86(unsigned int cpu)
|
||||
printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
|
||||
printf(_(" Active: %s\n"), active ? _("yes") : _("no"));
|
||||
|
||||
if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
|
||||
cpupower_cpu_info.family >= 0x10) ||
|
||||
cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
|
||||
if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
|
||||
cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) {
|
||||
return 0;
|
||||
} else if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
|
||||
cpupower_cpu_info.family >= 0x10) ||
|
||||
cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
|
||||
ret = decode_pstates(cpu, b_states, pstates, &pstate_no);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -254,11 +220,11 @@ static int get_boost_mode(unsigned int cpu)
|
||||
if (freqs) {
|
||||
printf(_(" boost frequency steps: "));
|
||||
while (freqs->next) {
|
||||
print_speed(freqs->frequency);
|
||||
print_speed(freqs->frequency, no_rounding);
|
||||
printf(", ");
|
||||
freqs = freqs->next;
|
||||
}
|
||||
print_speed(freqs->frequency);
|
||||
print_speed(freqs->frequency, no_rounding);
|
||||
printf("\n");
|
||||
cpufreq_put_available_frequencies(freqs);
|
||||
}
|
||||
@ -277,7 +243,7 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (human) {
|
||||
print_speed(freq);
|
||||
print_speed(freq, no_rounding);
|
||||
} else
|
||||
printf("%lu", freq);
|
||||
printf(_(" (asserted by call to kernel)\n"));
|
||||
@ -296,7 +262,7 @@ static int get_freq_hardware(unsigned int cpu, unsigned int human)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (human) {
|
||||
print_speed(freq);
|
||||
print_speed(freq, no_rounding);
|
||||
} else
|
||||
printf("%lu", freq);
|
||||
printf(_(" (asserted by call to hardware)\n"));
|
||||
@ -316,9 +282,9 @@ static int get_hardware_limits(unsigned int cpu, unsigned int human)
|
||||
|
||||
if (human) {
|
||||
printf(_(" hardware limits: "));
|
||||
print_speed(min);
|
||||
print_speed(min, no_rounding);
|
||||
printf(" - ");
|
||||
print_speed(max);
|
||||
print_speed(max, no_rounding);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%lu %lu\n", min, max);
|
||||
@ -350,9 +316,9 @@ static int get_policy(unsigned int cpu)
|
||||
return -EINVAL;
|
||||
}
|
||||
printf(_(" current policy: frequency should be within "));
|
||||
print_speed(policy->min);
|
||||
print_speed(policy->min, no_rounding);
|
||||
printf(_(" and "));
|
||||
print_speed(policy->max);
|
||||
print_speed(policy->max, no_rounding);
|
||||
|
||||
printf(".\n ");
|
||||
printf(_("The governor \"%s\" may decide which speed to use\n"
|
||||
@ -436,7 +402,7 @@ static int get_freq_stats(unsigned int cpu, unsigned int human)
|
||||
struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
|
||||
while (stats) {
|
||||
if (human) {
|
||||
print_speed(stats->frequency);
|
||||
print_speed(stats->frequency, no_rounding);
|
||||
printf(":%.2f%%",
|
||||
(100.0 * stats->time_in_state) / total_time);
|
||||
} else
|
||||
@ -472,6 +438,17 @@ static int get_latency(unsigned int cpu, unsigned int human)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --performance / -c */
|
||||
|
||||
static int get_perf_cap(unsigned int cpu)
|
||||
{
|
||||
if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
|
||||
cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE)
|
||||
amd_pstate_show_perf_and_freq(cpu, no_rounding);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_output_one(unsigned int cpu)
|
||||
{
|
||||
struct cpufreq_available_frequencies *freqs;
|
||||
@ -486,11 +463,11 @@ static void debug_output_one(unsigned int cpu)
|
||||
if (freqs) {
|
||||
printf(_(" available frequency steps: "));
|
||||
while (freqs->next) {
|
||||
print_speed(freqs->frequency);
|
||||
print_speed(freqs->frequency, no_rounding);
|
||||
printf(", ");
|
||||
freqs = freqs->next;
|
||||
}
|
||||
print_speed(freqs->frequency);
|
||||
print_speed(freqs->frequency, no_rounding);
|
||||
printf("\n");
|
||||
cpufreq_put_available_frequencies(freqs);
|
||||
}
|
||||
@ -500,6 +477,7 @@ static void debug_output_one(unsigned int cpu)
|
||||
if (get_freq_hardware(cpu, 1) < 0)
|
||||
get_freq_kernel(cpu, 1);
|
||||
get_boost_mode(cpu);
|
||||
get_perf_cap(cpu);
|
||||
}
|
||||
|
||||
static struct option info_opts[] = {
|
||||
@ -518,6 +496,7 @@ static struct option info_opts[] = {
|
||||
{"proc", no_argument, NULL, 'o'},
|
||||
{"human", no_argument, NULL, 'm'},
|
||||
{"no-rounding", no_argument, NULL, 'n'},
|
||||
{"performance", no_argument, NULL, 'c'},
|
||||
{ },
|
||||
};
|
||||
|
||||
@ -531,7 +510,7 @@ int cmd_freq_info(int argc, char **argv)
|
||||
int output_param = 0;
|
||||
|
||||
do {
|
||||
ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts,
|
||||
ret = getopt_long(argc, argv, "oefwldpgrasmybnc", info_opts,
|
||||
NULL);
|
||||
switch (ret) {
|
||||
case '?':
|
||||
@ -554,6 +533,7 @@ int cmd_freq_info(int argc, char **argv)
|
||||
case 'e':
|
||||
case 's':
|
||||
case 'y':
|
||||
case 'c':
|
||||
if (output_param) {
|
||||
output_param = -1;
|
||||
cont = 0;
|
||||
@ -660,6 +640,9 @@ int cmd_freq_info(int argc, char **argv)
|
||||
case 'y':
|
||||
ret = get_latency(cpu, human);
|
||||
break;
|
||||
case 'c':
|
||||
ret = get_perf_cap(cpu);
|
||||
break;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -8,7 +8,10 @@
|
||||
#include <pci/pci.h>
|
||||
|
||||
#include "helpers/helpers.h"
|
||||
#include "cpufreq.h"
|
||||
#include "acpi_cppc.h"
|
||||
|
||||
/* ACPI P-States Helper Functions for AMD Processors ***************/
|
||||
#define MSR_AMD_PSTATE_STATUS 0xc0010063
|
||||
#define MSR_AMD_PSTATE 0xc0010064
|
||||
#define MSR_AMD_PSTATE_LIMIT 0xc0010061
|
||||
@ -146,4 +149,78 @@ int amd_pci_get_num_boost_states(int *active, int *states)
|
||||
pci_cleanup(pci_acc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ACPI P-States Helper Functions for AMD Processors ***************/
|
||||
|
||||
/* AMD P-State Helper Functions ************************************/
|
||||
enum amd_pstate_value {
|
||||
AMD_PSTATE_HIGHEST_PERF,
|
||||
AMD_PSTATE_MAX_FREQ,
|
||||
AMD_PSTATE_LOWEST_NONLINEAR_FREQ,
|
||||
MAX_AMD_PSTATE_VALUE_READ_FILES,
|
||||
};
|
||||
|
||||
static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = {
|
||||
[AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf",
|
||||
[AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq",
|
||||
[AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq",
|
||||
};
|
||||
|
||||
static unsigned long amd_pstate_get_data(unsigned int cpu,
|
||||
enum amd_pstate_value value)
|
||||
{
|
||||
return cpufreq_get_sysfs_value_from_table(cpu,
|
||||
amd_pstate_value_files,
|
||||
value,
|
||||
MAX_AMD_PSTATE_VALUE_READ_FILES);
|
||||
}
|
||||
|
||||
void amd_pstate_boost_init(unsigned int cpu, int *support, int *active)
|
||||
{
|
||||
unsigned long highest_perf, nominal_perf, cpuinfo_min,
|
||||
cpuinfo_max, amd_pstate_max;
|
||||
|
||||
highest_perf = amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF);
|
||||
nominal_perf = acpi_cppc_get_data(cpu, NOMINAL_PERF);
|
||||
|
||||
*support = highest_perf > nominal_perf ? 1 : 0;
|
||||
if (!(*support))
|
||||
return;
|
||||
|
||||
cpufreq_get_hardware_limits(cpu, &cpuinfo_min, &cpuinfo_max);
|
||||
amd_pstate_max = amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ);
|
||||
|
||||
*active = cpuinfo_max == amd_pstate_max ? 1 : 0;
|
||||
}
|
||||
|
||||
void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)
|
||||
{
|
||||
printf(_(" AMD PSTATE Highest Performance: %lu. Maximum Frequency: "),
|
||||
amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF));
|
||||
/*
|
||||
* If boost isn't active, the cpuinfo_max doesn't indicate real max
|
||||
* frequency. So we read it back from amd-pstate sysfs entry.
|
||||
*/
|
||||
print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding);
|
||||
printf(".\n");
|
||||
|
||||
printf(_(" AMD PSTATE Nominal Performance: %lu. Nominal Frequency: "),
|
||||
acpi_cppc_get_data(cpu, NOMINAL_PERF));
|
||||
print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000,
|
||||
no_rounding);
|
||||
printf(".\n");
|
||||
|
||||
printf(_(" AMD PSTATE Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),
|
||||
acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF));
|
||||
print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ),
|
||||
no_rounding);
|
||||
printf(".\n");
|
||||
|
||||
printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "),
|
||||
acpi_cppc_get_data(cpu, LOWEST_PERF));
|
||||
print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding);
|
||||
printf(".\n");
|
||||
}
|
||||
|
||||
/* AMD P-State Helper Functions ************************************/
|
||||
#endif /* defined(__i386__) || defined(__x86_64__) */
|
||||
|
@ -149,6 +149,19 @@ out:
|
||||
if (ext_cpuid_level >= 0x80000008 &&
|
||||
cpuid_ebx(0x80000008) & (1 << 4))
|
||||
cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
|
||||
|
||||
if (cpupower_amd_pstate_enabled()) {
|
||||
cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATE;
|
||||
|
||||
/*
|
||||
* If AMD P-State is enabled, the firmware will treat
|
||||
* AMD P-State function as high priority.
|
||||
*/
|
||||
cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB;
|
||||
cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB_MSR;
|
||||
cpu_info->caps &= ~CPUPOWER_CAP_AMD_HW_PSTATE;
|
||||
cpu_info->caps &= ~CPUPOWER_CAP_AMD_PSTATEDEF;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_info->vendor == X86_VENDOR_INTEL) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "helpers/bitmask.h"
|
||||
#include <cpupower.h>
|
||||
@ -73,6 +74,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
|
||||
#define CPUPOWER_CAP_AMD_HW_PSTATE 0x00000100
|
||||
#define CPUPOWER_CAP_AMD_PSTATEDEF 0x00000200
|
||||
#define CPUPOWER_CAP_AMD_CPB_MSR 0x00000400
|
||||
#define CPUPOWER_CAP_AMD_PSTATE 0x00000800
|
||||
|
||||
#define CPUPOWER_AMD_CPBDIS 0x02000000
|
||||
|
||||
@ -135,6 +137,16 @@ extern int decode_pstates(unsigned int cpu, int boost_states,
|
||||
|
||||
extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
|
||||
int *active, int * states);
|
||||
|
||||
/* AMD P-State stuff **************************/
|
||||
bool cpupower_amd_pstate_enabled(void);
|
||||
void amd_pstate_boost_init(unsigned int cpu,
|
||||
int *support, int *active);
|
||||
void amd_pstate_show_perf_and_freq(unsigned int cpu,
|
||||
int no_rounding);
|
||||
|
||||
/* AMD P-State stuff **************************/
|
||||
|
||||
/*
|
||||
* CPUID functions returning a single datum
|
||||
*/
|
||||
@ -167,6 +179,15 @@ static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,
|
||||
int *active, int * states)
|
||||
{ return -1; }
|
||||
|
||||
static inline bool cpupower_amd_pstate_enabled(void)
|
||||
{ return false; }
|
||||
static inline void amd_pstate_boost_init(unsigned int cpu, int *support,
|
||||
int *active)
|
||||
{}
|
||||
static inline void amd_pstate_show_perf_and_freq(unsigned int cpu,
|
||||
int no_rounding)
|
||||
{}
|
||||
|
||||
/* cpuid and cpuinfo helpers **************************/
|
||||
|
||||
static inline unsigned int cpuid_eax(unsigned int op) { return 0; };
|
||||
@ -184,5 +205,6 @@ extern struct bitmask *offline_cpus;
|
||||
void get_cpustate(void);
|
||||
void print_online_cpus(void);
|
||||
void print_offline_cpus(void);
|
||||
void print_speed(unsigned long speed, int no_rounding);
|
||||
|
||||
#endif /* __CPUPOWERUTILS_HELPERS__ */
|
||||
|
@ -3,9 +3,11 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helpers/helpers.h"
|
||||
#include "helpers/sysfs.h"
|
||||
#include "cpufreq.h"
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
@ -39,6 +41,8 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) {
|
||||
amd_pstate_boost_init(cpu, support, active);
|
||||
} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
|
||||
*support = *active = 1;
|
||||
return 0;
|
||||
@ -83,6 +87,22 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cpupower_amd_pstate_enabled(void)
|
||||
{
|
||||
char *driver = cpufreq_get_driver(0);
|
||||
bool ret = false;
|
||||
|
||||
if (!driver)
|
||||
return ret;
|
||||
|
||||
if (!strcmp(driver, "amd-pstate"))
|
||||
ret = true;
|
||||
|
||||
cpufreq_put_driver(driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* #if defined(__i386__) || defined(__x86_64__) */
|
||||
|
||||
/* get_cpustate
|
||||
@ -144,3 +164,43 @@ void print_offline_cpus(void)
|
||||
printf(_("cpupower set operation was not performed on them\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print_speed
|
||||
*
|
||||
* Print the exact CPU frequency with appropriate unit
|
||||
*/
|
||||
void print_speed(unsigned long speed, int no_rounding)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
if (no_rounding) {
|
||||
if (speed > 1000000)
|
||||
printf("%u.%06u GHz", ((unsigned int)speed / 1000000),
|
||||
((unsigned int)speed % 1000000));
|
||||
else if (speed > 1000)
|
||||
printf("%u.%03u MHz", ((unsigned int)speed / 1000),
|
||||
(unsigned int)(speed % 1000));
|
||||
else
|
||||
printf("%lu kHz", speed);
|
||||
} else {
|
||||
if (speed > 1000000) {
|
||||
tmp = speed % 10000;
|
||||
if (tmp >= 5000)
|
||||
speed += 10000;
|
||||
printf("%u.%02u GHz", ((unsigned int)speed / 1000000),
|
||||
((unsigned int)(speed % 1000000) / 10000));
|
||||
} else if (speed > 100000) {
|
||||
tmp = speed % 1000;
|
||||
if (tmp >= 500)
|
||||
speed += 1000;
|
||||
printf("%u MHz", ((unsigned int)speed / 1000));
|
||||
} else if (speed > 1000) {
|
||||
tmp = speed % 100;
|
||||
if (tmp >= 50)
|
||||
speed += 100;
|
||||
printf("%u.%01u MHz", ((unsigned int)speed / 1000),
|
||||
((unsigned int)(speed % 1000) / 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
354
tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
Executable file
354
tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
Executable file
@ -0,0 +1,354 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
""" This utility can be used to debug and tune the performance of the
|
||||
AMD P-State driver. It imports intel_pstate_tracer to analyze AMD P-State
|
||||
trace event.
|
||||
|
||||
Prerequisites:
|
||||
Python version 2.7.x or higher
|
||||
gnuplot 5.0 or higher
|
||||
gnuplot-py 1.8 or higher
|
||||
(Most of the distributions have these required packages. They may be called
|
||||
gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... )
|
||||
|
||||
Kernel config for Linux trace is enabled
|
||||
|
||||
see print_help(): for Usage and Output details
|
||||
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from datetime import datetime
|
||||
import subprocess
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
import signal
|
||||
import sys
|
||||
import getopt
|
||||
import Gnuplot
|
||||
from numpy import *
|
||||
from decimal import *
|
||||
sys.path.append('../intel_pstate_tracer')
|
||||
#import intel_pstate_tracer
|
||||
import intel_pstate_tracer as ipt
|
||||
|
||||
__license__ = "GPL version 2"
|
||||
|
||||
MAX_CPUS = 256
|
||||
# Define the csv file columns
|
||||
C_COMM = 15
|
||||
C_ELAPSED = 14
|
||||
C_SAMPLE = 13
|
||||
C_DURATION = 12
|
||||
C_LOAD = 11
|
||||
C_TSC = 10
|
||||
C_APERF = 9
|
||||
C_MPERF = 8
|
||||
C_FREQ = 7
|
||||
C_MAX_PERF = 6
|
||||
C_DES_PERF = 5
|
||||
C_MIN_PERF = 4
|
||||
C_USEC = 3
|
||||
C_SEC = 2
|
||||
C_CPU = 1
|
||||
|
||||
global sample_num, last_sec_cpu, last_usec_cpu, start_time, test_name, trace_file
|
||||
|
||||
getcontext().prec = 11
|
||||
|
||||
sample_num =0
|
||||
last_sec_cpu = [0] * MAX_CPUS
|
||||
last_usec_cpu = [0] * MAX_CPUS
|
||||
|
||||
def plot_per_cpu_freq(cpu_index):
|
||||
""" Plot per cpu frequency """
|
||||
|
||||
file_name = 'cpu{:0>3}.csv'.format(cpu_index)
|
||||
if os.path.exists(file_name):
|
||||
output_png = "cpu%03d_frequency.png" % cpu_index
|
||||
g_plot = ipt.common_gnuplot_settings()
|
||||
g_plot('set output "' + output_png + '"')
|
||||
g_plot('set yrange [0:7]')
|
||||
g_plot('set ytics 0, 1')
|
||||
g_plot('set ylabel "CPU Frequency (GHz)"')
|
||||
g_plot('set title "{} : frequency : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
|
||||
g_plot('set ylabel "CPU frequency"')
|
||||
g_plot('set key off')
|
||||
ipt.set_4_plot_linestyles(g_plot)
|
||||
g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_FREQ))
|
||||
|
||||
def plot_per_cpu_des_perf(cpu_index):
|
||||
""" Plot per cpu desired perf """
|
||||
|
||||
file_name = 'cpu{:0>3}.csv'.format(cpu_index)
|
||||
if os.path.exists(file_name):
|
||||
output_png = "cpu%03d_des_perf.png" % cpu_index
|
||||
g_plot = ipt.common_gnuplot_settings()
|
||||
g_plot('set output "' + output_png + '"')
|
||||
g_plot('set yrange [0:255]')
|
||||
g_plot('set ylabel "des perf"')
|
||||
g_plot('set title "{} : cpu des perf : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
|
||||
g_plot('set key off')
|
||||
ipt.set_4_plot_linestyles(g_plot)
|
||||
g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DES_PERF))
|
||||
|
||||
def plot_per_cpu_load(cpu_index):
|
||||
""" Plot per cpu load """
|
||||
|
||||
file_name = 'cpu{:0>3}.csv'.format(cpu_index)
|
||||
if os.path.exists(file_name):
|
||||
output_png = "cpu%03d_load.png" % cpu_index
|
||||
g_plot = ipt.common_gnuplot_settings()
|
||||
g_plot('set output "' + output_png + '"')
|
||||
g_plot('set yrange [0:100]')
|
||||
g_plot('set ytics 0, 10')
|
||||
g_plot('set ylabel "CPU load (percent)"')
|
||||
g_plot('set title "{} : cpu load : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
|
||||
g_plot('set key off')
|
||||
ipt.set_4_plot_linestyles(g_plot)
|
||||
g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
|
||||
|
||||
def plot_all_cpu_frequency():
|
||||
""" Plot all cpu frequencies """
|
||||
|
||||
output_png = 'all_cpu_frequencies.png'
|
||||
g_plot = ipt.common_gnuplot_settings()
|
||||
g_plot('set output "' + output_png + '"')
|
||||
g_plot('set ylabel "CPU Frequency (GHz)"')
|
||||
g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(test_name, datetime.now()))
|
||||
|
||||
title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
|
||||
plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
|
||||
g_plot('title_list = "{}"'.format(title_list))
|
||||
g_plot(plot_str)
|
||||
|
||||
def plot_all_cpu_des_perf():
|
||||
""" Plot all cpu desired perf """
|
||||
|
||||
output_png = 'all_cpu_des_perf.png'
|
||||
g_plot = ipt.common_gnuplot_settings()
|
||||
g_plot('set output "' + output_png + '"')
|
||||
g_plot('set ylabel "des perf"')
|
||||
g_plot('set title "{} : cpu des perf : {:%F %H:%M}"'.format(test_name, datetime.now()))
|
||||
|
||||
title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
|
||||
plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 255 ps 1 title i".format(C_ELAPSED, C_DES_PERF)
|
||||
g_plot('title_list = "{}"'.format(title_list))
|
||||
g_plot(plot_str)
|
||||
|
||||
def plot_all_cpu_load():
|
||||
""" Plot all cpu load """
|
||||
|
||||
output_png = 'all_cpu_load.png'
|
||||
g_plot = ipt.common_gnuplot_settings()
|
||||
g_plot('set output "' + output_png + '"')
|
||||
g_plot('set yrange [0:100]')
|
||||
g_plot('set ylabel "CPU load (percent)"')
|
||||
g_plot('set title "{} : cpu load : {:%F %H:%M}"'.format(test_name, datetime.now()))
|
||||
|
||||
title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
|
||||
plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 255 ps 1 title i".format(C_ELAPSED, C_LOAD)
|
||||
g_plot('title_list = "{}"'.format(title_list))
|
||||
g_plot(plot_str)
|
||||
|
||||
def store_csv(cpu_int, time_pre_dec, time_post_dec, min_perf, des_perf, max_perf, freq_ghz, mperf, aperf, tsc, common_comm, load, duration_ms, sample_num, elapsed_time, cpu_mask):
|
||||
""" Store master csv file information """
|
||||
|
||||
global graph_data_present
|
||||
|
||||
if cpu_mask[cpu_int] == 0:
|
||||
return
|
||||
|
||||
try:
|
||||
f_handle = open('cpu.csv', 'a')
|
||||
string_buffer = "CPU_%03u, %05u, %06u, %u, %u, %u, %.4f, %u, %u, %u, %.2f, %.3f, %u, %.3f, %s\n" % (cpu_int, int(time_pre_dec), int(time_post_dec), int(min_perf), int(des_perf), int(max_perf), freq_ghz, int(mperf), int(aperf), int(tsc), load, duration_ms, sample_num, elapsed_time, common_comm)
|
||||
f_handle.write(string_buffer)
|
||||
f_handle.close()
|
||||
except:
|
||||
print('IO error cpu.csv')
|
||||
return
|
||||
|
||||
graph_data_present = True;
|
||||
|
||||
|
||||
def cleanup_data_files():
|
||||
""" clean up existing data files """
|
||||
|
||||
if os.path.exists('cpu.csv'):
|
||||
os.remove('cpu.csv')
|
||||
f_handle = open('cpu.csv', 'a')
|
||||
f_handle.write('common_cpu, common_secs, common_usecs, min_perf, des_perf, max_perf, freq, mperf, aperf, tsc, load, duration_ms, sample_num, elapsed_time, common_comm')
|
||||
f_handle.write('\n')
|
||||
f_handle.close()
|
||||
|
||||
def read_trace_data(file_name, cpu_mask):
|
||||
""" Read and parse trace data """
|
||||
|
||||
global current_max_cpu
|
||||
global sample_num, last_sec_cpu, last_usec_cpu, start_time
|
||||
|
||||
try:
|
||||
data = open(file_name, 'r').read()
|
||||
except:
|
||||
print('Error opening ', file_name)
|
||||
sys.exit(2)
|
||||
|
||||
for line in data.splitlines():
|
||||
search_obj = \
|
||||
re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?amd_min_perf=)(\d+)(.*?amd_des_perf=)(\d+)(.*?amd_max_perf=)(\d+)(.*?freq=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)'
|
||||
, line)
|
||||
|
||||
if search_obj:
|
||||
cpu = search_obj.group(3)
|
||||
cpu_int = int(cpu)
|
||||
cpu = str(cpu_int)
|
||||
|
||||
time_pre_dec = search_obj.group(6)
|
||||
time_post_dec = search_obj.group(8)
|
||||
min_perf = search_obj.group(10)
|
||||
des_perf = search_obj.group(12)
|
||||
max_perf = search_obj.group(14)
|
||||
freq = search_obj.group(16)
|
||||
mperf = search_obj.group(18)
|
||||
aperf = search_obj.group(20)
|
||||
tsc = search_obj.group(22)
|
||||
|
||||
common_comm = search_obj.group(2).replace(' ', '')
|
||||
|
||||
if sample_num == 0 :
|
||||
start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
|
||||
sample_num += 1
|
||||
|
||||
if last_sec_cpu[cpu_int] == 0 :
|
||||
last_sec_cpu[cpu_int] = time_pre_dec
|
||||
last_usec_cpu[cpu_int] = time_post_dec
|
||||
else :
|
||||
duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
|
||||
duration_ms = Decimal(duration_us) / Decimal(1000)
|
||||
last_sec_cpu[cpu_int] = time_pre_dec
|
||||
last_usec_cpu[cpu_int] = time_post_dec
|
||||
elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
|
||||
load = Decimal(int(mperf)*100)/ Decimal(tsc)
|
||||
freq_ghz = Decimal(freq)/Decimal(1000000)
|
||||
store_csv(cpu_int, time_pre_dec, time_post_dec, min_perf, des_perf, max_perf, freq_ghz, mperf, aperf, tsc, common_comm, load, duration_ms, sample_num, elapsed_time, cpu_mask)
|
||||
|
||||
if cpu_int > current_max_cpu:
|
||||
current_max_cpu = cpu_int
|
||||
# Now separate the main overall csv file into per CPU csv files.
|
||||
ipt.split_csv(current_max_cpu, cpu_mask)
|
||||
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
print(' SIGINT: Forcing cleanup before exit.')
|
||||
if interval:
|
||||
ipt.disable_trace(trace_file)
|
||||
ipt.clear_trace_file()
|
||||
ipt.free_trace_buffer()
|
||||
sys.exit(0)
|
||||
|
||||
trace_file = "/sys/kernel/debug/tracing/events/amd_cpu/enable"
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
interval = ""
|
||||
file_name = ""
|
||||
cpu_list = ""
|
||||
test_name = ""
|
||||
memory = "10240"
|
||||
graph_data_present = False;
|
||||
|
||||
valid1 = False
|
||||
valid2 = False
|
||||
|
||||
cpu_mask = zeros((MAX_CPUS,), dtype=int)
|
||||
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
|
||||
except getopt.GetoptError:
|
||||
ipt.print_help('amd_pstate')
|
||||
sys.exit(2)
|
||||
for opt, arg in opts:
|
||||
if opt == '-h':
|
||||
print()
|
||||
sys.exit()
|
||||
elif opt in ("-t", "--trace_file"):
|
||||
valid1 = True
|
||||
location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
|
||||
file_name = os.path.join(location, arg)
|
||||
elif opt in ("-i", "--interval"):
|
||||
valid1 = True
|
||||
interval = arg
|
||||
elif opt in ("-c", "--cpu"):
|
||||
cpu_list = arg
|
||||
elif opt in ("-n", "--name"):
|
||||
valid2 = True
|
||||
test_name = arg
|
||||
elif opt in ("-m", "--memory"):
|
||||
memory = arg
|
||||
|
||||
if not (valid1 and valid2):
|
||||
ipt.print_help('amd_pstate')
|
||||
sys.exit()
|
||||
|
||||
if cpu_list:
|
||||
for p in re.split("[,]", cpu_list):
|
||||
if int(p) < MAX_CPUS :
|
||||
cpu_mask[int(p)] = 1
|
||||
else:
|
||||
for i in range (0, MAX_CPUS):
|
||||
cpu_mask[i] = 1
|
||||
|
||||
if not os.path.exists('results'):
|
||||
os.mkdir('results')
|
||||
ipt.fix_ownership('results')
|
||||
|
||||
os.chdir('results')
|
||||
if os.path.exists(test_name):
|
||||
print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
|
||||
sys.exit()
|
||||
os.mkdir(test_name)
|
||||
ipt.fix_ownership(test_name)
|
||||
os.chdir(test_name)
|
||||
|
||||
cur_version = sys.version_info
|
||||
print('python version (should be >= 2.7):')
|
||||
print(cur_version)
|
||||
|
||||
cleanup_data_files()
|
||||
|
||||
if interval:
|
||||
file_name = "/sys/kernel/debug/tracing/trace"
|
||||
ipt.clear_trace_file()
|
||||
ipt.set_trace_buffer_size(memory)
|
||||
ipt.enable_trace(trace_file)
|
||||
time.sleep(int(interval))
|
||||
ipt.disable_trace(trace_file)
|
||||
|
||||
current_max_cpu = 0
|
||||
|
||||
read_trace_data(file_name, cpu_mask)
|
||||
|
||||
if interval:
|
||||
ipt.clear_trace_file()
|
||||
ipt.free_trace_buffer()
|
||||
|
||||
if graph_data_present == False:
|
||||
print('No valid data to plot')
|
||||
sys.exit(2)
|
||||
|
||||
for cpu_no in range(0, current_max_cpu + 1):
|
||||
plot_per_cpu_freq(cpu_no)
|
||||
plot_per_cpu_des_perf(cpu_no)
|
||||
plot_per_cpu_load(cpu_no)
|
||||
|
||||
plot_all_cpu_des_perf()
|
||||
plot_all_cpu_frequency()
|
||||
plot_all_cpu_load()
|
||||
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for f in files:
|
||||
ipt.fix_ownership(f)
|
||||
|
||||
os.chdir('../../')
|
@ -63,7 +63,7 @@ C_USEC = 3
|
||||
C_SEC = 2
|
||||
C_CPU = 1
|
||||
|
||||
global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname
|
||||
global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname, trace_file
|
||||
|
||||
# 11 digits covers uptime to 115 days
|
||||
getcontext().prec = 11
|
||||
@ -72,17 +72,17 @@ sample_num =0
|
||||
last_sec_cpu = [0] * MAX_CPUS
|
||||
last_usec_cpu = [0] * MAX_CPUS
|
||||
|
||||
def print_help():
|
||||
print('intel_pstate_tracer.py:')
|
||||
def print_help(driver_name):
|
||||
print('%s_tracer.py:'%driver_name)
|
||||
print(' Usage:')
|
||||
print(' If the trace file is available, then to simply parse and plot, use (sudo not required):')
|
||||
print(' ./intel_pstate_tracer.py [-c cpus] -t <trace_file> -n <test_name>')
|
||||
print(' ./%s_tracer.py [-c cpus] -t <trace_file> -n <test_name>'%driver_name)
|
||||
print(' Or')
|
||||
print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
|
||||
print(' ./%s_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>'%driver_name)
|
||||
print(' To generate trace file, parse and plot, use (sudo required):')
|
||||
print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>')
|
||||
print(' sudo ./%s_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>'%driver_name)
|
||||
print(' Or')
|
||||
print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>')
|
||||
print(' sudo ./%s_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>'%driver_name)
|
||||
print(' Optional argument:')
|
||||
print(' cpus: comma separated list of CPUs')
|
||||
print(' kbytes: Kilo bytes of memory per CPU to allocate to the trace buffer. Default: 10240')
|
||||
@ -323,7 +323,7 @@ def set_4_plot_linestyles(g_plot):
|
||||
g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
|
||||
g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
|
||||
|
||||
def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz):
|
||||
def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz, cpu_mask):
|
||||
""" Store master csv file information """
|
||||
|
||||
global graph_data_present
|
||||
@ -342,11 +342,9 @@ def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _t
|
||||
|
||||
graph_data_present = True;
|
||||
|
||||
def split_csv():
|
||||
def split_csv(current_max_cpu, cpu_mask):
|
||||
""" seperate the all csv file into per CPU csv files. """
|
||||
|
||||
global current_max_cpu
|
||||
|
||||
if os.path.exists('cpu.csv'):
|
||||
for index in range(0, current_max_cpu + 1):
|
||||
if cpu_mask[int(index)] != 0:
|
||||
@ -381,27 +379,25 @@ def clear_trace_file():
|
||||
print('IO error clearing trace file ')
|
||||
sys.exit(2)
|
||||
|
||||
def enable_trace():
|
||||
def enable_trace(trace_file):
|
||||
""" Enable trace """
|
||||
|
||||
try:
|
||||
open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
|
||||
, 'w').write("1")
|
||||
open(trace_file,'w').write("1")
|
||||
except:
|
||||
print('IO error enabling trace ')
|
||||
sys.exit(2)
|
||||
|
||||
def disable_trace():
|
||||
def disable_trace(trace_file):
|
||||
""" Disable trace """
|
||||
|
||||
try:
|
||||
open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
|
||||
, 'w').write("0")
|
||||
open(trace_file, 'w').write("0")
|
||||
except:
|
||||
print('IO error disabling trace ')
|
||||
sys.exit(2)
|
||||
|
||||
def set_trace_buffer_size():
|
||||
def set_trace_buffer_size(memory):
|
||||
""" Set trace buffer size """
|
||||
|
||||
try:
|
||||
@ -421,7 +417,7 @@ def free_trace_buffer():
|
||||
print('IO error freeing trace buffer ')
|
||||
sys.exit(2)
|
||||
|
||||
def read_trace_data(filename):
|
||||
def read_trace_data(filename, cpu_mask):
|
||||
""" Read and parse trace data """
|
||||
|
||||
global current_max_cpu
|
||||
@ -481,135 +477,137 @@ def read_trace_data(filename):
|
||||
tsc_ghz = Decimal(0)
|
||||
if duration_ms != Decimal(0) :
|
||||
tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
|
||||
store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz)
|
||||
store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz, cpu_mask)
|
||||
|
||||
if cpu_int > current_max_cpu:
|
||||
current_max_cpu = cpu_int
|
||||
# End of for each trace line loop
|
||||
# Now seperate the main overall csv file into per CPU csv files.
|
||||
split_csv()
|
||||
split_csv(current_max_cpu, cpu_mask)
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
print(' SIGINT: Forcing cleanup before exit.')
|
||||
if interval:
|
||||
disable_trace()
|
||||
disable_trace(trace_file)
|
||||
clear_trace_file()
|
||||
# Free the memory
|
||||
free_trace_buffer()
|
||||
sys.exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
if __name__ == "__main__":
|
||||
trace_file = "/sys/kernel/debug/tracing/events/power/pstate_sample/enable"
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
interval = ""
|
||||
filename = ""
|
||||
cpu_list = ""
|
||||
testname = ""
|
||||
memory = "10240"
|
||||
graph_data_present = False;
|
||||
interval = ""
|
||||
filename = ""
|
||||
cpu_list = ""
|
||||
testname = ""
|
||||
memory = "10240"
|
||||
graph_data_present = False;
|
||||
|
||||
valid1 = False
|
||||
valid2 = False
|
||||
valid1 = False
|
||||
valid2 = False
|
||||
|
||||
cpu_mask = zeros((MAX_CPUS,), dtype=int)
|
||||
cpu_mask = zeros((MAX_CPUS,), dtype=int)
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
|
||||
except getopt.GetoptError:
|
||||
print_help()
|
||||
sys.exit(2)
|
||||
for opt, arg in opts:
|
||||
if opt == '-h':
|
||||
print()
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
|
||||
except getopt.GetoptError:
|
||||
print_help('intel_pstate')
|
||||
sys.exit(2)
|
||||
for opt, arg in opts:
|
||||
if opt == '-h':
|
||||
print_help('intel_pstate')
|
||||
sys.exit()
|
||||
elif opt in ("-t", "--trace_file"):
|
||||
valid1 = True
|
||||
location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
|
||||
filename = os.path.join(location, arg)
|
||||
elif opt in ("-i", "--interval"):
|
||||
valid1 = True
|
||||
interval = arg
|
||||
elif opt in ("-c", "--cpu"):
|
||||
cpu_list = arg
|
||||
elif opt in ("-n", "--name"):
|
||||
valid2 = True
|
||||
testname = arg
|
||||
elif opt in ("-m", "--memory"):
|
||||
memory = arg
|
||||
|
||||
if not (valid1 and valid2):
|
||||
print_help('intel_pstate')
|
||||
sys.exit()
|
||||
elif opt in ("-t", "--trace_file"):
|
||||
valid1 = True
|
||||
location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
|
||||
filename = os.path.join(location, arg)
|
||||
elif opt in ("-i", "--interval"):
|
||||
valid1 = True
|
||||
interval = arg
|
||||
elif opt in ("-c", "--cpu"):
|
||||
cpu_list = arg
|
||||
elif opt in ("-n", "--name"):
|
||||
valid2 = True
|
||||
testname = arg
|
||||
elif opt in ("-m", "--memory"):
|
||||
memory = arg
|
||||
|
||||
if not (valid1 and valid2):
|
||||
print_help()
|
||||
sys.exit()
|
||||
if cpu_list:
|
||||
for p in re.split("[,]", cpu_list):
|
||||
if int(p) < MAX_CPUS :
|
||||
cpu_mask[int(p)] = 1
|
||||
else:
|
||||
for i in range (0, MAX_CPUS):
|
||||
cpu_mask[i] = 1
|
||||
|
||||
if cpu_list:
|
||||
for p in re.split("[,]", cpu_list):
|
||||
if int(p) < MAX_CPUS :
|
||||
cpu_mask[int(p)] = 1
|
||||
else:
|
||||
for i in range (0, MAX_CPUS):
|
||||
cpu_mask[i] = 1
|
||||
if not os.path.exists('results'):
|
||||
os.mkdir('results')
|
||||
# The regular user needs to own the directory, not root.
|
||||
fix_ownership('results')
|
||||
|
||||
if not os.path.exists('results'):
|
||||
os.mkdir('results')
|
||||
os.chdir('results')
|
||||
if os.path.exists(testname):
|
||||
print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
|
||||
sys.exit()
|
||||
os.mkdir(testname)
|
||||
# The regular user needs to own the directory, not root.
|
||||
fix_ownership('results')
|
||||
fix_ownership(testname)
|
||||
os.chdir(testname)
|
||||
|
||||
os.chdir('results')
|
||||
if os.path.exists(testname):
|
||||
print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
|
||||
sys.exit()
|
||||
os.mkdir(testname)
|
||||
# The regular user needs to own the directory, not root.
|
||||
fix_ownership(testname)
|
||||
os.chdir(testname)
|
||||
# Temporary (or perhaps not)
|
||||
cur_version = sys.version_info
|
||||
print('python version (should be >= 2.7):')
|
||||
print(cur_version)
|
||||
|
||||
# Temporary (or perhaps not)
|
||||
cur_version = sys.version_info
|
||||
print('python version (should be >= 2.7):')
|
||||
print(cur_version)
|
||||
# Left as "cleanup" for potential future re-run ability.
|
||||
cleanup_data_files()
|
||||
|
||||
# Left as "cleanup" for potential future re-run ability.
|
||||
cleanup_data_files()
|
||||
if interval:
|
||||
filename = "/sys/kernel/debug/tracing/trace"
|
||||
clear_trace_file()
|
||||
set_trace_buffer_size(memory)
|
||||
enable_trace(trace_file)
|
||||
print('Sleeping for ', interval, 'seconds')
|
||||
time.sleep(int(interval))
|
||||
disable_trace(trace_file)
|
||||
|
||||
if interval:
|
||||
filename = "/sys/kernel/debug/tracing/trace"
|
||||
clear_trace_file()
|
||||
set_trace_buffer_size()
|
||||
enable_trace()
|
||||
print('Sleeping for ', interval, 'seconds')
|
||||
time.sleep(int(interval))
|
||||
disable_trace()
|
||||
current_max_cpu = 0
|
||||
|
||||
current_max_cpu = 0
|
||||
read_trace_data(filename, cpu_mask)
|
||||
|
||||
read_trace_data(filename)
|
||||
if interval:
|
||||
clear_trace_file()
|
||||
# Free the memory
|
||||
free_trace_buffer()
|
||||
|
||||
if interval:
|
||||
clear_trace_file()
|
||||
# Free the memory
|
||||
free_trace_buffer()
|
||||
if graph_data_present == False:
|
||||
print('No valid data to plot')
|
||||
sys.exit(2)
|
||||
|
||||
if graph_data_present == False:
|
||||
print('No valid data to plot')
|
||||
sys.exit(2)
|
||||
for cpu_no in range(0, current_max_cpu + 1):
|
||||
plot_perf_busy_with_sample(cpu_no)
|
||||
plot_perf_busy(cpu_no)
|
||||
plot_durations(cpu_no)
|
||||
plot_loads(cpu_no)
|
||||
|
||||
for cpu_no in range(0, current_max_cpu + 1):
|
||||
plot_perf_busy_with_sample(cpu_no)
|
||||
plot_perf_busy(cpu_no)
|
||||
plot_durations(cpu_no)
|
||||
plot_loads(cpu_no)
|
||||
plot_pstate_cpu_with_sample()
|
||||
plot_pstate_cpu()
|
||||
plot_load_cpu()
|
||||
plot_frequency_cpu()
|
||||
plot_duration_cpu()
|
||||
plot_scaled_cpu()
|
||||
plot_boost_cpu()
|
||||
plot_ghz_cpu()
|
||||
|
||||
plot_pstate_cpu_with_sample()
|
||||
plot_pstate_cpu()
|
||||
plot_load_cpu()
|
||||
plot_frequency_cpu()
|
||||
plot_duration_cpu()
|
||||
plot_scaled_cpu()
|
||||
plot_boost_cpu()
|
||||
plot_ghz_cpu()
|
||||
# It is preferrable, but not necessary, that the regular user owns the files, not root.
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for f in files:
|
||||
fix_ownership(f)
|
||||
|
||||
# It is preferrable, but not necessary, that the regular user owns the files, not root.
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for f in files:
|
||||
fix_ownership(f)
|
||||
|
||||
os.chdir('../../')
|
||||
os.chdir('../../')
|
||||
|
@ -2323,7 +2323,7 @@ int skx_pkg_cstate_limits[16] =
|
||||
};
|
||||
|
||||
int icx_pkg_cstate_limits[16] =
|
||||
{ PCL__0, PCL__2, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
|
||||
{ PCL__0, PCL__2, PCL__6, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
|
||||
PCLRSV, PCLRSV
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user