From 0efea7b6b2ac2a6e7d7b223a6c70299099285103 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 22:33:19 -0400 Subject: tools/power/acpi/acpidump: version 20051111 This is unchanged version 20051111, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. Signed-off-by: Len Brown --- tools/power/acpi/Makefile | 15 ++ tools/power/acpi/acpidump.c | 472 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 487 insertions(+) create mode 100644 tools/power/acpi/Makefile create mode 100644 tools/power/acpi/acpidump.c (limited to 'tools') diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile new file mode 100644 index 000000000000..faf5ff5c8f8f --- /dev/null +++ b/tools/power/acpi/Makefile @@ -0,0 +1,15 @@ +PROG= acpidump +SRCS= acpidump.c +KERNEL_INCLUDE := ../../../include +CFLAGS += -Wall -Wstrict-prototypes -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) + +all: acpidump + +acpidump : $(SRCS) + $(CC) $(CFLAGS) $(SRCS) -o $(PROG) + +CLEANFILES= $(PROG) + +clean : + rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~ + diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c new file mode 100644 index 000000000000..3f0a9da6df9f --- /dev/null +++ b/tools/power/acpi/acpidump.c @@ -0,0 +1,472 @@ +/* + * (c) Alexey Starikovskiy, Intel, 2005. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifdef DEFINE_ALTERNATE_TYPES +/* hack to enable building old application with new headers -lenb */ +#define acpi_fadt_descriptor acpi_table_fadt +#define acpi_rsdp_descriptor acpi_table_rsdp +#define DSDT_SIG ACPI_SIG_DSDT +#define FACS_SIG ACPI_SIG_FACS +#define FADT_SIG ACPI_SIG_FADT +#define xfirmware_ctrl Xfacs +#define firmware_ctrl facs + +typedef int s32; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef long long s64; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +static inline u8 checksum(u8 * buffer, u32 length) +{ + u8 sum = 0, *i = buffer; + buffer += length; + for (; i < buffer; sum += *(i++)); + return sum; +} + +static unsigned long psz, addr, length; +static int print, connect; +static u8 select_sig[4]; + +static unsigned long read_efi_systab( void ) +{ + FILE *f = fopen("/sys/firmware/efi/systab", "r"); + if (f) { + char buffer[80]; + while (fgets(buffer, 80, f)) { + unsigned long addr; + if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1) + return addr; + } + fclose(f); + } + return 0; +} + +static u8 *acpi_map_memory(unsigned long where, unsigned length) +{ + int fd = open("/dev/mem", O_RDONLY); + if (fd < 0) { + fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n"); + exit(1); + } + unsigned long offset = where % psz; + u8 *there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE, + fd, where - offset); + close(fd); + if (there == MAP_FAILED) return 0; + return (there + offset); +} + +static void acpi_unmap_memory(u8 * there, unsigned length) +{ + unsigned long offset = (unsigned long)there % psz; + munmap(there - offset, length + offset); +} + +static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig) +{ + struct acpi_table_header *tbl = (struct acpi_table_header *) + acpi_map_memory(where, sizeof(struct acpi_table_header)); + if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0; + unsigned size = tbl->length; + acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header)); + return (struct acpi_table_header *)acpi_map_memory(where, size); +} + +static void acpi_unmap_table(struct acpi_table_header *tbl) +{ + acpi_unmap_memory((u8 *)tbl, tbl->length); +} + +static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length) +{ + u8 *i, *end = begin + length; + /* Search from given start address for the requested length */ + for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) { + /* The signature and checksum must both be correct */ + if (memcmp((char *)i, "RSD PTR ", 8)) continue; + struct acpi_rsdp_descriptor *rsdp = (struct acpi_rsdp_descriptor *)i; + /* Signature matches, check the appropriate checksum */ + if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ? + ACPI_RSDP_CHECKSUM_LENGTH : + ACPI_RSDP_XCHECKSUM_LENGTH)) + /* Checksum valid, we have found a valid RSDP */ + return rsdp; + } + /* Searched entire block, no RSDP was found */ + return 0; +} + +/* + * Output data + */ +static void acpi_show_data(int fd, u8 * data, int size) +{ + char buffer[256]; + int i, remain = size; + while (remain > 0) { + int len = snprintf(buffer, 256, " %04x:", size - remain); + for (i = 0; i < 16 && i < remain; i++) { + len += + snprintf(&buffer[len], 256 - len, " %02x", data[i]); + } + for (; i < 16; i++) { + len += snprintf(&buffer[len], 256 - len, " "); + } + len += snprintf(&buffer[len], 256 - len, " "); + for (i = 0; i < 16 && i < remain; i++) { + buffer[len++] = (isprint(data[i])) ? data[i] : '.'; + } + buffer[len++] = '\n'; + write(fd, buffer, len); + data += 16; + remain -= 16; + } +} + +/* + * Output ACPI table + */ +static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) +{ + char buff[80]; + int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr); + write(fd, buff, len); + acpi_show_data(fd, (u8 *) table, table->length); + buff[0] = '\n'; + write(fd, buff, 1); +} + +static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) +{ + static int select_done = 0; + if (!select_sig[0]) { + if (print) { + acpi_show_table(fd, tbl, addr); + } else { + write(fd, tbl, tbl->length); + } + } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) { + if (print) { + acpi_show_table(fd, tbl, addr); + } else { + write(fd, tbl, tbl->length); + } + select_done = 1; + } +} + +static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { + struct acpi_fadt_descriptor x; + unsigned long addr; + size_t len = sizeof(struct acpi_fadt_descriptor); + if (len > tbl->length) len = tbl->length; + memcpy(&x, tbl, len); + x.header.length = len; + if (checksum((u8 *)tbl, len)) { + fprintf(stderr, "Wrong checksum for FADT!\n"); + } + if (x.header.length >= 148 && x.Xdsdt) { + addr = (unsigned long)x.Xdsdt; + if (connect) { + x.Xdsdt = lseek(fd, 0, SEEK_CUR); + } + } else if (x.header.length >= 44 && x.dsdt) { + addr = (unsigned long)x.dsdt; + if (connect) { + x.dsdt = lseek(fd, 0, SEEK_CUR); + } + } else { + fprintf(stderr, "No DSDT in FADT!\n"); + goto no_dsdt; + } + tbl = acpi_map_table(addr, DSDT_SIG); + if (!tbl) goto no_dsdt; + if (checksum((u8 *)tbl, tbl->length)) + fprintf(stderr, "Wrong checksum for DSDT!\n"); + write_table(fd, tbl, addr); + acpi_unmap_table(tbl); +no_dsdt: + if (x.header.length >= 140 && x.xfirmware_ctrl) { + addr = (unsigned long)x.xfirmware_ctrl; + if (connect) { + x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR); + } + } else if (x.header.length >= 40 && x.firmware_ctrl) { + addr = (unsigned long)x.firmware_ctrl; + if (connect) { + x.firmware_ctrl = lseek(fd, 0, SEEK_CUR); + } + } else { + fprintf(stderr, "No FACS in FADT!\n"); + goto no_facs; + } + tbl = acpi_map_table(addr, FACS_SIG); + if (!tbl) goto no_facs; + /* do not checksum FACS */ + write_table(fd, tbl, addr); + acpi_unmap_table(tbl); +no_facs: + write_table(fd, (struct acpi_table_header *)&x, xaddr); +} + +static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) +{ + struct acpi_table_header *tbl = 0; + int xsdt = 1; + if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { + tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); + } + if (!tbl && rsdp->rsdt_physical_address) { + xsdt = 0; + tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); + } + if (!tbl) return 0; + struct acpi_table_header *sdt = malloc(tbl->length); + memcpy(sdt, tbl, tbl->length); + acpi_unmap_table(tbl); + if (checksum((u8 *)sdt, sdt->length)) + fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); + int i, num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); + char *offset = (char *)sdt + sizeof(struct acpi_table_header); + unsigned long addr; + for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { + addr = (xsdt) ? (unsigned long)(*(u64 *)offset): + (unsigned long)(*(u32 *)offset); + tbl = acpi_map_table(addr, 0); + if (!tbl) continue; + if (!memcmp(tbl->signature, FADT_SIG, 4)) { + acpi_dump_FADT(fd, tbl, addr); + } else { + if (checksum((u8 *)tbl, tbl->length)) + fprintf(stderr, "Wrong checksum for generic table!\n"); + write_table(fd, tbl, addr); + } + acpi_unmap_table(tbl); + if (connect) { + if (xsdt) + (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); + else + (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); + } + } + if (xsdt) { + addr = (unsigned long)rsdp->xsdt_physical_address; + if (connect) { + rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } + } else { + addr = (unsigned long)rsdp->rsdt_physical_address; + if (connect) { + rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } + } + write_table(fd, sdt, addr); + free (sdt); + return 1; +} + +static void usage(const char *progname) +{ + puts("Usage:"); + printf("%s [--addr 0x1234][--table DSDT][--output filename]" + "[--binary][--length 0x456][--help]\n", progname); + puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address"); + puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature"); + puts("\t--output filename or -o filename -- redirect output from stdin to filename"); + puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format"); + puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory" + "\n\t\tregion without trying to understand it's contents"); + puts("\t--help or -h -- this help message"); + exit(0); +} + +int main(int argc, char **argv) +{ + memset(select_sig, 0, 4); + print = 1; + connect = 0; + char *filename = 0; + addr = length = 0; + while (1) { + int option_index = 0; + static struct option long_options[] = { + {"addr", 1, 0, 0}, + {"table", 1, 0, 0}, + {"output", 1, 0, 0}, + {"binary", 0, 0, 0}, + {"length", 1, 0, 0}, + {"help", 0, 0, 0}, + {0, 0, 0, 0} + }; + int c = getopt_long(argc, argv, "a:t:o:bl:h", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + switch (option_index) { + case 0: + addr = strtoul(optarg, (char **)NULL, 16); + break; + case 1: + memcpy(select_sig, optarg, 4); + break; + case 2: + filename = optarg; + break; + case 3: + print = 0; + break; + case 4: + length = strtoul(optarg, (char **)NULL, 16); + break; + case 5: + usage(argv[0]); + exit(0); + } + break; + case 'a': + addr = strtoul(optarg, (char **)NULL, 16); + break; + case 't': + memcpy(select_sig, optarg, 4); + break; + case 'o': + filename = optarg; + break; + case 'b': + print = 0; + break; + case 'l': + length = strtoul(optarg, (char **)NULL, 16); + break; + case 'h': + usage(argv[0]); + exit(0); + default: + printf("Unknown option!\n"); + usage(argv[0]); + exit(0); + } + } + + int fd = STDOUT_FILENO; + if (filename) { + fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd < 0) + return fd; + } + + if (!select_sig[0] && !print) { + connect = 1; + } + + psz = sysconf(_SC_PAGESIZE); + u8 *raw; + if (length && addr) { + /* We know length and address, it means we just want a memory dump */ + if (!(raw = acpi_map_memory(addr, length))) + goto not_found; + write(fd, raw, length); + acpi_unmap_memory(raw, length); + return 0; + } + + length = sizeof(struct acpi_rsdp_descriptor); + if (!addr) { + addr = read_efi_systab(); + if (!addr) { + addr = ACPI_HI_RSDP_WINDOW_BASE; + length = ACPI_HI_RSDP_WINDOW_SIZE; + } + } + + struct acpi_rsdp_descriptor rsdpx, *x = 0; + if (!(raw = acpi_map_memory(addr, length)) || + !(x = acpi_scan_for_rsdp(raw, length))) + goto not_found; + + /* Find RSDP and print all found tables */ + memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor)); + acpi_unmap_memory(raw, length); + if (connect) { + lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); + } + if (!acpi_dump_SDT(fd, &rsdpx)) + goto not_found; + if (connect) { + lseek(fd, 0, SEEK_SET); + write(fd, x, (rsdpx.revision < 2) ? + ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); + } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) { + char buff[80]; + addr += (long)x - (long)raw; + length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr); + write(fd, buff, length); + acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ? + ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); + buff[0] = '\n'; + write(fd, buff, 1); + } + return 0; +not_found: + fprintf(stderr, "ACPI tables were not found. If you know location " + "of RSD PTR table (from dmesg, etc), " + "supply it with either --addr or -a option\n"); + return 1; +} -- cgit v1.2.2 From 4f1004207ed67903c60ed6476da0cc571b19a220 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 22:43:08 -0400 Subject: tools/power/acpi/acpidump: version 20060606 This is unchanged version 20060606, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. Signed-off-by: Len Brown --- tools/power/acpi/acpidump.c | 97 +++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 38 deletions(-) (limited to 'tools') diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c index 3f0a9da6df9f..3bb8e820ba43 100644 --- a/tools/power/acpi/acpidump.c +++ b/tools/power/acpi/acpidump.c @@ -1,5 +1,5 @@ /* - * (c) Alexey Starikovskiy, Intel, 2005. + * (c) Alexey Starikovskiy, Intel, 2005-2006. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,16 +77,16 @@ static inline u8 checksum(u8 * buffer, u32 length) } static unsigned long psz, addr, length; -static int print, connect; +static int print, connect, skip; static u8 select_sig[4]; static unsigned long read_efi_systab( void ) { + char buffer[80]; + unsigned long addr; FILE *f = fopen("/sys/firmware/efi/systab", "r"); if (f) { - char buffer[80]; while (fgets(buffer, 80, f)) { - unsigned long addr; if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1) return addr; } @@ -97,13 +97,15 @@ static unsigned long read_efi_systab( void ) static u8 *acpi_map_memory(unsigned long where, unsigned length) { + unsigned long offset; + u8 *there; int fd = open("/dev/mem", O_RDONLY); if (fd < 0) { fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n"); exit(1); } - unsigned long offset = where % psz; - u8 *there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE, + offset = where % psz; + there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE, fd, where - offset); close(fd); if (there == MAP_FAILED) return 0; @@ -118,10 +120,11 @@ static void acpi_unmap_memory(u8 * there, unsigned length) static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig) { + unsigned size; struct acpi_table_header *tbl = (struct acpi_table_header *) acpi_map_memory(where, sizeof(struct acpi_table_header)); if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0; - unsigned size = tbl->length; + size = tbl->length; acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header)); return (struct acpi_table_header *)acpi_map_memory(where, size); } @@ -133,12 +136,13 @@ static void acpi_unmap_table(struct acpi_table_header *tbl) static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length) { + struct acpi_rsdp_descriptor *rsdp; u8 *i, *end = begin + length; /* Search from given start address for the requested length */ for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) { /* The signature and checksum must both be correct */ if (memcmp((char *)i, "RSD PTR ", 8)) continue; - struct acpi_rsdp_descriptor *rsdp = (struct acpi_rsdp_descriptor *)i; + rsdp = (struct acpi_rsdp_descriptor *)i; /* Signature matches, check the appropriate checksum */ if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ? ACPI_RSDP_CHECKSUM_LENGTH : @@ -156,9 +160,10 @@ static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length) static void acpi_show_data(int fd, u8 * data, int size) { char buffer[256]; + int len; int i, remain = size; while (remain > 0) { - int len = snprintf(buffer, 256, " %04x:", size - remain); + len = snprintf(buffer, 256, " %04x:", size - remain); for (i = 0; i < 16 && i < remain; i++) { len += snprintf(&buffer[len], 256 - len, " %02x", data[i]); @@ -200,6 +205,10 @@ static void write_table(int fd, struct acpi_table_header *tbl, unsigned long add write(fd, tbl, tbl->length); } } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) { + if (skip > 0) { + --skip; + return; + } if (print) { acpi_show_table(fd, tbl, addr); } else { @@ -265,8 +274,10 @@ no_facs: static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) { - struct acpi_table_header *tbl = 0; - int xsdt = 1; + struct acpi_table_header *sdt, *tbl = 0; + int xsdt = 1, i, num; + char *offset; + unsigned long addr; if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); } @@ -275,17 +286,17 @@ static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); } if (!tbl) return 0; - struct acpi_table_header *sdt = malloc(tbl->length); + sdt = malloc(tbl->length); memcpy(sdt, tbl, tbl->length); acpi_unmap_table(tbl); if (checksum((u8 *)sdt, sdt->length)) fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); - int i, num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); - char *offset = (char *)sdt + sizeof(struct acpi_table_header); - unsigned long addr; + num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); + offset = (char *)sdt + sizeof(struct acpi_table_header); for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { addr = (xsdt) ? (unsigned long)(*(u64 *)offset): (unsigned long)(*(u32 *)offset); + if (!addr) continue; tbl = acpi_map_table(addr, 0); if (!tbl) continue; if (!memcmp(tbl->signature, FADT_SIG, 4)) { @@ -330,29 +341,36 @@ static void usage(const char *progname) puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format"); puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory" "\n\t\tregion without trying to understand it's contents"); + puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one"); puts("\t--help or -h -- this help message"); exit(0); } +static struct option long_options[] = { + {"addr", 1, 0, 0}, + {"table", 1, 0, 0}, + {"output", 1, 0, 0}, + {"binary", 0, 0, 0}, + {"length", 1, 0, 0}, + {"skip", 1, 0, 0}, + {"help", 0, 0, 0}, + {0, 0, 0, 0} +}; int main(int argc, char **argv) { + int option_index, c, fd; + u8 *raw; + struct acpi_rsdp_descriptor rsdpx, *x = 0; + char *filename = 0; + char buff[80]; memset(select_sig, 0, 4); print = 1; connect = 0; - char *filename = 0; addr = length = 0; + skip = 0; while (1) { - int option_index = 0; - static struct option long_options[] = { - {"addr", 1, 0, 0}, - {"table", 1, 0, 0}, - {"output", 1, 0, 0}, - {"binary", 0, 0, 0}, - {"length", 1, 0, 0}, - {"help", 0, 0, 0}, - {0, 0, 0, 0} - }; - int c = getopt_long(argc, argv, "a:t:o:bl:h", + option_index = 0; + c = getopt_long(argc, argv, "a:t:o:bl:s:h", long_options, &option_index); if (c == -1) break; @@ -376,6 +394,9 @@ int main(int argc, char **argv) length = strtoul(optarg, (char **)NULL, 16); break; case 5: + skip = strtoul(optarg, (char **)NULL, 10); + break; + case 6: usage(argv[0]); exit(0); } @@ -395,6 +416,9 @@ int main(int argc, char **argv) case 'l': length = strtoul(optarg, (char **)NULL, 16); break; + case 's': + skip = strtoul(optarg, (char **)NULL, 10); + break; case 'h': usage(argv[0]); exit(0); @@ -404,20 +428,19 @@ int main(int argc, char **argv) exit(0); } } - - int fd = STDOUT_FILENO; + + fd = STDOUT_FILENO; if (filename) { fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd < 0) return fd; } - + if (!select_sig[0] && !print) { connect = 1; } - + psz = sysconf(_SC_PAGESIZE); - u8 *raw; if (length && addr) { /* We know length and address, it means we just want a memory dump */ if (!(raw = acpi_map_memory(addr, length))) @@ -426,7 +449,7 @@ int main(int argc, char **argv) acpi_unmap_memory(raw, length); return 0; } - + length = sizeof(struct acpi_rsdp_descriptor); if (!addr) { addr = read_efi_systab(); @@ -435,12 +458,11 @@ int main(int argc, char **argv) length = ACPI_HI_RSDP_WINDOW_SIZE; } } - - struct acpi_rsdp_descriptor rsdpx, *x = 0; + if (!(raw = acpi_map_memory(addr, length)) || - !(x = acpi_scan_for_rsdp(raw, length))) + !(x = acpi_scan_for_rsdp(raw, length))) goto not_found; - + /* Find RSDP and print all found tables */ memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor)); acpi_unmap_memory(raw, length); @@ -454,7 +476,6 @@ int main(int argc, char **argv) write(fd, x, (rsdpx.revision < 2) ? ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) { - char buff[80]; addr += (long)x - (long)raw; length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr); write(fd, buff, length); -- cgit v1.2.2 From 981efe9ab9e91e13ec75836300515428a30017df Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 22:49:25 -0400 Subject: tools/power/acpi/acpidump: version 20070714 This is unchanged version 20070714, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. Signed-off-by: Len Brown --- tools/power/acpi/Makefile | 7 ++- tools/power/acpi/acpidump.c | 127 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 103 insertions(+), 31 deletions(-) (limited to 'tools') diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index faf5ff5c8f8f..dad79a69b679 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -1,11 +1,10 @@ -PROG= acpidump +PROG= acpidump SRCS= acpidump.c KERNEL_INCLUDE := ../../../include -CFLAGS += -Wall -Wstrict-prototypes -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) +CFLAGS += -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) all: acpidump - -acpidump : $(SRCS) +$(PROG) : $(SRCS) $(CC) $(CFLAGS) $(SRCS) -o $(PROG) CLEANFILES= $(PROG) diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c index 3bb8e820ba43..8e5e19451ce1 100644 --- a/tools/power/acpi/acpidump.c +++ b/tools/power/acpi/acpidump.c @@ -1,5 +1,6 @@ /* * (c) Alexey Starikovskiy, Intel, 2005-2006. + * (c) Len Brown, Intel, 2007. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -185,6 +186,40 @@ static void acpi_show_data(int fd, u8 * data, int size) /* * Output ACPI table */ + +#define MAX_TABLES 128 +int next_table_dump; +u64 dumped_tables[MAX_TABLES]; + +void +set_table_dumped(u64 address) { + if (next_table_dump >= MAX_TABLES) { + printf("increase MAX_TABLES\n"); + exit(1); + } + dumped_tables[next_table_dump++] = address; +} + +/* + * list the tables as they are dumped + * check the list so that they are not dumped twice. + * + * this is needed because we follow both the XSDT and RSDT + * which generally point to all duplicate tables + * except the FADT + */ +int +check_table_dumped(u64 address) { + int i; + + for (i = 0; i < MAX_TABLES; ++i) { + if (address == dumped_tables[i]) + return 1; + if (dumped_tables[i] == 0) + return 0; + } + return 0; +} static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) { char buff[80]; @@ -198,6 +233,10 @@ static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned lo static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) { static int select_done = 0; + + if (check_table_dumped((u64)addr)) + return; + if (!select_sig[0]) { if (print) { acpi_show_table(fd, tbl, addr); @@ -216,6 +255,7 @@ static void write_table(int fd, struct acpi_table_header *tbl, unsigned long add } select_done = 1; } + set_table_dumped((u64) addr); } static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { @@ -272,30 +312,26 @@ no_facs: write_table(fd, (struct acpi_table_header *)&x, xaddr); } -static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) + +static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp) { struct acpi_table_header *sdt, *tbl = 0; - int xsdt = 1, i, num; + int i, num; char *offset; unsigned long addr; - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { - tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); - } - if (!tbl && rsdp->rsdt_physical_address) { - xsdt = 0; - tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); - } + + tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); if (!tbl) return 0; + sdt = malloc(tbl->length); memcpy(sdt, tbl, tbl->length); acpi_unmap_table(tbl); if (checksum((u8 *)sdt, sdt->length)) - fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); - num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); + fprintf(stderr, "Wrong checksum for %s!\n", "RSDT"); + num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u32); offset = (char *)sdt + sizeof(struct acpi_table_header); - for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { - addr = (xsdt) ? (unsigned long)(*(u64 *)offset): - (unsigned long)(*(u32 *)offset); + for (i = 0; i < num; ++i, offset += sizeof(u32)) { + addr = (unsigned long)(*(u32 *)offset); if (!addr) continue; tbl = acpi_map_table(addr, 0); if (!tbl) continue; @@ -303,28 +339,63 @@ static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) acpi_dump_FADT(fd, tbl, addr); } else { if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for generic table!\n"); + fprintf(stderr, "Wrong checksum for %.4s!\n", tbl->signature); write_table(fd, tbl, addr); } acpi_unmap_table(tbl); if (connect) { - if (xsdt) - (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); - else - (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); + (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); } } - if (xsdt) { - addr = (unsigned long)rsdp->xsdt_physical_address; - if (connect) { - rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); + addr = (unsigned long)rsdp->rsdt_physical_address; + if (connect) { + rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } + write_table(fd, sdt, addr); + free (sdt); + return 1; +} + + +static int acpi_dump_XSDT(int fd, struct acpi_rsdp_descriptor *rsdp) +{ + struct acpi_table_header *sdt, *tbl = 0; + int i, num; + char *offset; + unsigned long addr; + if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { + tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); + } + if (!tbl) return 0; + + sdt = malloc(tbl->length); + memcpy(sdt, tbl, tbl->length); + acpi_unmap_table(tbl); + if (checksum((u8 *)sdt, sdt->length)) + fprintf(stderr, "Wrong checksum for %s!\n", "XSDT"); + num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u64); + offset = (char *)sdt + sizeof(struct acpi_table_header); + for (i = 0; i < num; ++i, offset += sizeof(u64)) { + addr = (unsigned long)(*(u64 *)offset); + if (!addr) continue; + tbl = acpi_map_table(addr, 0); + if (!tbl) continue; + if (!memcmp(tbl->signature, FADT_SIG, 4)) { + acpi_dump_FADT(fd, tbl, addr); + } else { + if (checksum((u8 *)tbl, tbl->length)) + fprintf(stderr, "Wrong checksum for %.4s\n", tbl->signature); + write_table(fd, tbl, addr); } - } else { - addr = (unsigned long)rsdp->rsdt_physical_address; + acpi_unmap_table(tbl); if (connect) { - rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); } } + addr = (unsigned long)rsdp->xsdt_physical_address; + if (connect) { + rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } write_table(fd, sdt, addr); free (sdt); return 1; @@ -469,7 +540,9 @@ int main(int argc, char **argv) if (connect) { lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); } - if (!acpi_dump_SDT(fd, &rsdpx)) + if (!acpi_dump_XSDT(fd, &rsdpx)) + goto not_found; + if (!acpi_dump_RSDT(fd, &rsdpx)) goto not_found; if (connect) { lseek(fd, 0, SEEK_SET); -- cgit v1.2.2 From 39a55ff2c34a11ab9bbc8ba6f4dfb5d366cb2532 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 22:52:17 -0400 Subject: tools/power/acpi/acpidump: version 20071116 This is unchanged version 20071116, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. Signed-off-by: Len Brown --- tools/power/acpi/acpidump.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c index 8e5e19451ce1..a63dee960311 100644 --- a/tools/power/acpi/acpidump.c +++ b/tools/power/acpi/acpidump.c @@ -540,8 +540,11 @@ int main(int argc, char **argv) if (connect) { lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); } - if (!acpi_dump_XSDT(fd, &rsdpx)) - goto not_found; + if (rsdpx.revision > 1 && rsdpx.xsdt_physical_address) { + /* ACPIDUMP uses xsdt table */ + if (!acpi_dump_XSDT(fd, &rsdpx)) + goto not_found; + } if (!acpi_dump_RSDT(fd, &rsdpx)) goto not_found; if (connect) { -- cgit v1.2.2 From d4bb1c90c850c5163f28b1c04d16c5d85aaaf815 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 23:09:15 -0400 Subject: tools/power/acpi/acpidump: version 20101221 - find dynamic tables in sysfs This is unchanged version 20101221, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. This version finds dynamic tables exported by Linux in /sys/firmware/acpi/tables/dynamic Signed-off-by: Len Brown --- tools/power/acpi/acpidump.c | 187 +++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 98 deletions(-) (limited to 'tools') diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c index a63dee960311..07779871421c 100644 --- a/tools/power/acpi/acpidump.c +++ b/tools/power/acpi/acpidump.c @@ -1,6 +1,5 @@ /* * (c) Alexey Starikovskiy, Intel, 2005-2006. - * (c) Len Brown, Intel, 2007. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,6 +62,8 @@ typedef long long s64; #include #include +#include +#include #include #include @@ -186,40 +187,6 @@ static void acpi_show_data(int fd, u8 * data, int size) /* * Output ACPI table */ - -#define MAX_TABLES 128 -int next_table_dump; -u64 dumped_tables[MAX_TABLES]; - -void -set_table_dumped(u64 address) { - if (next_table_dump >= MAX_TABLES) { - printf("increase MAX_TABLES\n"); - exit(1); - } - dumped_tables[next_table_dump++] = address; -} - -/* - * list the tables as they are dumped - * check the list so that they are not dumped twice. - * - * this is needed because we follow both the XSDT and RSDT - * which generally point to all duplicate tables - * except the FADT - */ -int -check_table_dumped(u64 address) { - int i; - - for (i = 0; i < MAX_TABLES; ++i) { - if (address == dumped_tables[i]) - return 1; - if (dumped_tables[i] == 0) - return 0; - } - return 0; -} static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) { char buff[80]; @@ -233,10 +200,6 @@ static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned lo static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) { static int select_done = 0; - - if (check_table_dumped((u64)addr)) - return; - if (!select_sig[0]) { if (print) { acpi_show_table(fd, tbl, addr); @@ -255,7 +218,6 @@ static void write_table(int fd, struct acpi_table_header *tbl, unsigned long add } select_done = 1; } - set_table_dumped((u64) addr); } static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { @@ -312,26 +274,30 @@ no_facs: write_table(fd, (struct acpi_table_header *)&x, xaddr); } - -static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp) +static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) { struct acpi_table_header *sdt, *tbl = 0; - int i, num; + int xsdt = 1, i, num; char *offset; unsigned long addr; - - tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); + if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { + tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); + } + if (!tbl && rsdp->rsdt_physical_address) { + xsdt = 0; + tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); + } if (!tbl) return 0; - sdt = malloc(tbl->length); memcpy(sdt, tbl, tbl->length); acpi_unmap_table(tbl); if (checksum((u8 *)sdt, sdt->length)) - fprintf(stderr, "Wrong checksum for %s!\n", "RSDT"); - num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u32); + fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); + num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); offset = (char *)sdt + sizeof(struct acpi_table_header); - for (i = 0; i < num; ++i, offset += sizeof(u32)) { - addr = (unsigned long)(*(u32 *)offset); + for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { + addr = (xsdt) ? (unsigned long)(*(u64 *)offset): + (unsigned long)(*(u32 *)offset); if (!addr) continue; tbl = acpi_map_table(addr, 0); if (!tbl) continue; @@ -339,66 +305,92 @@ static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp) acpi_dump_FADT(fd, tbl, addr); } else { if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for %.4s!\n", tbl->signature); + fprintf(stderr, "Wrong checksum for generic table!\n"); write_table(fd, tbl, addr); } acpi_unmap_table(tbl); if (connect) { - (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); + if (xsdt) + (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); + else + (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); } } - addr = (unsigned long)rsdp->rsdt_physical_address; - if (connect) { - rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + if (xsdt) { + addr = (unsigned long)rsdp->xsdt_physical_address; + if (connect) { + rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } + } else { + addr = (unsigned long)rsdp->rsdt_physical_address; + if (connect) { + rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } } write_table(fd, sdt, addr); free (sdt); return 1; } +#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic" -static int acpi_dump_XSDT(int fd, struct acpi_rsdp_descriptor *rsdp) +static void acpi_dump_dynamic_SSDT(int fd) { - struct acpi_table_header *sdt, *tbl = 0; - int i, num; - char *offset; - unsigned long addr; - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { - tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); + struct stat file_stat; + char filename[256], *ptr; + DIR *tabledir; + struct dirent *entry; + FILE *fp; + int count, readcount, length; + struct acpi_table_header table_header, *ptable; + + if (stat(DYNAMIC_SSDT, &file_stat) == -1) { + /* The directory doesn't exist */ + return; } - if (!tbl) return 0; - - sdt = malloc(tbl->length); - memcpy(sdt, tbl, tbl->length); - acpi_unmap_table(tbl); - if (checksum((u8 *)sdt, sdt->length)) - fprintf(stderr, "Wrong checksum for %s!\n", "XSDT"); - num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u64); - offset = (char *)sdt + sizeof(struct acpi_table_header); - for (i = 0; i < num; ++i, offset += sizeof(u64)) { - addr = (unsigned long)(*(u64 *)offset); - if (!addr) continue; - tbl = acpi_map_table(addr, 0); - if (!tbl) continue; - if (!memcmp(tbl->signature, FADT_SIG, 4)) { - acpi_dump_FADT(fd, tbl, addr); - } else { - if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for %.4s\n", tbl->signature); - write_table(fd, tbl, addr); + tabledir = opendir(DYNAMIC_SSDT); + if(!tabledir){ + /*can't open the directory */ + return; + } + + while ((entry = readdir(tabledir)) != 0){ + /* skip the file of . /.. */ + if (entry->d_name[0] == '.') + continue; + + sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name); + fp = fopen(filename, "r"); + if (fp == NULL) { + fprintf(stderr, "Can't open the file of %s\n", + filename); + continue; } - acpi_unmap_table(tbl); - if (connect) { - (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); + /* Read the Table header to parse the table length */ + count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); + if (count < sizeof(table_header)) { + /* the length is lessn than ACPI table header. skip it */ + fclose(fp); + continue; } + length = table_header.length; + ptr = malloc(table_header.length); + fseek(fp, 0, SEEK_SET); + readcount = 0; + while(!feof(fp) && readcount < length) { + count = fread(ptr + readcount, 1, 256, fp); + readcount += count; + } + fclose(fp); + ptable = (struct acpi_table_header *) ptr; + if (checksum((u8 *) ptable, ptable->length)) + fprintf(stderr, "Wrong checksum " + "for dynamic SSDT table!\n"); + write_table(fd, ptable, 0); + free(ptr); } - addr = (unsigned long)rsdp->xsdt_physical_address; - if (connect) { - rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); - } - write_table(fd, sdt, addr); - free (sdt); - return 1; + closedir(tabledir); + return; } static void usage(const char *progname) @@ -518,6 +510,7 @@ int main(int argc, char **argv) goto not_found; write(fd, raw, length); acpi_unmap_memory(raw, length); + close(fd); return 0; } @@ -540,12 +533,7 @@ int main(int argc, char **argv) if (connect) { lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); } - if (rsdpx.revision > 1 && rsdpx.xsdt_physical_address) { - /* ACPIDUMP uses xsdt table */ - if (!acpi_dump_XSDT(fd, &rsdpx)) - goto not_found; - } - if (!acpi_dump_RSDT(fd, &rsdpx)) + if (!acpi_dump_SDT(fd, &rsdpx)) goto not_found; if (connect) { lseek(fd, 0, SEEK_SET); @@ -560,8 +548,11 @@ int main(int argc, char **argv) buff[0] = '\n'; write(fd, buff, 1); } + acpi_dump_dynamic_SSDT(fd); + close(fd); return 0; not_found: + close(fd); fprintf(stderr, "ACPI tables were not found. If you know location " "of RSD PTR table (from dmesg, etc), " "supply it with either --addr or -a option\n"); -- cgit v1.2.2 From 0e7cc27935cda92c7a39a00791d0d4bbffeab117 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 23:30:22 -0400 Subject: tools/power/acpi/acpidump: create acpidump(8), local make install targets Signed-off-by: Len Brown --- tools/power/acpi/Makefile | 4 +++ tools/power/acpi/acpidump.8 | 59 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tools/power/acpi/acpidump.8 (limited to 'tools') diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index dad79a69b679..6b9cf7a987c7 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -12,3 +12,7 @@ CLEANFILES= $(PROG) clean : rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~ +install : + install acpidump /usr/bin/acpidump + install acpidump.8 /usr/share/man/man8 + 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 @@ +.TH ACPIDUMP 8 +.SH NAME +acpidump \- Dump system's ACPI tables to an ASCII file. +.SH SYNOPSIS +.ft B +.B acpidump > acpidump.out +.SH DESCRIPTION +\fBacpidump \fP dumps the systems ACPI tables to an ASCII file +appropriate for attaching to a bug report. + +Subsequently, they can be processed by utilities in the ACPICA package. +.SS Options +no options worth worrying about. +.PP +.SH EXAMPLE + +.nf +# acpidump > acpidump.out + +$ acpixtract -a acpidump.out + Acpi table [DSDT] - 15974 bytes written to DSDT.dat + Acpi table [FACS] - 64 bytes written to FACS.dat + Acpi table [FACP] - 116 bytes written to FACP.dat + Acpi table [APIC] - 120 bytes written to APIC.dat + Acpi table [MCFG] - 60 bytes written to MCFG.dat + Acpi table [SSDT] - 444 bytes written to SSDT1.dat + Acpi table [SSDT] - 439 bytes written to SSDT2.dat + Acpi table [SSDT] - 439 bytes written to SSDT3.dat + Acpi table [SSDT] - 439 bytes written to SSDT4.dat + Acpi table [SSDT] - 439 bytes written to SSDT5.dat + Acpi table [RSDT] - 76 bytes written to RSDT.dat + Acpi table [RSDP] - 20 bytes written to RSDP.dat + +$ iasl -d *.dat +... +.fi +creates *.dsl, a human readable form which can be edited +and compiled using iasl. + + +.SH NOTES + +.B "acpidump " +must be run as root. + +.SH REFERENCES +ACPICA: https://acpica.org/ + +.SH FILES +.ta +.nf +/dev/mem +/sys/firmware/acpi/tables/dynamic/* +.fi + +.PP +.SH AUTHOR +.nf +Written by Len Brown -- cgit v1.2.2 From b7e1751278ce8f6d727e19832ecf6f6ef707233e Mon Sep 17 00:00:00 2001 From: Yakui Zhao Date: Sat, 22 Sep 2012 23:09:15 -0400 Subject: tools/power/acpi/acpidump: version 20101221 - find dynamic tables in sysfs This is unchanged version 20101221, plus a small bit in DEFINE_ALTERNATE_TYPES to enable building with latest kernel headers. This version finds dynamic tables exported by Linux in /sys/firmware/acpi/tables/dynamic Signed-off-by: Yakui Zhao Signed-off-by: Len Brown --- tools/power/acpi/acpidump.c | 187 +++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 98 deletions(-) (limited to 'tools') diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c index a63dee960311..07779871421c 100644 --- a/tools/power/acpi/acpidump.c +++ b/tools/power/acpi/acpidump.c @@ -1,6 +1,5 @@ /* * (c) Alexey Starikovskiy, Intel, 2005-2006. - * (c) Len Brown, Intel, 2007. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,6 +62,8 @@ typedef long long s64; #include #include +#include +#include #include #include @@ -186,40 +187,6 @@ static void acpi_show_data(int fd, u8 * data, int size) /* * Output ACPI table */ - -#define MAX_TABLES 128 -int next_table_dump; -u64 dumped_tables[MAX_TABLES]; - -void -set_table_dumped(u64 address) { - if (next_table_dump >= MAX_TABLES) { - printf("increase MAX_TABLES\n"); - exit(1); - } - dumped_tables[next_table_dump++] = address; -} - -/* - * list the tables as they are dumped - * check the list so that they are not dumped twice. - * - * this is needed because we follow both the XSDT and RSDT - * which generally point to all duplicate tables - * except the FADT - */ -int -check_table_dumped(u64 address) { - int i; - - for (i = 0; i < MAX_TABLES; ++i) { - if (address == dumped_tables[i]) - return 1; - if (dumped_tables[i] == 0) - return 0; - } - return 0; -} static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) { char buff[80]; @@ -233,10 +200,6 @@ static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned lo static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) { static int select_done = 0; - - if (check_table_dumped((u64)addr)) - return; - if (!select_sig[0]) { if (print) { acpi_show_table(fd, tbl, addr); @@ -255,7 +218,6 @@ static void write_table(int fd, struct acpi_table_header *tbl, unsigned long add } select_done = 1; } - set_table_dumped((u64) addr); } static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { @@ -312,26 +274,30 @@ no_facs: write_table(fd, (struct acpi_table_header *)&x, xaddr); } - -static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp) +static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) { struct acpi_table_header *sdt, *tbl = 0; - int i, num; + int xsdt = 1, i, num; char *offset; unsigned long addr; - - tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); + if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { + tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); + } + if (!tbl && rsdp->rsdt_physical_address) { + xsdt = 0; + tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); + } if (!tbl) return 0; - sdt = malloc(tbl->length); memcpy(sdt, tbl, tbl->length); acpi_unmap_table(tbl); if (checksum((u8 *)sdt, sdt->length)) - fprintf(stderr, "Wrong checksum for %s!\n", "RSDT"); - num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u32); + fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); + num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); offset = (char *)sdt + sizeof(struct acpi_table_header); - for (i = 0; i < num; ++i, offset += sizeof(u32)) { - addr = (unsigned long)(*(u32 *)offset); + for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { + addr = (xsdt) ? (unsigned long)(*(u64 *)offset): + (unsigned long)(*(u32 *)offset); if (!addr) continue; tbl = acpi_map_table(addr, 0); if (!tbl) continue; @@ -339,66 +305,92 @@ static int acpi_dump_RSDT(int fd, struct acpi_rsdp_descriptor *rsdp) acpi_dump_FADT(fd, tbl, addr); } else { if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for %.4s!\n", tbl->signature); + fprintf(stderr, "Wrong checksum for generic table!\n"); write_table(fd, tbl, addr); } acpi_unmap_table(tbl); if (connect) { - (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); + if (xsdt) + (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); + else + (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); } } - addr = (unsigned long)rsdp->rsdt_physical_address; - if (connect) { - rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + if (xsdt) { + addr = (unsigned long)rsdp->xsdt_physical_address; + if (connect) { + rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } + } else { + addr = (unsigned long)rsdp->rsdt_physical_address; + if (connect) { + rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); + } } write_table(fd, sdt, addr); free (sdt); return 1; } +#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic" -static int acpi_dump_XSDT(int fd, struct acpi_rsdp_descriptor *rsdp) +static void acpi_dump_dynamic_SSDT(int fd) { - struct acpi_table_header *sdt, *tbl = 0; - int i, num; - char *offset; - unsigned long addr; - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { - tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); + struct stat file_stat; + char filename[256], *ptr; + DIR *tabledir; + struct dirent *entry; + FILE *fp; + int count, readcount, length; + struct acpi_table_header table_header, *ptable; + + if (stat(DYNAMIC_SSDT, &file_stat) == -1) { + /* The directory doesn't exist */ + return; } - if (!tbl) return 0; - - sdt = malloc(tbl->length); - memcpy(sdt, tbl, tbl->length); - acpi_unmap_table(tbl); - if (checksum((u8 *)sdt, sdt->length)) - fprintf(stderr, "Wrong checksum for %s!\n", "XSDT"); - num = (sdt->length - sizeof(struct acpi_table_header))/sizeof(u64); - offset = (char *)sdt + sizeof(struct acpi_table_header); - for (i = 0; i < num; ++i, offset += sizeof(u64)) { - addr = (unsigned long)(*(u64 *)offset); - if (!addr) continue; - tbl = acpi_map_table(addr, 0); - if (!tbl) continue; - if (!memcmp(tbl->signature, FADT_SIG, 4)) { - acpi_dump_FADT(fd, tbl, addr); - } else { - if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for %.4s\n", tbl->signature); - write_table(fd, tbl, addr); + tabledir = opendir(DYNAMIC_SSDT); + if(!tabledir){ + /*can't open the directory */ + return; + } + + while ((entry = readdir(tabledir)) != 0){ + /* skip the file of . /.. */ + if (entry->d_name[0] == '.') + continue; + + sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name); + fp = fopen(filename, "r"); + if (fp == NULL) { + fprintf(stderr, "Can't open the file of %s\n", + filename); + continue; } - acpi_unmap_table(tbl); - if (connect) { - (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); + /* Read the Table header to parse the table length */ + count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); + if (count < sizeof(table_header)) { + /* the length is lessn than ACPI table header. skip it */ + fclose(fp); + continue; } + length = table_header.length; + ptr = malloc(table_header.length); + fseek(fp, 0, SEEK_SET); + readcount = 0; + while(!feof(fp) && readcount < length) { + count = fread(ptr + readcount, 1, 256, fp); + readcount += count; + } + fclose(fp); + ptable = (struct acpi_table_header *) ptr; + if (checksum((u8 *) ptable, ptable->length)) + fprintf(stderr, "Wrong checksum " + "for dynamic SSDT table!\n"); + write_table(fd, ptable, 0); + free(ptr); } - addr = (unsigned long)rsdp->xsdt_physical_address; - if (connect) { - rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); - } - write_table(fd, sdt, addr); - free (sdt); - return 1; + closedir(tabledir); + return; } static void usage(const char *progname) @@ -518,6 +510,7 @@ int main(int argc, char **argv) goto not_found; write(fd, raw, length); acpi_unmap_memory(raw, length); + close(fd); return 0; } @@ -540,12 +533,7 @@ int main(int argc, char **argv) if (connect) { lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); } - if (rsdpx.revision > 1 && rsdpx.xsdt_physical_address) { - /* ACPIDUMP uses xsdt table */ - if (!acpi_dump_XSDT(fd, &rsdpx)) - goto not_found; - } - if (!acpi_dump_RSDT(fd, &rsdpx)) + if (!acpi_dump_SDT(fd, &rsdpx)) goto not_found; if (connect) { lseek(fd, 0, SEEK_SET); @@ -560,8 +548,11 @@ int main(int argc, char **argv) buff[0] = '\n'; write(fd, buff, 1); } + acpi_dump_dynamic_SSDT(fd); + close(fd); return 0; not_found: + close(fd); fprintf(stderr, "ACPI tables were not found. If you know location " "of RSD PTR table (from dmesg, etc), " "supply it with either --addr or -a option\n"); -- cgit v1.2.2 From 45e1424be7cf0897f27adbd15936acab87199118 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 23:30:22 -0400 Subject: tools/power/acpi/acpidump: create acpidump(8), local make install targets Signed-off-by: Len Brown --- tools/power/acpi/Makefile | 4 +++ tools/power/acpi/acpidump.8 | 59 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tools/power/acpi/acpidump.8 (limited to 'tools') diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index dad79a69b679..6b9cf7a987c7 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -12,3 +12,7 @@ CLEANFILES= $(PROG) clean : rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~ +install : + install acpidump /usr/bin/acpidump + install acpidump.8 /usr/share/man/man8 + 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 @@ +.TH ACPIDUMP 8 +.SH NAME +acpidump \- Dump system's ACPI tables to an ASCII file. +.SH SYNOPSIS +.ft B +.B acpidump > acpidump.out +.SH DESCRIPTION +\fBacpidump \fP dumps the systems ACPI tables to an ASCII file +appropriate for attaching to a bug report. + +Subsequently, they can be processed by utilities in the ACPICA package. +.SS Options +no options worth worrying about. +.PP +.SH EXAMPLE + +.nf +# acpidump > acpidump.out + +$ acpixtract -a acpidump.out + Acpi table [DSDT] - 15974 bytes written to DSDT.dat + Acpi table [FACS] - 64 bytes written to FACS.dat + Acpi table [FACP] - 116 bytes written to FACP.dat + Acpi table [APIC] - 120 bytes written to APIC.dat + Acpi table [MCFG] - 60 bytes written to MCFG.dat + Acpi table [SSDT] - 444 bytes written to SSDT1.dat + Acpi table [SSDT] - 439 bytes written to SSDT2.dat + Acpi table [SSDT] - 439 bytes written to SSDT3.dat + Acpi table [SSDT] - 439 bytes written to SSDT4.dat + Acpi table [SSDT] - 439 bytes written to SSDT5.dat + Acpi table [RSDT] - 76 bytes written to RSDT.dat + Acpi table [RSDP] - 20 bytes written to RSDP.dat + +$ iasl -d *.dat +... +.fi +creates *.dsl, a human readable form which can be edited +and compiled using iasl. + + +.SH NOTES + +.B "acpidump " +must be run as root. + +.SH REFERENCES +ACPICA: https://acpica.org/ + +.SH FILES +.ta +.nf +/dev/mem +/sys/firmware/acpi/tables/dynamic/* +.fi + +.PP +.SH AUTHOR +.nf +Written by Len Brown -- cgit v1.2.2 From 1300651b40298ce60ee628b8f13f8c121706b06c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 26 Sep 2012 18:11:31 -0400 Subject: tools/power turbostat: run on IVB Xeon This fix is required to run on IVB Xeon, which previously had an incorrect cpuid model number listed. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 861d77190206..7108d8671c11 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1038,7 +1038,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) case 0x2A: /* SNB */ case 0x2D: /* SNB Xeon */ case 0x3A: /* IVB */ - case 0x3D: /* IVB Xeon */ + case 0x3E: /* IVB Xeon */ return 1; case 0x2E: /* Nehalem-EX Xeon - Beckton */ case 0x2F: /* Westmere-EX Xeon - Eagleton */ @@ -1056,7 +1056,7 @@ int is_snb(unsigned int family, unsigned int model) case 0x2A: case 0x2D: case 0x3A: /* IVB */ - case 0x3D: /* IVB Xeon */ + case 0x3E: /* IVB Xeon */ return 1; } return 0; -- cgit v1.2.2 From d7db69016548c4bf3bec3556f6a15b9332dae34f Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 20 Sep 2012 13:43:07 -0400 Subject: tools/power turbostat: delete unused line MSR_TSC is no longer needed because we now use RDTSC directly. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 1 - 1 file changed, 1 deletion(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 7108d8671c11..3c9dc54c710c 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -35,7 +35,6 @@ #include #include -#define MSR_TSC 0x10 #define MSR_NEHALEM_PLATFORM_INFO 0xCE #define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD #define MSR_APERF 0xE8 -- cgit v1.2.2 From 6574a5d5053cd3b8e7c088900b80a9ff51895450 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 21 Sep 2012 00:01:31 -0400 Subject: tools/power turbostat: print more turbo-limit information The "turbo-limit" is the maximum opportunistic processor speed, assuming no electrical or thermal constraints. For a given processor, the turbo-limit varies, depending on the number of active cores. Generally, there is more opportunity when fewer cores are active. Under the "-v" verbose option, turbostat would print the turbo-limits for the four cases of 1 to 4 cores active. Expand that capability to cover the cases of turbo opportunities with up to 16 cores active. Note that not all hardware platforms supply this information, and that sometimes a valid limit may be specified for a core which is not actually present. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 95 ++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 3c9dc54c710c..5db4addbe1d9 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -37,6 +37,7 @@ #define MSR_NEHALEM_PLATFORM_INFO 0xCE #define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD +#define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE #define MSR_APERF 0xE8 #define MSR_MPERF 0xE7 #define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */ @@ -61,6 +62,7 @@ unsigned int genuine_intel; unsigned int has_invariant_tsc; unsigned int do_nehalem_platform_info; unsigned int do_nehalem_turbo_ratio_limit; +unsigned int do_ivt_turbo_ratio_limit; unsigned int extra_msr_offset; double bclk; unsigned int show_pkg; @@ -676,6 +678,9 @@ void print_verbose_header(void) get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); + if (verbose > 1) + fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); + ratio = (msr >> 40) & 0xFF; fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", ratio, bclk, ratio * bclk); @@ -684,14 +689,84 @@ void print_verbose_header(void) fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", ratio, bclk, ratio * bclk); + if (!do_ivt_turbo_ratio_limit) + goto print_nhm_turbo_ratio_limits; + + get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr); + if (verbose > 1) - fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); + fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr); + + ratio = (msr >> 56) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 48) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 40) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 32) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 24) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 16) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 8) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 0) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", + ratio, bclk, ratio * bclk); + +print_nhm_turbo_ratio_limits: if (!do_nehalem_turbo_ratio_limit) return; get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); + if (verbose > 1) + fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr); + + ratio = (msr >> 56) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 48) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 40) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n", + ratio, bclk, ratio * bclk); + + ratio = (msr >> 32) & 0xFF; + if (ratio) + fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n", + ratio, bclk, ratio * bclk); + ratio = (msr >> 24) & 0xFF; if (ratio) fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", @@ -711,7 +786,6 @@ void print_verbose_header(void) if (ratio) fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", ratio, bclk, ratio * bclk); - } void free_all_buffers(void) @@ -1045,6 +1119,22 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model) return 0; } } +int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) +{ + if (!genuine_intel) + return 0; + + if (family != 6) + return 0; + + switch (model) { + case 0x3E: /* IVB Xeon */ + return 1; + default: + return 0; + } +} + int is_snb(unsigned int family, unsigned int model) { @@ -1144,6 +1234,7 @@ void check_cpuid() bclk = discover_bclk(family, model); do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); + do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model); } -- cgit v1.2.2 From 130ff304f6d31484fc73bb337bc635cba1ffe04c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 21 Sep 2012 22:56:06 -0400 Subject: tools/power turbostat: make -M output pretty The -M option dumps the specified 64-bit MSR with every sample. Previously it was output at the end of each line. However, with the v2 style of printing, the lines are now staggered, making MSR output hard to read. So move the MSR output column to the left where things are aligned. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5db4addbe1d9..5ce88dd8c95a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -223,6 +223,8 @@ void print_header(void) if (has_aperf) outp += sprintf(outp, " GHz"); outp += sprintf(outp, " TSC"); + if (extra_msr_offset) + outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset); if (do_nhm_cstates) outp += sprintf(outp, " %%c1"); if (do_nhm_cstates) @@ -239,8 +241,6 @@ void print_header(void) outp += sprintf(outp, " %%pc6"); if (do_snb_cstates) outp += sprintf(outp, " %%pc7"); - if (extra_msr_offset) - outp += sprintf(outp, " MSR 0x%x ", extra_msr_offset); outp += sprintf(outp, "\n"); } @@ -361,6 +361,10 @@ int format_counters(struct thread_data *t, struct core_data *c, /* TSC */ outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); + /* MSR */ + if (extra_msr_offset) + outp += sprintf(outp, " 0x%016llx", t->extra_msr); + if (do_nhm_cstates) { if (!skip_c1) outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); @@ -392,8 +396,6 @@ int format_counters(struct thread_data *t, struct core_data *c, if (do_snb_cstates) outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); done: - if (extra_msr_offset) - outp += sprintf(outp, " 0x%016llx", t->extra_msr); outp += sprintf(outp, "\n"); return 0; -- cgit v1.2.2 From 2f32edf12c1eafc8e5b1b0337360993fde1b3565 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 21 Sep 2012 23:45:46 -0400 Subject: tools/power turbostat: add [-m MSR#] option -m MSR# prints the specified MSR in 32-bit format -M MSR# prints the specified MSR in 64-bit format Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 14 +++++++- tools/power/x86/turbostat/turbostat.c | 68 +++++++++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 74e44507dfe9..8e7b29af78f6 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -6,12 +6,14 @@ turbostat \- Report processor frequency and idle statistics .B turbostat .RB [ "\-s" ] .RB [ "\-v" ] +.RB [ "\-m MSR#" ] .RB [ "\-M MSR#" ] .RB command .br .B turbostat .RB [ "\-s" ] .RB [ "\-v" ] +.RB [ "\-m MSR#" ] .RB [ "\-M MSR#" ] .RB [ "\-i interval_sec" ] .SH DESCRIPTION @@ -35,7 +37,10 @@ The \fB-p\fP option limits output to the 1st thread in each package. .PP The \fB-v\fP option increases verbosity. .PP -The \fB-M MSR#\fP option dumps the specified MSR, +The \fB-m MSR#\fP option dumps the specified 32-bit MSR, +in addition to the usual frequency and idle statistics. +.PP +The \fB-M MSR#\fP option dumps the specified 64-bit MSR, in addition to the usual frequency and idle statistics. .PP The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. @@ -165,6 +170,13 @@ may work poorly on Linux-2.6.20 through 2.6.29, as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF in those kernels. +If the TSC column does not make sense, then +the other numbers will also make no sense. +Turbostat is lightweight, and its data collection is not atomic. +These issues are usually caused by an extremely short measurement +interval (much less than 1 second), or system activity that prevents +turbostat from being able to run on all CPUS to quickly collect data. + The APERF, MPERF MSRs are defined to count non-halted cycles. Although it is not guaranteed by the architecture, turbostat assumes that 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 5ce88dd8c95a..946e9ab48edb 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -63,7 +63,8 @@ unsigned int has_invariant_tsc; unsigned int do_nehalem_platform_info; unsigned int do_nehalem_turbo_ratio_limit; unsigned int do_ivt_turbo_ratio_limit; -unsigned int extra_msr_offset; +unsigned int extra_msr_offset32; +unsigned int extra_msr_offset64; double bclk; unsigned int show_pkg; unsigned int show_core; @@ -84,7 +85,8 @@ struct thread_data { unsigned long long aperf; unsigned long long mperf; unsigned long long c1; /* derived */ - unsigned long long extra_msr; + unsigned long long extra_msr64; + unsigned int extra_msr32; unsigned int cpu_id; unsigned int flags; #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 @@ -206,6 +208,24 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) return 0; } +/* + * Truncate the 8 bytes we read from /dev/cpu/.../msr + * to the 4 bytes requested + */ + +int get_msr32(int cpu, off_t offset, unsigned int *msr) +{ + int retval; + + unsigned long long msr64; + + retval = get_msr(cpu, offset, &msr64); + *msr = (unsigned int) msr64; + + return retval; +} + + void print_header(void) { if (show_pkg) @@ -223,8 +243,10 @@ void print_header(void) if (has_aperf) outp += sprintf(outp, " GHz"); outp += sprintf(outp, " TSC"); - if (extra_msr_offset) - outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset); + if (extra_msr_offset32) + outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset32); + if (extra_msr_offset64) + outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset64); if (do_nhm_cstates) outp += sprintf(outp, " %%c1"); if (do_nhm_cstates) @@ -256,8 +278,10 @@ int dump_counters(struct thread_data *t, struct core_data *c, fprintf(stderr, "aperf: %016llX\n", t->aperf); fprintf(stderr, "mperf: %016llX\n", t->mperf); fprintf(stderr, "c1: %016llX\n", t->c1); + fprintf(stderr, "msr0x%x: %08X\n", + extra_msr_offset32, t->extra_msr32); fprintf(stderr, "msr0x%x: %016llX\n", - extra_msr_offset, t->extra_msr); + extra_msr_offset64, t->extra_msr64); } if (c) { @@ -361,9 +385,13 @@ int format_counters(struct thread_data *t, struct core_data *c, /* TSC */ outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); + /* msr */ + if (extra_msr_offset32) + outp += sprintf(outp, " 0x%08x", t->extra_msr32); + /* MSR */ - if (extra_msr_offset) - outp += sprintf(outp, " 0x%016llx", t->extra_msr); + if (extra_msr_offset64) + outp += sprintf(outp, " 0x%016llx", t->extra_msr64); if (do_nhm_cstates) { if (!skip_c1) @@ -506,9 +534,10 @@ delta_thread(struct thread_data *new, struct thread_data *old, } /* - * for "extra msr", just copy the latest w/o subtracting + * Extra MSR is a snapshot, simply copy latest w/o subtracting */ - old->extra_msr = new->extra_msr; + old->extra_msr32 = new->extra_msr32; + old->extra_msr64 = new->extra_msr64; } int delta_cpu(struct thread_data *t, struct core_data *c, @@ -632,8 +661,12 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) return -4; } - if (extra_msr_offset) - if (get_msr(cpu, extra_msr_offset, &t->extra_msr)) + if (extra_msr_offset32) + if (get_msr32(cpu, extra_msr_offset32, &t->extra_msr32)) + return -5; + + if (extra_msr_offset64) + if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64)) return -5; /* collect core counters only for 1st thread in core */ @@ -1242,7 +1275,7 @@ void check_cpuid() void usage() { - fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n", + fprintf(stderr, "%s: [-v] [-m msr#] [-M MSR#] [-i interval_sec | command ...]\n", progname); exit(1); } @@ -1532,7 +1565,7 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) { + while ((opt = getopt(argc, argv, "+cpsvi:m:M:")) != -1) { switch (opt) { case 'c': show_core_only++; @@ -1549,10 +1582,15 @@ void cmdline(int argc, char **argv) case 'i': interval_sec = atoi(optarg); break; + case 'm': + sscanf(optarg, "%x", &extra_msr_offset32); + if (verbose > 1) + fprintf(stderr, "msr 0x%X\n", extra_msr_offset32); + break; case 'M': - sscanf(optarg, "%x", &extra_msr_offset); + sscanf(optarg, "%x", &extra_msr_offset64); if (verbose > 1) - fprintf(stderr, "MSR 0x%X\n", extra_msr_offset); + fprintf(stderr, "MSR 0x%X\n", extra_msr_offset64); break; default: usage(); -- cgit v1.2.2 From 8e180f3cb6b7510a3bdf14e16ce87c9f5d86f102 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 22 Sep 2012 01:25:08 -0400 Subject: tools/power turbostat: add [-d MSR#][-D MSR#] options to print counter deltas # turbostat -d 0x34 is useful for printing the number of SMI's within an interval on Nehalem and newer processors. where # turbostat -m 0x34 will simply print out the total SMI count since reset. Suggested-by: Andi Kleen Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 43 +++++++++++----- tools/power/x86/turbostat/turbostat.c | 95 +++++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 44 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 8e7b29af78f6..0fc7a11f300e 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -4,17 +4,11 @@ turbostat \- Report processor frequency and idle statistics .SH SYNOPSIS .ft B .B turbostat -.RB [ "\-s" ] -.RB [ "\-v" ] -.RB [ "\-m MSR#" ] -.RB [ "\-M MSR#" ] +.RB [ Options ] .RB command .br .B turbostat -.RB [ "\-s" ] -.RB [ "\-v" ] -.RB [ "\-m MSR#" ] -.RB [ "\-M MSR#" ] +.RB [ Options ] .RB [ "\-i interval_sec" ] .SH DESCRIPTION \fBturbostat \fP reports processor topology, frequency @@ -37,11 +31,13 @@ The \fB-p\fP option limits output to the 1st thread in each package. .PP The \fB-v\fP option increases verbosity. .PP -The \fB-m MSR#\fP option dumps the specified 32-bit MSR, -in addition to the usual frequency and idle statistics. +The \fB-d MSR#\fP option includes the delta of the specified 32-bit MSR counter. .PP -The \fB-M MSR#\fP option dumps the specified 64-bit MSR, -in addition to the usual frequency and idle statistics. +The \fB-D MSR#\fP option includes the delta of the specified 64-bit MSR counter. +.PP +The \fB-m MSR#\fP option includes the the specified 32-bit MSR value. +.PP +The \fB-M MSR#\fP option includes the the specified 64-bit MSR value. .PP The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. The default is 5 seconds. @@ -155,6 +151,29 @@ Note that turbostat reports average GHz of 3.63, while the arithmetic average of the GHz column above is lower. This is a weighted average, where the weight is %c0. ie. it is the total number of un-halted cycles elapsed per time divided by the number of CPUs. +.SH SMI COUNTING EXAMPLE +On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter. +Using the -m option, you can display how many SMIs have fired since reset, or if there +are SMIs during the measurement interval, you can display the delta using the -d option. +.nf +[root@x980 ~]# turbostat -m 0x34 +cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6 + 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55 + 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55 + 0 6 0.14 1.63 3.38 0x00000056 5.30 + 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52 + 1 8 0.10 1.65 3.38 0x00000056 18.05 + 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50 + 2 10 0.10 1.63 3.38 0x00000056 6.93 + 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16 + 8 7 0.08 1.64 3.38 0x00000056 5.12 + 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38 + 9 9 0.09 1.68 3.38 0x00000056 9.32 + 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23 + 10 11 1.72 1.65 3.38 0x00000056 15.05 +^C +[root@x980 ~]# +.fi .SH NOTES .B "turbostat " diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 946e9ab48edb..e38976c0b0a2 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -65,6 +65,8 @@ unsigned int do_nehalem_turbo_ratio_limit; unsigned int do_ivt_turbo_ratio_limit; unsigned int extra_msr_offset32; unsigned int extra_msr_offset64; +unsigned int extra_delta_offset32; +unsigned int extra_delta_offset64; double bclk; unsigned int show_pkg; unsigned int show_core; @@ -86,7 +88,9 @@ struct thread_data { unsigned long long mperf; unsigned long long c1; /* derived */ unsigned long long extra_msr64; - unsigned int extra_msr32; + unsigned long long extra_delta64; + unsigned long long extra_msr32; + unsigned long long extra_delta32; unsigned int cpu_id; unsigned int flags; #define CPU_IS_FIRST_THREAD_IN_CORE 0x2 @@ -208,24 +212,6 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) return 0; } -/* - * Truncate the 8 bytes we read from /dev/cpu/.../msr - * to the 4 bytes requested - */ - -int get_msr32(int cpu, off_t offset, unsigned int *msr) -{ - int retval; - - unsigned long long msr64; - - retval = get_msr(cpu, offset, &msr64); - *msr = (unsigned int) msr64; - - return retval; -} - - void print_header(void) { if (show_pkg) @@ -243,10 +229,14 @@ void print_header(void) if (has_aperf) outp += sprintf(outp, " GHz"); outp += sprintf(outp, " TSC"); + if (extra_delta_offset32) + outp += sprintf(outp, " delta 0x%03X", extra_delta_offset32); + if (extra_delta_offset64) + outp += sprintf(outp, " DELTA 0x%03X", extra_delta_offset64); if (extra_msr_offset32) - outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset32); + outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); if (extra_msr_offset64) - outp += sprintf(outp, " MSR 0x%04X", extra_msr_offset64); + outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); if (do_nhm_cstates) outp += sprintf(outp, " %%c1"); if (do_nhm_cstates) @@ -278,7 +268,11 @@ int dump_counters(struct thread_data *t, struct core_data *c, fprintf(stderr, "aperf: %016llX\n", t->aperf); fprintf(stderr, "mperf: %016llX\n", t->mperf); fprintf(stderr, "c1: %016llX\n", t->c1); - fprintf(stderr, "msr0x%x: %08X\n", + fprintf(stderr, "msr0x%x: %08llX\n", + extra_delta_offset32, t->extra_delta32); + fprintf(stderr, "msr0x%x: %016llX\n", + extra_delta_offset64, t->extra_delta64); + fprintf(stderr, "msr0x%x: %08llX\n", extra_msr_offset32, t->extra_msr32); fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset64, t->extra_msr64); @@ -385,9 +379,16 @@ int format_counters(struct thread_data *t, struct core_data *c, /* TSC */ outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); + /* delta */ + if (extra_delta_offset32) + outp += sprintf(outp, " %11llu", t->extra_delta32); + + /* DELTA */ + if (extra_delta_offset64) + outp += sprintf(outp, " %11llu", t->extra_delta64); /* msr */ if (extra_msr_offset32) - outp += sprintf(outp, " 0x%08x", t->extra_msr32); + outp += sprintf(outp, " 0x%08llx", t->extra_msr32); /* MSR */ if (extra_msr_offset64) @@ -533,8 +534,13 @@ delta_thread(struct thread_data *new, struct thread_data *old, old->mperf = 1; /* divide by 0 protection */ } + old->extra_delta32 = new->extra_delta32 - old->extra_delta32; + old->extra_delta32 &= 0xFFFFFFFF; + + old->extra_delta64 = new->extra_delta64 - old->extra_delta64; + /* - * Extra MSR is a snapshot, simply copy latest w/o subtracting + * Extra MSR is just a snapshot, simply copy latest w/o subtracting */ old->extra_msr32 = new->extra_msr32; old->extra_msr64 = new->extra_msr64; @@ -565,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data t->mperf = 0; t->c1 = 0; + t->extra_delta32 = 0; + t->extra_delta64 = 0; + /* tells format_counters to dump all fields from this set */ t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; @@ -585,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c, average.threads.mperf += t->mperf; average.threads.c1 += t->c1; + average.threads.extra_delta32 += t->extra_delta32; + average.threads.extra_delta64 += t->extra_delta64; + /* sum per-core values only for 1st thread in core */ if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) return 0; @@ -620,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c, average.threads.mperf /= topo.num_cpus; average.threads.c1 /= topo.num_cpus; + average.threads.extra_delta32 /= topo.num_cpus; + average.threads.extra_delta32 &= 0xFFFFFFFF; + + average.threads.extra_delta64 /= topo.num_cpus; + average.cores.c3 /= topo.num_cores; average.cores.c6 /= topo.num_cores; average.cores.c7 /= topo.num_cores; @@ -661,10 +678,22 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) return -4; } - if (extra_msr_offset32) - if (get_msr32(cpu, extra_msr_offset32, &t->extra_msr32)) + if (extra_delta_offset32) { + if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32)) + return -5; + t->extra_delta32 &= 0xFFFFFFFF; + } + + if (extra_delta_offset64) + if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64)) return -5; + if (extra_msr_offset32) { + if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32)) + return -5; + t->extra_msr32 &= 0xFFFFFFFF; + } + if (extra_msr_offset64) if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64)) return -5; @@ -1275,7 +1304,7 @@ void check_cpuid() void usage() { - fprintf(stderr, "%s: [-v] [-m msr#] [-M MSR#] [-i interval_sec | command ...]\n", + fprintf(stderr, "%s: [-v][-d MSR#][-D MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", progname); exit(1); } @@ -1565,7 +1594,7 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt(argc, argv, "+cpsvi:m:M:")) != -1) { + while ((opt = getopt(argc, argv, "+cpsvid:D:m:M:")) != -1) { switch (opt) { case 'c': show_core_only++; @@ -1582,15 +1611,17 @@ void cmdline(int argc, char **argv) case 'i': interval_sec = atoi(optarg); break; + case 'd': + sscanf(optarg, "%x", &extra_delta_offset32); + break; + case 'D': + sscanf(optarg, "%x", &extra_delta_offset64); + break; case 'm': sscanf(optarg, "%x", &extra_msr_offset32); - if (verbose > 1) - fprintf(stderr, "msr 0x%X\n", extra_msr_offset32); break; case 'M': sscanf(optarg, "%x", &extra_msr_offset64); - if (verbose > 1) - fprintf(stderr, "MSR 0x%X\n", extra_msr_offset64); break; default: usage(); -- cgit v1.2.2 From f9240813e61cb3e5838c9ab0237af831c61df7cf Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 6 Oct 2012 15:26:31 -0400 Subject: tools/power/turbostat: add option to count SMIs, re-name some options Counting SMIs is popular, so add a dedicated "-s" option to do it, and juggle some of the other option letters. -S is now system summary (was -s) -c is 32 bit counter (was -d) -C is 64-bit counter (was -D) -p is 1st thread in core (was -c) -P is 1st thread in package (was -p) bump the minor version number Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 12 +++++++----- tools/power/x86/turbostat/turbostat.c | 23 +++++++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 0fc7a11f300e..e4d0690cccf9 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -23,17 +23,19 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs. on processors that additionally support C-state residency counters. .SS Options -The \fB-s\fP option limits output to a 1-line system summary for each interval. +The \fB-p\fP option limits output to the 1st thread in 1st core of each package. .PP -The \fB-c\fP option limits output to the 1st thread in each core. +The \fB-P\fP option limits output to the 1st thread in each Package. .PP -The \fB-p\fP option limits output to the 1st thread in each package. +The \fB-S\fP option limits output to a 1-line System Summary for each interval. .PP The \fB-v\fP option increases verbosity. .PP -The \fB-d MSR#\fP option includes the delta of the specified 32-bit MSR counter. +The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34" .PP -The \fB-D MSR#\fP option includes the delta of the specified 64-bit MSR counter. +The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter. +.PP +The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter. .PP The \fB-m MSR#\fP option includes the the specified 32-bit MSR value. .PP diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index e38976c0b0a2..2655ae9a3ad8 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -230,9 +230,9 @@ void print_header(void) outp += sprintf(outp, " GHz"); outp += sprintf(outp, " TSC"); if (extra_delta_offset32) - outp += sprintf(outp, " delta 0x%03X", extra_delta_offset32); + outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); if (extra_delta_offset64) - outp += sprintf(outp, " DELTA 0x%03X", extra_delta_offset64); + outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64); if (extra_msr_offset32) outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); if (extra_msr_offset64) @@ -1304,7 +1304,7 @@ void check_cpuid() void usage() { - fprintf(stderr, "%s: [-v][-d MSR#][-D MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", + fprintf(stderr, "%s: [-v][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", progname); exit(1); } @@ -1594,15 +1594,15 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt(argc, argv, "+cpsvid:D:m:M:")) != -1) { + while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) { switch (opt) { - case 'c': + case 'p': show_core_only++; break; - case 'p': + case 'P': show_pkg_only++; break; - case 's': + case 'S': summary_only++; break; case 'v': @@ -1611,10 +1611,13 @@ void cmdline(int argc, char **argv) case 'i': interval_sec = atoi(optarg); break; - case 'd': + case 'c': sscanf(optarg, "%x", &extra_delta_offset32); break; - case 'D': + case 's': + extra_delta_offset32 = 0x34; /* SMI counter */ + break; + case 'C': sscanf(optarg, "%x", &extra_delta_offset64); break; case 'm': @@ -1634,7 +1637,7 @@ int main(int argc, char **argv) cmdline(argc, argv); if (verbose > 1) - fprintf(stderr, "turbostat v2.0 May 16, 2012" + fprintf(stderr, "turbostat v2.1 October 6, 2012" " - Len Brown \n"); turbostat_init(); -- cgit v1.2.2