tools/power turbostat: add optional APIC X2APIC columns
Add APIC and X2APIC columns to the topology section. They are disabled-by-default -- enable like so: --debug or --enable APIC,X2APIC Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
@@ -56,7 +56,7 @@ name as necessary to disambiguate it from others is necessary. Note that option
|
|||||||
.PP
|
.PP
|
||||||
\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
|
\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
|
||||||
.PP
|
.PP
|
||||||
\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec" and "Time_Of_Day_Seconds".
|
\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec", "Time_Of_Day_Seconds", "APIC" and "X2APIC".
|
||||||
The column name "all" can be used to enable all disabled-by-default built-in counters.
|
The column name "all" can be used to enable all disabled-by-default built-in counters.
|
||||||
.PP
|
.PP
|
||||||
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
|
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
|
|||||||
unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
|
unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
|
||||||
unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
|
unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
|
||||||
unsigned int has_misc_feature_control;
|
unsigned int has_misc_feature_control;
|
||||||
|
unsigned int first_counter_read = 1;
|
||||||
|
|
||||||
#define RAPL_PKG (1 << 0)
|
#define RAPL_PKG (1 << 0)
|
||||||
/* 0x610 MSR_PKG_POWER_LIMIT */
|
/* 0x610 MSR_PKG_POWER_LIMIT */
|
||||||
@@ -170,6 +171,8 @@ struct thread_data {
|
|||||||
unsigned long long irq_count;
|
unsigned long long irq_count;
|
||||||
unsigned int smi_count;
|
unsigned int smi_count;
|
||||||
unsigned int cpu_id;
|
unsigned int cpu_id;
|
||||||
|
unsigned int apic_id;
|
||||||
|
unsigned int x2apic_id;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
|
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
|
||||||
#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
|
#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
|
||||||
@@ -435,10 +438,10 @@ struct msr_counter bic[] = {
|
|||||||
{ 0x0, "CPUGFX%" },
|
{ 0x0, "CPUGFX%" },
|
||||||
{ 0x0, "Core" },
|
{ 0x0, "Core" },
|
||||||
{ 0x0, "CPU" },
|
{ 0x0, "CPU" },
|
||||||
|
{ 0x0, "APIC" },
|
||||||
|
{ 0x0, "X2APIC" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
|
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
|
||||||
#define BIC_USEC (1ULL << 0)
|
#define BIC_USEC (1ULL << 0)
|
||||||
#define BIC_TOD (1ULL << 1)
|
#define BIC_TOD (1ULL << 1)
|
||||||
@@ -488,11 +491,13 @@ struct msr_counter bic[] = {
|
|||||||
#define BIC_CPUGFX (1ULL << 45)
|
#define BIC_CPUGFX (1ULL << 45)
|
||||||
#define BIC_Core (1ULL << 46)
|
#define BIC_Core (1ULL << 46)
|
||||||
#define BIC_CPU (1ULL << 47)
|
#define BIC_CPU (1ULL << 47)
|
||||||
|
#define BIC_APIC (1ULL << 48)
|
||||||
|
#define BIC_X2APIC (1ULL << 49)
|
||||||
|
|
||||||
#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD)
|
#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
|
||||||
|
|
||||||
unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
|
unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
|
||||||
unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs;
|
unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
|
||||||
|
|
||||||
#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
|
#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
|
||||||
#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
|
#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
|
||||||
@@ -603,6 +608,10 @@ void print_header(char *delim)
|
|||||||
outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_CPU))
|
if (DO_BIC(BIC_CPU))
|
||||||
outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
|
||||||
|
if (DO_BIC(BIC_APIC))
|
||||||
|
outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));
|
||||||
|
if (DO_BIC(BIC_X2APIC))
|
||||||
|
outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_Avg_MHz))
|
if (DO_BIC(BIC_Avg_MHz))
|
||||||
outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_Busy))
|
if (DO_BIC(BIC_Busy))
|
||||||
@@ -882,6 +891,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
|
|||||||
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
|
||||||
if (DO_BIC(BIC_CPU))
|
if (DO_BIC(BIC_CPU))
|
||||||
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
|
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
|
||||||
|
if (DO_BIC(BIC_APIC))
|
||||||
|
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
|
||||||
|
if (DO_BIC(BIC_X2APIC))
|
||||||
|
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
|
||||||
} else {
|
} else {
|
||||||
if (DO_BIC(BIC_Package)) {
|
if (DO_BIC(BIC_Package)) {
|
||||||
if (p)
|
if (p)
|
||||||
@@ -906,6 +919,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
|
|||||||
}
|
}
|
||||||
if (DO_BIC(BIC_CPU))
|
if (DO_BIC(BIC_CPU))
|
||||||
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
|
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
|
||||||
|
if (DO_BIC(BIC_APIC))
|
||||||
|
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);
|
||||||
|
if (DO_BIC(BIC_X2APIC))
|
||||||
|
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DO_BIC(BIC_Avg_MHz))
|
if (DO_BIC(BIC_Avg_MHz))
|
||||||
@@ -1233,6 +1250,12 @@ delta_thread(struct thread_data *new, struct thread_data *old,
|
|||||||
int i;
|
int i;
|
||||||
struct msr_counter *mp;
|
struct msr_counter *mp;
|
||||||
|
|
||||||
|
/* we run cpuid just the 1st time, copy the results */
|
||||||
|
if (DO_BIC(BIC_APIC))
|
||||||
|
new->apic_id = old->apic_id;
|
||||||
|
if (DO_BIC(BIC_X2APIC))
|
||||||
|
new->x2apic_id = old->x2apic_id;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the timestamps from start of measurement interval are in "old"
|
* the timestamps from start of measurement interval are in "old"
|
||||||
* the timestamp from end of measurement interval are in "new"
|
* the timestamp from end of measurement interval are in "new"
|
||||||
@@ -1395,6 +1418,12 @@ int sum_counters(struct thread_data *t, struct core_data *c,
|
|||||||
int i;
|
int i;
|
||||||
struct msr_counter *mp;
|
struct msr_counter *mp;
|
||||||
|
|
||||||
|
/* copy un-changing apic_id's */
|
||||||
|
if (DO_BIC(BIC_APIC))
|
||||||
|
average.threads.apic_id = t->apic_id;
|
||||||
|
if (DO_BIC(BIC_X2APIC))
|
||||||
|
average.threads.x2apic_id = t->x2apic_id;
|
||||||
|
|
||||||
/* remember first tv_begin */
|
/* remember first tv_begin */
|
||||||
if (average.threads.tv_begin.tv_sec == 0)
|
if (average.threads.tv_begin.tv_sec == 0)
|
||||||
average.threads.tv_begin = t->tv_begin;
|
average.threads.tv_begin = t->tv_begin;
|
||||||
@@ -1621,6 +1650,34 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_apic_id(struct thread_data *t)
|
||||||
|
{
|
||||||
|
unsigned int eax, ebx, ecx, edx, max_level;
|
||||||
|
|
||||||
|
eax = ebx = ecx = edx = 0;
|
||||||
|
|
||||||
|
if (!genuine_intel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
__cpuid(0, max_level, ebx, ecx, edx);
|
||||||
|
|
||||||
|
__cpuid(1, eax, ebx, ecx, edx);
|
||||||
|
t->apic_id = (ebx >> 24) & 0xf;
|
||||||
|
|
||||||
|
if (max_level < 0xb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!DO_BIC(BIC_X2APIC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ecx = 0;
|
||||||
|
__cpuid(0xb, eax, ebx, ecx, edx);
|
||||||
|
t->x2apic_id = edx;
|
||||||
|
|
||||||
|
if (debug && (t->apic_id != t->x2apic_id))
|
||||||
|
fprintf(stderr, "cpu%d: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_counters(...)
|
* get_counters(...)
|
||||||
* migrate to cpu
|
* migrate to cpu
|
||||||
@@ -1634,7 +1691,6 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
|||||||
struct msr_counter *mp;
|
struct msr_counter *mp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
gettimeofday(&t->tv_begin, (struct timezone *)NULL);
|
gettimeofday(&t->tv_begin, (struct timezone *)NULL);
|
||||||
|
|
||||||
if (cpu_migrate(cpu)) {
|
if (cpu_migrate(cpu)) {
|
||||||
@@ -1642,6 +1698,8 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (first_counter_read)
|
||||||
|
get_apic_id(t);
|
||||||
retry:
|
retry:
|
||||||
t->tsc = rdtsc(); /* we are running on local CPU of interest */
|
t->tsc = rdtsc(); /* we are running on local CPU of interest */
|
||||||
|
|
||||||
@@ -2881,6 +2939,7 @@ void do_sleep(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void turbostat_loop()
|
void turbostat_loop()
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
@@ -2894,6 +2953,7 @@ restart:
|
|||||||
|
|
||||||
snapshot_proc_sysfs_files();
|
snapshot_proc_sysfs_files();
|
||||||
retval = for_all_cpus(get_counters, EVEN_COUNTERS);
|
retval = for_all_cpus(get_counters, EVEN_COUNTERS);
|
||||||
|
first_counter_read = 0;
|
||||||
if (retval < -1) {
|
if (retval < -1) {
|
||||||
exit(retval);
|
exit(retval);
|
||||||
} else if (retval == -1) {
|
} else if (retval == -1) {
|
||||||
@@ -4655,7 +4715,6 @@ void process_cpuid()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in /dev/cpu/ return success for names that are numbers
|
* in /dev/cpu/ return success for names that are numbers
|
||||||
* ie. filter out ".", "..", "microcode".
|
* ie. filter out ".", "..", "microcode".
|
||||||
@@ -4949,6 +5008,7 @@ int fork_it(char **argv)
|
|||||||
|
|
||||||
snapshot_proc_sysfs_files();
|
snapshot_proc_sysfs_files();
|
||||||
status = for_all_cpus(get_counters, EVEN_COUNTERS);
|
status = for_all_cpus(get_counters, EVEN_COUNTERS);
|
||||||
|
first_counter_read = 0;
|
||||||
if (status)
|
if (status)
|
||||||
exit(status);
|
exit(status);
|
||||||
/* clear affinity side-effect of get_counters() */
|
/* clear affinity side-effect of get_counters() */
|
||||||
@@ -5384,7 +5444,7 @@ void cmdline(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
/* --enable specified counter */
|
/* --enable specified counter */
|
||||||
bic_enabled |= bic_lookup(optarg, SHOW_LIST);
|
bic_enabled = bic_enabled | bic_lookup(optarg, SHOW_LIST);
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
debug++;
|
debug++;
|
||||||
@@ -5468,7 +5528,6 @@ void cmdline(int argc, char **argv)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
outf = stderr;
|
outf = stderr;
|
||||||
|
|
||||||
cmdline(argc, argv);
|
cmdline(argc, argv);
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
|
|||||||
Reference in New Issue
Block a user