aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/acpi/Makefile18
-rw-r--r--tools/power/acpi/acpidump.859
-rw-r--r--tools/power/acpi/acpidump.c560
-rw-r--r--tools/power/x86/turbostat/turbostat.855
-rw-r--r--tools/power/x86/turbostat/turbostat.c214
5 files changed, 870 insertions, 36 deletions
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
new file mode 100644
index 000000000000..6b9cf7a987c7
--- /dev/null
+++ b/tools/power/acpi/Makefile
@@ -0,0 +1,18 @@
1PROG= acpidump
2SRCS= acpidump.c
3KERNEL_INCLUDE := ../../../include
4CFLAGS += -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE)
5
6all: acpidump
7$(PROG) : $(SRCS)
8 $(CC) $(CFLAGS) $(SRCS) -o $(PROG)
9
10CLEANFILES= $(PROG)
11
12clean :
13 rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~
14
15install :
16 install acpidump /usr/bin/acpidump
17 install acpidump.8 /usr/share/man/man8
18
diff --git a/tools/power/acpi/acpidump.8 b/tools/power/acpi/acpidump.8
new file mode 100644
index 000000000000..adfa99166e5e
--- /dev/null
+++ b/tools/power/acpi/acpidump.8
@@ -0,0 +1,59 @@
1.TH ACPIDUMP 8
2.SH NAME
3acpidump \- Dump system's ACPI tables to an ASCII file.
4.SH SYNOPSIS
5.ft B
6.B acpidump > acpidump.out
7.SH DESCRIPTION
8\fBacpidump \fP dumps the systems ACPI tables to an ASCII file
9appropriate for attaching to a bug report.
10
11Subsequently, they can be processed by utilities in the ACPICA package.
12.SS Options
13no options worth worrying about.
14.PP
15.SH EXAMPLE
16
17.nf
18# acpidump > acpidump.out
19
20$ acpixtract -a acpidump.out
21 Acpi table [DSDT] - 15974 bytes written to DSDT.dat
22 Acpi table [FACS] - 64 bytes written to FACS.dat
23 Acpi table [FACP] - 116 bytes written to FACP.dat
24 Acpi table [APIC] - 120 bytes written to APIC.dat
25 Acpi table [MCFG] - 60 bytes written to MCFG.dat
26 Acpi table [SSDT] - 444 bytes written to SSDT1.dat
27 Acpi table [SSDT] - 439 bytes written to SSDT2.dat
28 Acpi table [SSDT] - 439 bytes written to SSDT3.dat
29 Acpi table [SSDT] - 439 bytes written to SSDT4.dat
30 Acpi table [SSDT] - 439 bytes written to SSDT5.dat
31 Acpi table [RSDT] - 76 bytes written to RSDT.dat
32 Acpi table [RSDP] - 20 bytes written to RSDP.dat
33
34$ iasl -d *.dat
35...
36.fi
37creates *.dsl, a human readable form which can be edited
38and compiled using iasl.
39
40
41.SH NOTES
42
43.B "acpidump "
44must be run as root.
45
46.SH REFERENCES
47ACPICA: https://acpica.org/
48
49.SH FILES
50.ta
51.nf
52/dev/mem
53/sys/firmware/acpi/tables/dynamic/*
54.fi
55
56.PP
57.SH AUTHOR
58.nf
59Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c
new file mode 100644
index 000000000000..07779871421c
--- /dev/null
+++ b/tools/power/acpi/acpidump.c
@@ -0,0 +1,560 @@
1/*
2 * (c) Alexey Starikovskiy, Intel, 2005-2006.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
16 * 3. Neither the names of the above-listed copyright holders nor the names
17 * of any contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * NO WARRANTY
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGES.
36 */
37
38#ifdef DEFINE_ALTERNATE_TYPES
39/* hack to enable building old application with new headers -lenb */
40#define acpi_fadt_descriptor acpi_table_fadt
41#define acpi_rsdp_descriptor acpi_table_rsdp
42#define DSDT_SIG ACPI_SIG_DSDT
43#define FACS_SIG ACPI_SIG_FACS
44#define FADT_SIG ACPI_SIG_FADT
45#define xfirmware_ctrl Xfacs
46#define firmware_ctrl facs
47
48typedef int s32;
49typedef unsigned char u8;
50typedef unsigned short u16;
51typedef unsigned int u32;
52typedef unsigned long long u64;
53typedef long long s64;
54#endif
55
56#include <sys/mman.h>
57#include <sys/types.h>
58#include <sys/stat.h>
59#include <fcntl.h>
60#include <stdio.h>
61#include <string.h>
62#include <unistd.h>
63#include <getopt.h>
64
65#include <sys/types.h>
66#include <dirent.h>
67
68#include <acpi/acconfig.h>
69#include <acpi/platform/acenv.h>
70#include <acpi/actypes.h>
71#include <acpi/actbl.h>
72
73static inline u8 checksum(u8 * buffer, u32 length)
74{
75 u8 sum = 0, *i = buffer;
76 buffer += length;
77 for (; i < buffer; sum += *(i++));
78 return sum;
79}
80
81static unsigned long psz, addr, length;
82static int print, connect, skip;
83static u8 select_sig[4];
84
85static unsigned long read_efi_systab( void )
86{
87 char buffer[80];
88 unsigned long addr;
89 FILE *f = fopen("/sys/firmware/efi/systab", "r");
90 if (f) {
91 while (fgets(buffer, 80, f)) {
92 if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1)
93 return addr;
94 }
95 fclose(f);
96 }
97 return 0;
98}
99
100static u8 *acpi_map_memory(unsigned long where, unsigned length)
101{
102 unsigned long offset;
103 u8 *there;
104 int fd = open("/dev/mem", O_RDONLY);
105 if (fd < 0) {
106 fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n");
107 exit(1);
108 }
109 offset = where % psz;
110 there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE,
111 fd, where - offset);
112 close(fd);
113 if (there == MAP_FAILED) return 0;
114 return (there + offset);
115}
116
117static void acpi_unmap_memory(u8 * there, unsigned length)
118{
119 unsigned long offset = (unsigned long)there % psz;
120 munmap(there - offset, length + offset);
121}
122
123static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig)
124{
125 unsigned size;
126 struct acpi_table_header *tbl = (struct acpi_table_header *)
127 acpi_map_memory(where, sizeof(struct acpi_table_header));
128 if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0;
129 size = tbl->length;
130 acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header));
131 return (struct acpi_table_header *)acpi_map_memory(where, size);
132}
133
134static void acpi_unmap_table(struct acpi_table_header *tbl)
135{
136 acpi_unmap_memory((u8 *)tbl, tbl->length);
137}
138
139static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length)
140{
141 struct acpi_rsdp_descriptor *rsdp;
142 u8 *i, *end = begin + length;
143 /* Search from given start address for the requested length */
144 for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) {
145 /* The signature and checksum must both be correct */
146 if (memcmp((char *)i, "RSD PTR ", 8)) continue;
147 rsdp = (struct acpi_rsdp_descriptor *)i;
148 /* Signature matches, check the appropriate checksum */
149 if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ?
150 ACPI_RSDP_CHECKSUM_LENGTH :
151 ACPI_RSDP_XCHECKSUM_LENGTH))
152 /* Checksum valid, we have found a valid RSDP */
153 return rsdp;
154 }
155 /* Searched entire block, no RSDP was found */
156 return 0;
157}
158
159/*
160 * Output data
161 */
162static void acpi_show_data(int fd, u8 * data, int size)
163{
164 char buffer[256];
165 int len;
166 int i, remain = size;
167 while (remain > 0) {
168 len = snprintf(buffer, 256, " %04x:", size - remain);
169 for (i = 0; i < 16 && i < remain; i++) {
170 len +=
171 snprintf(&buffer[len], 256 - len, " %02x", data[i]);
172 }
173 for (; i < 16; i++) {
174 len += snprintf(&buffer[len], 256 - len, " ");
175 }
176 len += snprintf(&buffer[len], 256 - len, " ");
177 for (i = 0; i < 16 && i < remain; i++) {
178 buffer[len++] = (isprint(data[i])) ? data[i] : '.';
179 }
180 buffer[len++] = '\n';
181 write(fd, buffer, len);
182 data += 16;
183 remain -= 16;
184 }
185}
186
187/*
188 * Output ACPI table
189 */
190static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr)
191{
192 char buff[80];
193 int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr);
194 write(fd, buff, len);
195 acpi_show_data(fd, (u8 *) table, table->length);
196 buff[0] = '\n';
197 write(fd, buff, 1);
198}
199
200static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr)
201{
202 static int select_done = 0;
203 if (!select_sig[0]) {
204 if (print) {
205 acpi_show_table(fd, tbl, addr);
206 } else {
207 write(fd, tbl, tbl->length);
208 }
209 } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) {
210 if (skip > 0) {
211 --skip;
212 return;
213 }
214 if (print) {
215 acpi_show_table(fd, tbl, addr);
216 } else {
217 write(fd, tbl, tbl->length);
218 }
219 select_done = 1;
220 }
221}
222
223static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) {
224 struct acpi_fadt_descriptor x;
225 unsigned long addr;
226 size_t len = sizeof(struct acpi_fadt_descriptor);
227 if (len > tbl->length) len = tbl->length;
228 memcpy(&x, tbl, len);
229 x.header.length = len;
230 if (checksum((u8 *)tbl, len)) {
231 fprintf(stderr, "Wrong checksum for FADT!\n");
232 }
233 if (x.header.length >= 148 && x.Xdsdt) {
234 addr = (unsigned long)x.Xdsdt;
235 if (connect) {
236 x.Xdsdt = lseek(fd, 0, SEEK_CUR);
237 }
238 } else if (x.header.length >= 44 && x.dsdt) {
239 addr = (unsigned long)x.dsdt;
240 if (connect) {
241 x.dsdt = lseek(fd, 0, SEEK_CUR);
242 }
243 } else {
244 fprintf(stderr, "No DSDT in FADT!\n");
245 goto no_dsdt;
246 }
247 tbl = acpi_map_table(addr, DSDT_SIG);
248 if (!tbl) goto no_dsdt;
249 if (checksum((u8 *)tbl, tbl->length))
250 fprintf(stderr, "Wrong checksum for DSDT!\n");
251 write_table(fd, tbl, addr);
252 acpi_unmap_table(tbl);
253no_dsdt:
254 if (x.header.length >= 140 && x.xfirmware_ctrl) {
255 addr = (unsigned long)x.xfirmware_ctrl;
256 if (connect) {
257 x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR);
258 }
259 } else if (x.header.length >= 40 && x.firmware_ctrl) {
260 addr = (unsigned long)x.firmware_ctrl;
261 if (connect) {
262 x.firmware_ctrl = lseek(fd, 0, SEEK_CUR);
263 }
264 } else {
265 fprintf(stderr, "No FACS in FADT!\n");
266 goto no_facs;
267 }
268 tbl = acpi_map_table(addr, FACS_SIG);
269 if (!tbl) goto no_facs;
270 /* do not checksum FACS */
271 write_table(fd, tbl, addr);
272 acpi_unmap_table(tbl);
273no_facs:
274 write_table(fd, (struct acpi_table_header *)&x, xaddr);
275}
276
277static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp)
278{
279 struct acpi_table_header *sdt, *tbl = 0;
280 int xsdt = 1, i, num;
281 char *offset;
282 unsigned long addr;
283 if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
284 tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT");
285 }
286 if (!tbl && rsdp->rsdt_physical_address) {
287 xsdt = 0;
288 tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT");
289 }
290 if (!tbl) return 0;
291 sdt = malloc(tbl->length);
292 memcpy(sdt, tbl, tbl->length);
293 acpi_unmap_table(tbl);
294 if (checksum((u8 *)sdt, sdt->length))
295 fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT");
296 num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32));
297 offset = (char *)sdt + sizeof(struct acpi_table_header);
298 for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) {
299 addr = (xsdt) ? (unsigned long)(*(u64 *)offset):
300 (unsigned long)(*(u32 *)offset);
301 if (!addr) continue;
302 tbl = acpi_map_table(addr, 0);
303 if (!tbl) continue;
304 if (!memcmp(tbl->signature, FADT_SIG, 4)) {
305 acpi_dump_FADT(fd, tbl, addr);
306 } else {
307 if (checksum((u8 *)tbl, tbl->length))
308 fprintf(stderr, "Wrong checksum for generic table!\n");
309 write_table(fd, tbl, addr);
310 }
311 acpi_unmap_table(tbl);
312 if (connect) {
313 if (xsdt)
314 (*(u64*)offset) = lseek(fd, 0, SEEK_CUR);
315 else
316 (*(u32*)offset) = lseek(fd, 0, SEEK_CUR);
317 }
318 }
319 if (xsdt) {
320 addr = (unsigned long)rsdp->xsdt_physical_address;
321 if (connect) {
322 rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
323 }
324 } else {
325 addr = (unsigned long)rsdp->rsdt_physical_address;
326 if (connect) {
327 rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR);
328 }
329 }
330 write_table(fd, sdt, addr);
331 free (sdt);
332 return 1;
333}
334
335#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic"
336
337static void acpi_dump_dynamic_SSDT(int fd)
338{
339 struct stat file_stat;
340 char filename[256], *ptr;
341 DIR *tabledir;
342 struct dirent *entry;
343 FILE *fp;
344 int count, readcount, length;
345 struct acpi_table_header table_header, *ptable;
346
347 if (stat(DYNAMIC_SSDT, &file_stat) == -1) {
348 /* The directory doesn't exist */
349 return;
350 }
351 tabledir = opendir(DYNAMIC_SSDT);
352 if(!tabledir){
353 /*can't open the directory */
354 return;
355 }
356
357 while ((entry = readdir(tabledir)) != 0){
358 /* skip the file of . /.. */
359 if (entry->d_name[0] == '.')
360 continue;
361
362 sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name);
363 fp = fopen(filename, "r");
364 if (fp == NULL) {
365 fprintf(stderr, "Can't open the file of %s\n",
366 filename);
367 continue;
368 }
369 /* Read the Table header to parse the table length */
370 count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
371 if (count < sizeof(table_header)) {
372 /* the length is lessn than ACPI table header. skip it */
373 fclose(fp);
374 continue;
375 }
376 length = table_header.length;
377 ptr = malloc(table_header.length);
378 fseek(fp, 0, SEEK_SET);
379 readcount = 0;
380 while(!feof(fp) && readcount < length) {
381 count = fread(ptr + readcount, 1, 256, fp);
382 readcount += count;
383 }
384 fclose(fp);
385 ptable = (struct acpi_table_header *) ptr;
386 if (checksum((u8 *) ptable, ptable->length))
387 fprintf(stderr, "Wrong checksum "
388 "for dynamic SSDT table!\n");
389 write_table(fd, ptable, 0);
390 free(ptr);
391 }
392 closedir(tabledir);
393 return;
394}
395
396static void usage(const char *progname)
397{
398 puts("Usage:");
399 printf("%s [--addr 0x1234][--table DSDT][--output filename]"
400 "[--binary][--length 0x456][--help]\n", progname);
401 puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address");
402 puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature");
403 puts("\t--output filename or -o filename -- redirect output from stdin to filename");
404 puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format");
405 puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory"
406 "\n\t\tregion without trying to understand it's contents");
407 puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one");
408 puts("\t--help or -h -- this help message");
409 exit(0);
410}
411
412static struct option long_options[] = {
413 {"addr", 1, 0, 0},
414 {"table", 1, 0, 0},
415 {"output", 1, 0, 0},
416 {"binary", 0, 0, 0},
417 {"length", 1, 0, 0},
418 {"skip", 1, 0, 0},
419 {"help", 0, 0, 0},
420 {0, 0, 0, 0}
421};
422int main(int argc, char **argv)
423{
424 int option_index, c, fd;
425 u8 *raw;
426 struct acpi_rsdp_descriptor rsdpx, *x = 0;
427 char *filename = 0;
428 char buff[80];
429 memset(select_sig, 0, 4);
430 print = 1;
431 connect = 0;
432 addr = length = 0;
433 skip = 0;
434 while (1) {
435 option_index = 0;
436 c = getopt_long(argc, argv, "a:t:o:bl:s:h",
437 long_options, &option_index);
438 if (c == -1)
439 break;
440
441 switch (c) {
442 case 0:
443 switch (option_index) {
444 case 0:
445 addr = strtoul(optarg, (char **)NULL, 16);
446 break;
447 case 1:
448 memcpy(select_sig, optarg, 4);
449 break;
450 case 2:
451 filename = optarg;
452 break;
453 case 3:
454 print = 0;
455 break;
456 case 4:
457 length = strtoul(optarg, (char **)NULL, 16);
458 break;
459 case 5:
460 skip = strtoul(optarg, (char **)NULL, 10);
461 break;
462 case 6:
463 usage(argv[0]);
464 exit(0);
465 }
466 break;
467 case 'a':
468 addr = strtoul(optarg, (char **)NULL, 16);
469 break;
470 case 't':
471 memcpy(select_sig, optarg, 4);
472 break;
473 case 'o':
474 filename = optarg;
475 break;
476 case 'b':
477 print = 0;
478 break;
479 case 'l':
480 length = strtoul(optarg, (char **)NULL, 16);
481 break;
482 case 's':
483 skip = strtoul(optarg, (char **)NULL, 10);
484 break;
485 case 'h':
486 usage(argv[0]);
487 exit(0);
488 default:
489 printf("Unknown option!\n");
490 usage(argv[0]);
491 exit(0);
492 }
493 }
494
495 fd = STDOUT_FILENO;
496 if (filename) {
497 fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
498 if (fd < 0)
499 return fd;
500 }
501
502 if (!select_sig[0] && !print) {
503 connect = 1;
504 }
505
506 psz = sysconf(_SC_PAGESIZE);
507 if (length && addr) {
508 /* We know length and address, it means we just want a memory dump */
509 if (!(raw = acpi_map_memory(addr, length)))
510 goto not_found;
511 write(fd, raw, length);
512 acpi_unmap_memory(raw, length);
513 close(fd);
514 return 0;
515 }
516
517 length = sizeof(struct acpi_rsdp_descriptor);
518 if (!addr) {
519 addr = read_efi_systab();
520 if (!addr) {
521 addr = ACPI_HI_RSDP_WINDOW_BASE;
522 length = ACPI_HI_RSDP_WINDOW_SIZE;
523 }
524 }
525
526 if (!(raw = acpi_map_memory(addr, length)) ||
527 !(x = acpi_scan_for_rsdp(raw, length)))
528 goto not_found;
529
530 /* Find RSDP and print all found tables */
531 memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor));
532 acpi_unmap_memory(raw, length);
533 if (connect) {
534 lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET);
535 }
536 if (!acpi_dump_SDT(fd, &rsdpx))
537 goto not_found;
538 if (connect) {
539 lseek(fd, 0, SEEK_SET);
540 write(fd, x, (rsdpx.revision < 2) ?
541 ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
542 } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) {
543 addr += (long)x - (long)raw;
544 length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr);
545 write(fd, buff, length);
546 acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ?
547 ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
548 buff[0] = '\n';
549 write(fd, buff, 1);
550 }
551 acpi_dump_dynamic_SSDT(fd);
552 close(fd);
553 return 0;
554not_found:
555 close(fd);
556 fprintf(stderr, "ACPI tables were not found. If you know location "
557 "of RSD PTR table (from dmesg, etc), "
558 "supply it with either --addr or -a option\n");
559 return 1;
560}
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 74e44507dfe9..e4d0690cccf9 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -4,15 +4,11 @@ turbostat \- Report processor frequency and idle statistics
4.SH SYNOPSIS 4.SH SYNOPSIS
5.ft B 5.ft B
6.B turbostat 6.B turbostat
7.RB [ "\-s" ] 7.RB [ Options ]
8.RB [ "\-v" ]
9.RB [ "\-M MSR#" ]
10.RB command 8.RB command
11.br 9.br
12.B turbostat 10.B turbostat
13.RB [ "\-s" ] 11.RB [ Options ]
14.RB [ "\-v" ]
15.RB [ "\-M MSR#" ]
16.RB [ "\-i interval_sec" ] 12.RB [ "\-i interval_sec" ]
17.SH DESCRIPTION 13.SH DESCRIPTION
18\fBturbostat \fP reports processor topology, frequency 14\fBturbostat \fP reports processor topology, frequency
@@ -27,16 +23,23 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs.
27on processors that additionally support C-state residency counters. 23on processors that additionally support C-state residency counters.
28 24
29.SS Options 25.SS Options
30The \fB-s\fP option limits output to a 1-line system summary for each interval. 26The \fB-p\fP option limits output to the 1st thread in 1st core of each package.
31.PP 27.PP
32The \fB-c\fP option limits output to the 1st thread in each core. 28The \fB-P\fP option limits output to the 1st thread in each Package.
33.PP 29.PP
34The \fB-p\fP option limits output to the 1st thread in each package. 30The \fB-S\fP option limits output to a 1-line System Summary for each interval.
35.PP 31.PP
36The \fB-v\fP option increases verbosity. 32The \fB-v\fP option increases verbosity.
37.PP 33.PP
38The \fB-M MSR#\fP option dumps the specified MSR, 34The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34"
39in addition to the usual frequency and idle statistics. 35.PP
36The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter.
37.PP
38The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter.
39.PP
40The \fB-m MSR#\fP option includes the the specified 32-bit MSR value.
41.PP
42The \fB-M MSR#\fP option includes the the specified 64-bit MSR value.
40.PP 43.PP
41The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. 44The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
42The default is 5 seconds. 45The default is 5 seconds.
@@ -150,6 +153,29 @@ Note that turbostat reports average GHz of 3.63, while
150the arithmetic average of the GHz column above is lower. 153the arithmetic average of the GHz column above is lower.
151This is a weighted average, where the weight is %c0. ie. it is the total number of 154This is a weighted average, where the weight is %c0. ie. it is the total number of
152un-halted cycles elapsed per time divided by the number of CPUs. 155un-halted cycles elapsed per time divided by the number of CPUs.
156.SH SMI COUNTING EXAMPLE
157On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter.
158Using the -m option, you can display how many SMIs have fired since reset, or if there
159are SMIs during the measurement interval, you can display the delta using the -d option.
160.nf
161[root@x980 ~]# turbostat -m 0x34
162cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6
163 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55
164 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55
165 0 6 0.14 1.63 3.38 0x00000056 5.30
166 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52
167 1 8 0.10 1.65 3.38 0x00000056 18.05
168 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50
169 2 10 0.10 1.63 3.38 0x00000056 6.93
170 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16
171 8 7 0.08 1.64 3.38 0x00000056 5.12
172 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38
173 9 9 0.09 1.68 3.38 0x00000056 9.32
174 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23
175 10 11 1.72 1.65 3.38 0x00000056 15.05
176^C
177[root@x980 ~]#
178.fi
153.SH NOTES 179.SH NOTES
154 180
155.B "turbostat " 181.B "turbostat "
@@ -165,6 +191,13 @@ may work poorly on Linux-2.6.20 through 2.6.29,
165as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF 191as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
166in those kernels. 192in those kernels.
167 193
194If the TSC column does not make sense, then
195the other numbers will also make no sense.
196Turbostat is lightweight, and its data collection is not atomic.
197These issues are usually caused by an extremely short measurement
198interval (much less than 1 second), or system activity that prevents
199turbostat from being able to run on all CPUS to quickly collect data.
200
168The APERF, MPERF MSRs are defined to count non-halted cycles. 201The APERF, MPERF MSRs are defined to count non-halted cycles.
169Although it is not guaranteed by the architecture, turbostat assumes 202Although it is not guaranteed by the architecture, turbostat assumes
170that they count at TSC rate, which is true on all processors tested to date. 203that they count at TSC rate, which is true on all processors tested to date.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 861d77190206..2655ae9a3ad8 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -35,9 +35,9 @@
35#include <ctype.h> 35#include <ctype.h>
36#include <sched.h> 36#include <sched.h>
37 37
38#define MSR_TSC 0x10
39#define MSR_NEHALEM_PLATFORM_INFO 0xCE 38#define MSR_NEHALEM_PLATFORM_INFO 0xCE
40#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD 39#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
40#define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE
41#define MSR_APERF 0xE8 41#define MSR_APERF 0xE8
42#define MSR_MPERF 0xE7 42#define MSR_MPERF 0xE7
43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */ 43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
@@ -62,7 +62,11 @@ unsigned int genuine_intel;
62unsigned int has_invariant_tsc; 62unsigned int has_invariant_tsc;
63unsigned int do_nehalem_platform_info; 63unsigned int do_nehalem_platform_info;
64unsigned int do_nehalem_turbo_ratio_limit; 64unsigned int do_nehalem_turbo_ratio_limit;
65unsigned int extra_msr_offset; 65unsigned int do_ivt_turbo_ratio_limit;
66unsigned int extra_msr_offset32;
67unsigned int extra_msr_offset64;
68unsigned int extra_delta_offset32;
69unsigned int extra_delta_offset64;
66double bclk; 70double bclk;
67unsigned int show_pkg; 71unsigned int show_pkg;
68unsigned int show_core; 72unsigned int show_core;
@@ -83,7 +87,10 @@ struct thread_data {
83 unsigned long long aperf; 87 unsigned long long aperf;
84 unsigned long long mperf; 88 unsigned long long mperf;
85 unsigned long long c1; /* derived */ 89 unsigned long long c1; /* derived */
86 unsigned long long extra_msr; 90 unsigned long long extra_msr64;
91 unsigned long long extra_delta64;
92 unsigned long long extra_msr32;
93 unsigned long long extra_delta32;
87 unsigned int cpu_id; 94 unsigned int cpu_id;
88 unsigned int flags; 95 unsigned int flags;
89#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 96#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
@@ -222,6 +229,14 @@ void print_header(void)
222 if (has_aperf) 229 if (has_aperf)
223 outp += sprintf(outp, " GHz"); 230 outp += sprintf(outp, " GHz");
224 outp += sprintf(outp, " TSC"); 231 outp += sprintf(outp, " TSC");
232 if (extra_delta_offset32)
233 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
234 if (extra_delta_offset64)
235 outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64);
236 if (extra_msr_offset32)
237 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
238 if (extra_msr_offset64)
239 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
225 if (do_nhm_cstates) 240 if (do_nhm_cstates)
226 outp += sprintf(outp, " %%c1"); 241 outp += sprintf(outp, " %%c1");
227 if (do_nhm_cstates) 242 if (do_nhm_cstates)
@@ -238,8 +253,6 @@ void print_header(void)
238 outp += sprintf(outp, " %%pc6"); 253 outp += sprintf(outp, " %%pc6");
239 if (do_snb_cstates) 254 if (do_snb_cstates)
240 outp += sprintf(outp, " %%pc7"); 255 outp += sprintf(outp, " %%pc7");
241 if (extra_msr_offset)
242 outp += sprintf(outp, " MSR 0x%x ", extra_msr_offset);
243 256
244 outp += sprintf(outp, "\n"); 257 outp += sprintf(outp, "\n");
245} 258}
@@ -255,8 +268,14 @@ int dump_counters(struct thread_data *t, struct core_data *c,
255 fprintf(stderr, "aperf: %016llX\n", t->aperf); 268 fprintf(stderr, "aperf: %016llX\n", t->aperf);
256 fprintf(stderr, "mperf: %016llX\n", t->mperf); 269 fprintf(stderr, "mperf: %016llX\n", t->mperf);
257 fprintf(stderr, "c1: %016llX\n", t->c1); 270 fprintf(stderr, "c1: %016llX\n", t->c1);
271 fprintf(stderr, "msr0x%x: %08llX\n",
272 extra_delta_offset32, t->extra_delta32);
258 fprintf(stderr, "msr0x%x: %016llX\n", 273 fprintf(stderr, "msr0x%x: %016llX\n",
259 extra_msr_offset, t->extra_msr); 274 extra_delta_offset64, t->extra_delta64);
275 fprintf(stderr, "msr0x%x: %08llX\n",
276 extra_msr_offset32, t->extra_msr32);
277 fprintf(stderr, "msr0x%x: %016llX\n",
278 extra_msr_offset64, t->extra_msr64);
260 } 279 }
261 280
262 if (c) { 281 if (c) {
@@ -360,6 +379,21 @@ int format_counters(struct thread_data *t, struct core_data *c,
360 /* TSC */ 379 /* TSC */
361 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); 380 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
362 381
382 /* delta */
383 if (extra_delta_offset32)
384 outp += sprintf(outp, " %11llu", t->extra_delta32);
385
386 /* DELTA */
387 if (extra_delta_offset64)
388 outp += sprintf(outp, " %11llu", t->extra_delta64);
389 /* msr */
390 if (extra_msr_offset32)
391 outp += sprintf(outp, " 0x%08llx", t->extra_msr32);
392
393 /* MSR */
394 if (extra_msr_offset64)
395 outp += sprintf(outp, " 0x%016llx", t->extra_msr64);
396
363 if (do_nhm_cstates) { 397 if (do_nhm_cstates) {
364 if (!skip_c1) 398 if (!skip_c1)
365 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); 399 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc);
@@ -391,8 +425,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
391 if (do_snb_cstates) 425 if (do_snb_cstates)
392 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); 426 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
393done: 427done:
394 if (extra_msr_offset)
395 outp += sprintf(outp, " 0x%016llx", t->extra_msr);
396 outp += sprintf(outp, "\n"); 428 outp += sprintf(outp, "\n");
397 429
398 return 0; 430 return 0;
@@ -502,10 +534,16 @@ delta_thread(struct thread_data *new, struct thread_data *old,
502 old->mperf = 1; /* divide by 0 protection */ 534 old->mperf = 1; /* divide by 0 protection */
503 } 535 }
504 536
537 old->extra_delta32 = new->extra_delta32 - old->extra_delta32;
538 old->extra_delta32 &= 0xFFFFFFFF;
539
540 old->extra_delta64 = new->extra_delta64 - old->extra_delta64;
541
505 /* 542 /*
506 * for "extra msr", just copy the latest w/o subtracting 543 * Extra MSR is just a snapshot, simply copy latest w/o subtracting
507 */ 544 */
508 old->extra_msr = new->extra_msr; 545 old->extra_msr32 = new->extra_msr32;
546 old->extra_msr64 = new->extra_msr64;
509} 547}
510 548
511int delta_cpu(struct thread_data *t, struct core_data *c, 549int delta_cpu(struct thread_data *t, struct core_data *c,
@@ -533,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
533 t->mperf = 0; 571 t->mperf = 0;
534 t->c1 = 0; 572 t->c1 = 0;
535 573
574 t->extra_delta32 = 0;
575 t->extra_delta64 = 0;
576
536 /* tells format_counters to dump all fields from this set */ 577 /* tells format_counters to dump all fields from this set */
537 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 578 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
538 579
@@ -553,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
553 average.threads.mperf += t->mperf; 594 average.threads.mperf += t->mperf;
554 average.threads.c1 += t->c1; 595 average.threads.c1 += t->c1;
555 596
597 average.threads.extra_delta32 += t->extra_delta32;
598 average.threads.extra_delta64 += t->extra_delta64;
599
556 /* sum per-core values only for 1st thread in core */ 600 /* sum per-core values only for 1st thread in core */
557 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 601 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
558 return 0; 602 return 0;
@@ -588,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
588 average.threads.mperf /= topo.num_cpus; 632 average.threads.mperf /= topo.num_cpus;
589 average.threads.c1 /= topo.num_cpus; 633 average.threads.c1 /= topo.num_cpus;
590 634
635 average.threads.extra_delta32 /= topo.num_cpus;
636 average.threads.extra_delta32 &= 0xFFFFFFFF;
637
638 average.threads.extra_delta64 /= topo.num_cpus;
639
591 average.cores.c3 /= topo.num_cores; 640 average.cores.c3 /= topo.num_cores;
592 average.cores.c6 /= topo.num_cores; 641 average.cores.c6 /= topo.num_cores;
593 average.cores.c7 /= topo.num_cores; 642 average.cores.c7 /= topo.num_cores;
@@ -629,8 +678,24 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
629 return -4; 678 return -4;
630 } 679 }
631 680
632 if (extra_msr_offset) 681 if (extra_delta_offset32) {
633 if (get_msr(cpu, extra_msr_offset, &t->extra_msr)) 682 if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32))
683 return -5;
684 t->extra_delta32 &= 0xFFFFFFFF;
685 }
686
687 if (extra_delta_offset64)
688 if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64))
689 return -5;
690
691 if (extra_msr_offset32) {
692 if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32))
693 return -5;
694 t->extra_msr32 &= 0xFFFFFFFF;
695 }
696
697 if (extra_msr_offset64)
698 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
634 return -5; 699 return -5;
635 700
636 /* collect core counters only for 1st thread in core */ 701 /* collect core counters only for 1st thread in core */
@@ -677,6 +742,9 @@ void print_verbose_header(void)
677 742
678 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); 743 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
679 744
745 if (verbose > 1)
746 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
747
680 ratio = (msr >> 40) & 0xFF; 748 ratio = (msr >> 40) & 0xFF;
681 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", 749 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
682 ratio, bclk, ratio * bclk); 750 ratio, bclk, ratio * bclk);
@@ -685,14 +753,84 @@ void print_verbose_header(void)
685 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", 753 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
686 ratio, bclk, ratio * bclk); 754 ratio, bclk, ratio * bclk);
687 755
756 if (!do_ivt_turbo_ratio_limit)
757 goto print_nhm_turbo_ratio_limits;
758
759 get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr);
760
688 if (verbose > 1) 761 if (verbose > 1)
689 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); 762 fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
763
764 ratio = (msr >> 56) & 0xFF;
765 if (ratio)
766 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
767 ratio, bclk, ratio * bclk);
768
769 ratio = (msr >> 48) & 0xFF;
770 if (ratio)
771 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
772 ratio, bclk, ratio * bclk);
773
774 ratio = (msr >> 40) & 0xFF;
775 if (ratio)
776 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
777 ratio, bclk, ratio * bclk);
778
779 ratio = (msr >> 32) & 0xFF;
780 if (ratio)
781 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
782 ratio, bclk, ratio * bclk);
783
784 ratio = (msr >> 24) & 0xFF;
785 if (ratio)
786 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
787 ratio, bclk, ratio * bclk);
788
789 ratio = (msr >> 16) & 0xFF;
790 if (ratio)
791 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
792 ratio, bclk, ratio * bclk);
793
794 ratio = (msr >> 8) & 0xFF;
795 if (ratio)
796 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
797 ratio, bclk, ratio * bclk);
798
799 ratio = (msr >> 0) & 0xFF;
800 if (ratio)
801 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
802 ratio, bclk, ratio * bclk);
803
804print_nhm_turbo_ratio_limits:
690 805
691 if (!do_nehalem_turbo_ratio_limit) 806 if (!do_nehalem_turbo_ratio_limit)
692 return; 807 return;
693 808
694 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); 809 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
695 810
811 if (verbose > 1)
812 fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
813
814 ratio = (msr >> 56) & 0xFF;
815 if (ratio)
816 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
817 ratio, bclk, ratio * bclk);
818
819 ratio = (msr >> 48) & 0xFF;
820 if (ratio)
821 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
822 ratio, bclk, ratio * bclk);
823
824 ratio = (msr >> 40) & 0xFF;
825 if (ratio)
826 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
827 ratio, bclk, ratio * bclk);
828
829 ratio = (msr >> 32) & 0xFF;
830 if (ratio)
831 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
832 ratio, bclk, ratio * bclk);
833
696 ratio = (msr >> 24) & 0xFF; 834 ratio = (msr >> 24) & 0xFF;
697 if (ratio) 835 if (ratio)
698 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", 836 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
@@ -712,7 +850,6 @@ void print_verbose_header(void)
712 if (ratio) 850 if (ratio)
713 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 851 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
714 ratio, bclk, ratio * bclk); 852 ratio, bclk, ratio * bclk);
715
716} 853}
717 854
718void free_all_buffers(void) 855void free_all_buffers(void)
@@ -1038,7 +1175,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1038 case 0x2A: /* SNB */ 1175 case 0x2A: /* SNB */
1039 case 0x2D: /* SNB Xeon */ 1176 case 0x2D: /* SNB Xeon */
1040 case 0x3A: /* IVB */ 1177 case 0x3A: /* IVB */
1041 case 0x3D: /* IVB Xeon */ 1178 case 0x3E: /* IVB Xeon */
1042 return 1; 1179 return 1;
1043 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1180 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1044 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1181 case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1046,6 +1183,22 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1046 return 0; 1183 return 0;
1047 } 1184 }
1048} 1185}
1186int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1187{
1188 if (!genuine_intel)
1189 return 0;
1190
1191 if (family != 6)
1192 return 0;
1193
1194 switch (model) {
1195 case 0x3E: /* IVB Xeon */
1196 return 1;
1197 default:
1198 return 0;
1199 }
1200}
1201
1049 1202
1050int is_snb(unsigned int family, unsigned int model) 1203int is_snb(unsigned int family, unsigned int model)
1051{ 1204{
@@ -1056,7 +1209,7 @@ int is_snb(unsigned int family, unsigned int model)
1056 case 0x2A: 1209 case 0x2A:
1057 case 0x2D: 1210 case 0x2D:
1058 case 0x3A: /* IVB */ 1211 case 0x3A: /* IVB */
1059 case 0x3D: /* IVB Xeon */ 1212 case 0x3E: /* IVB Xeon */
1060 return 1; 1213 return 1;
1061 } 1214 }
1062 return 0; 1215 return 0;
@@ -1145,12 +1298,13 @@ void check_cpuid()
1145 bclk = discover_bclk(family, model); 1298 bclk = discover_bclk(family, model);
1146 1299
1147 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); 1300 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
1301 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
1148} 1302}
1149 1303
1150 1304
1151void usage() 1305void usage()
1152{ 1306{
1153 fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n", 1307 fprintf(stderr, "%s: [-v][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n",
1154 progname); 1308 progname);
1155 exit(1); 1309 exit(1);
1156} 1310}
@@ -1440,15 +1594,15 @@ void cmdline(int argc, char **argv)
1440 1594
1441 progname = argv[0]; 1595 progname = argv[0];
1442 1596
1443 while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) { 1597 while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
1444 switch (opt) { 1598 switch (opt) {
1445 case 'c': 1599 case 'p':
1446 show_core_only++; 1600 show_core_only++;
1447 break; 1601 break;
1448 case 'p': 1602 case 'P':
1449 show_pkg_only++; 1603 show_pkg_only++;
1450 break; 1604 break;
1451 case 's': 1605 case 'S':
1452 summary_only++; 1606 summary_only++;
1453 break; 1607 break;
1454 case 'v': 1608 case 'v':
@@ -1457,10 +1611,20 @@ void cmdline(int argc, char **argv)
1457 case 'i': 1611 case 'i':
1458 interval_sec = atoi(optarg); 1612 interval_sec = atoi(optarg);
1459 break; 1613 break;
1614 case 'c':
1615 sscanf(optarg, "%x", &extra_delta_offset32);
1616 break;
1617 case 's':
1618 extra_delta_offset32 = 0x34; /* SMI counter */
1619 break;
1620 case 'C':
1621 sscanf(optarg, "%x", &extra_delta_offset64);
1622 break;
1623 case 'm':
1624 sscanf(optarg, "%x", &extra_msr_offset32);
1625 break;
1460 case 'M': 1626 case 'M':
1461 sscanf(optarg, "%x", &extra_msr_offset); 1627 sscanf(optarg, "%x", &extra_msr_offset64);
1462 if (verbose > 1)
1463 fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
1464 break; 1628 break;
1465 default: 1629 default:
1466 usage(); 1630 usage();
@@ -1473,7 +1637,7 @@ int main(int argc, char **argv)
1473 cmdline(argc, argv); 1637 cmdline(argc, argv);
1474 1638
1475 if (verbose > 1) 1639 if (verbose > 1)
1476 fprintf(stderr, "turbostat v2.0 May 16, 2012" 1640 fprintf(stderr, "turbostat v2.1 October 6, 2012"
1477 " - Len Brown <lenb@kernel.org>\n"); 1641 " - Len Brown <lenb@kernel.org>\n");
1478 1642
1479 turbostat_init(); 1643 turbostat_init();