/*
* turbostat -- show CPU frequency and C-state residency
* on modern Intel turbo-capable processors.
*
* Copyright (c) 2010, Intel Corporation.
* Len Brown <len.brown@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <ctype.h>
#define MSR_TSC 0x10
#define MSR_NEHALEM_PLATFORM_INFO 0xCE
#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
#define MSR_APERF 0xE8
#define MSR_MPERF 0xE7
#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
#define MSR_PKG_C3_RESIDENCY 0x3F8
#define MSR_PKG_C6_RESIDENCY 0x3F9
#define MSR_PKG_C7_RESIDENCY 0x3FA /* SNB only */
#define MSR_CORE_C3_RESIDENCY 0x3FC
#define MSR_CORE_C6_RESIDENCY 0x3FD
#define MSR_CORE_C7_RESIDENCY 0x3FE /* SNB only */
char *proc_stat = "/proc/stat";
unsigned int interval_sec = 5; /* set with -i interval_sec */
unsigned int verbose; /* set with -v */
unsigned int skip_c0;
unsigned int skip_c1;
unsigned int do_nhm_cstates;
unsigned int do_snb_cstates;
unsigned int has_aperf;
unsigned int units = 1000000000; /* Ghz etc */
unsigned int genuine_intel;
unsigned int has_invariant_tsc;
unsigned int do_nehalem_platform_info;
unsigned int do_nehalem_turbo_ratio_limit;
unsigned int extra_msr_offset;
double bclk;
unsigned int show_pkg;
unsigned int show_core;
unsigned int show_cpu;
int aperf_mperf_unstable;
int backwards_count;
char *progname;
int need_reinitialize;
int num_cpus;
struct counters {
unsigned long long tsc; /* per thread */
unsigned long long aperf; /* per thread */
unsigned long long mperf; /* per thread */
unsigned long long c1; /* per thread (calculated) */
unsigned long long c3; /* per core */
unsigned long long c6; /* per core */
unsigned long long c7; /* per core */
unsigned long long pc2; /* per package */
unsigned long long pc3; /* per package */
unsigned long long pc6; /* per package */
unsigned long long pc7; /* per package */
unsigned long long extra_msr; /* per thread */
int pkg;
int core;
int cpu;
struct counters *next;
};
struct counters *cnt_even;
struct counters *cnt_odd;
struct counters *cnt_delta;
struct counters *cnt_average;
struct timeval tv_even;
struct timeval tv_odd;
struct timeval tv_delta;
unsigned long long get_msr(int cpu, off_t offset)
{
ssize_t retval;
unsigned long long msr;
char pathname[32];
int fd;
sprintf(pathname, "/dev/cpu/%d/msr", cpu);
fd = open(pathname, O_RDONLY);
if (fd < 0) {
perror(pathname);
need_reinitialize = 1;
return 0;
}
retval = pread(fd, &msr, sizeof msr, offset);
if (retval != sizeof msr) {
fprintf(stderr, "cpu%d pread(..., 0x%zx) = %jd\n",
cpu, offset, retval);
exit(-2);
}
close(fd);
return msr;
}
void print_header(void)
{
if (show_pkg)
fprintf(stderr, "pkg ");
if (show_core)
fprintf(stderr, "core");
if (show_cpu)
fprintf(stderr, " CPU");
if (do_nhm_cstates)
fprintf(stderr, " %%c0 ");
if (has_aperf)
fprintf(stderr, " GHz");
fprintf(stderr, " TSC");
if (do_nhm_cstates)
fprintf(stderr, " %%c1 ");
if (do_nhm_cstates)
fprintf(stderr, " %%c3 ");
if (do_nhm_cstates)
fprintf(stderr, " %%c6 ");
if (do_snb_cstates)
fprintf(stderr,