msr-tools-1.3/0000755000000000000000000000000012225635477012027 5ustar rootrootmsr-tools-1.3/cpuid.c0000644000000000000000000001043712213504271013264 0ustar rootroot/* * Utility to read CPUIDs from x86 processors * Copyright (c) 2013, Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * */ #include #include #include #include #include #include #include #include #include struct cpuid { uint32_t eax, ebx, ecx, edx; }; static int cpuid(int cpu, uint32_t leaf, uint32_t subleaf, struct cpuid *data) { static int fd = -1; static int last_cpu; off_t offset = leaf + ((off_t) subleaf << 32); if (fd < 0 || last_cpu != cpu) { char devstr[64]; if (fd >= 0) close(fd); snprintf(devstr, sizeof devstr, "/dev/cpu/%d/cpuid", cpu); fd = open(devstr, O_RDONLY); if (fd < 0) { if (errno == ENXIO) { fprintf(stderr, "cpuid: No CPU %d\n", cpu); exit(2); } else if (errno == EIO) { fprintf(stderr, "cpuid: CPU %d doesn't support cpuid\n", cpu); exit(3); } else { perror("cpuid: open"); exit(127); } } last_cpu = cpu; } return pread(fd, data, sizeof(*data), offset) == sizeof(*data) ? 0 : -1; } static char *make_string(uint32_t val) { static char string[5] = "xxxx"; int i, ch; for (i = 0; i < 4; i++) { ch = val & 0xff; string[i] = isprint(ch) ? ch : '.'; val >>= 8; } return string; } static void print_cpuid_level(uint32_t leaf, uint32_t subleaf, struct cpuid *lvl) { printf("%08x %08x: ", leaf, subleaf); printf("%08x %s ", lvl->eax, make_string(lvl->eax)); printf("%08x %s ", lvl->ebx, make_string(lvl->ebx)); printf("%08x %s ", lvl->ecx, make_string(lvl->ecx)); printf("%08x %s\n", lvl->edx, make_string(lvl->edx)); } static void dump_cpuid_leaf(int cpu, uint32_t leaf) { struct cpuid lvl, lastlvl, lvl0; uint32_t subleaf; cpuid(cpu, leaf, 0, &lvl0); print_cpuid_level(leaf, 0, &lvl0); /* * There is no standard mechanism for enumerating the number of * subleaves, this is a heuristic... */ lastlvl = lvl0; for (subleaf = 1; subleaf != 0; subleaf++) { if (cpuid(cpu, leaf, subleaf, &lvl)) return; switch (leaf) { case 4: if ((lvl.eax & 0x1f) == 0 || !memcmp(&lvl, &lastlvl, sizeof lvl)) return; break; case 7: if (subleaf >= lvl0.eax) return; break; case 0xb: if ((lvl.ecx & ~0xff) == 0) return; case 0xd: if ((lvl.eax | lvl.ebx | lvl.ecx | lvl.edx) == 0) return; default: /* Generic, anticipatory rules */ /* Exclude ecx here for levels which return the initial ecx value */ if ((lvl.eax | lvl.ebx | lvl.ecx | lvl.edx) == 0) return; if (!memcmp(&lvl, &lvl0, sizeof lvl)) return; break; } print_cpuid_level(leaf, subleaf, &lvl); lastlvl = lvl; } } static void dump_levels(int cpu, uint32_t region) { static struct cpuid invalid_leaf; struct cpuid max; uint32_t n; if (cpuid(cpu, region, 0, &max)) return; /* * Intel processors may return the last group 0 CPUID leaf instead * all zero for a not-present level */ if (region == 0) { cpuid(cpu, max.eax + 1, 0, &invalid_leaf); } else { if (!memcmp(&max, &invalid_leaf, sizeof(struct cpuid))) return; } if ((max.eax & 0xffff0000) == region) { for (n = region; n <= max.eax; n++) { dump_cpuid_leaf(cpu, n); } } } void usage(void) { fprintf(stderr, "Usage: cpuid [processor # (default 0)]\n"); } int main(int argc, char *argv[]) { int cpu = 0; uint32_t n; char *endptr; if (argc > 2) { usage(); exit(127); } else if (argc == 2) { cpu = strtoul(argv[1], &endptr, 0); if (*endptr || cpu > 255) { usage(); exit(127); } } printf ("Leaf Subleaf EAX EBX ECX EDX \n"); for (n = 0; n <= 0xffff; n++) { dump_levels(cpu, n << 16); } return 0; } msr-tools-1.3/Makefile0000644000000000000000000000172112213504271013450 0ustar rootroot## ----------------------------------------------------------------------- ## ## Copyright 2000 Transmeta Corporation - All Rights Reserved ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, ## USA; either version 2 of the License, or (at your option) any later ## version; incorporated herein by reference. ## ## ----------------------------------------------------------------------- # # Makefile for MSRs # CC = gcc -Wall CFLAGS = -g -O2 -fomit-frame-pointer -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 LDFLAGS = BIN = wrmsr rdmsr cpuid sbindir = /usr/sbin all: $(BIN) clean: rm -f *.o $(BIN) distclean: clean rm -f *~ \#* install: all install -m 755 $(BIN) $(sbindir) .o: $(CC) $(LDFLAGS) -o $@ $< .c.o: $(CC) $(CFLAGS) -o $@ $< .c: $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< msr-tools-1.3/wrmsr.c0000644000000000000000000000725412213504271013335 0ustar rootroot/* ----------------------------------------------------------------------- * * * Copyright 2000 Transmeta Corporation - All Rights Reserved * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston MA 02110-1301, USA; either version 2 of the License, or * (at your option) any later version; incorporated herein by reference. * * ----------------------------------------------------------------------- */ /* * wrmsr.c * * Utility to write to an MSR. */ #include #include #include #include #include #include #include #include #include #include #include "version.h" static const struct option long_options[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"all", 0, 0, 'a'}, {"processor", 1, 0, 'p'}, {"cpu", 1, 0, 'p'}, {0, 0, 0, 0} }; static const char short_options[] = "hVap:"; const char *program; void usage(void) { fprintf(stderr, "Usage: %s [options] regno value...\n" " --help -h Print this help\n" " --version -V Print current version\n" " --all -a all processors\n" " --processor # -p Select processor number (default 0)\n", program); } void wrmsr_on_cpu(uint32_t reg, int cpu, int valcnt, char *regvals[]); /* filter out ".", "..", "microcode" in /dev/cpu */ int dir_filter(const struct dirent *dirp) { if (isdigit(dirp->d_name[0])) return 1; else return 0; } void wrmsr_on_all_cpus(uint32_t reg, int valcnt, char *regvals[]) { struct dirent **namelist; int dir_entries; dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0); while (dir_entries--) { wrmsr_on_cpu(reg, atoi(namelist[dir_entries]->d_name), valcnt, regvals); free(namelist[dir_entries]); } free(namelist); } int main(int argc, char *argv[]) { uint32_t reg; int c; int cpu = 0; unsigned long arg; char *endarg; program = argv[0]; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (c) { case 'h': usage(); exit(0); case 'V': fprintf(stderr, "%s: version %s\n", program, VERSION_STRING); exit(0); case 'a': cpu = -1; break; case 'p': arg = strtoul(optarg, &endarg, 0); if (*endarg || arg > 255) { usage(); exit(127); } cpu = (int)arg; break; default: usage(); exit(127); } } if (optind > argc - 2) { /* Should have at least two arguments */ usage(); exit(127); } reg = strtoul(argv[optind++], NULL, 0); if (cpu == -1) { wrmsr_on_all_cpus(reg, argc - optind, &argv[optind]); } else { wrmsr_on_cpu(reg, cpu, argc - optind, &argv[optind]); } exit(0); } void wrmsr_on_cpu(uint32_t reg, int cpu, int valcnt, char *regvals[]) { uint64_t data; int fd; char msr_file_name[64]; sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu); fd = open(msr_file_name, O_WRONLY); if (fd < 0) { if (errno == ENXIO) { fprintf(stderr, "wrmsr: No CPU %d\n", cpu); exit(2); } else if (errno == EIO) { fprintf(stderr, "wrmsr: CPU %d doesn't support MSRs\n", cpu); exit(3); } else { perror("wrmsr: open"); exit(127); } } while (valcnt--) { data = strtoull(*regvals++, NULL, 0); if (pwrite(fd, &data, sizeof data, reg) != sizeof data) { if (errno == EIO) { fprintf(stderr, "wrmsr: CPU %d cannot set MSR " "0x%08"PRIx32" to 0x%016"PRIx64"\n", cpu, reg, data); exit(4); } else { perror("wrmsr: pwrite"); exit(127); } } } close(fd); return; } msr-tools-1.3/MAKEDEV-cpuid-msr0000755000000000000000000000034712213504271014716 0ustar rootroot#!/bin/sh msr_major=202 cpuid_major=203 n=0 while [ $n -lt 32 ]; do mkdir -m 0755 -p /dev/cpu/$n mknod /dev/cpu/$n/msr -m 0600 c $msr_major $n mknod /dev/cpu/$n/cpuid -m 0444 c $cpuid_major $n n=`expr $n + 1` done msr-tools-1.3/version.h0000644000000000000000000000014612213504271013646 0ustar rootroot#ifndef MSR_TOOLS_VERSION_H #define MSR_TOOLS_VERSION_H #define VERSION_STRING "msr-tools-1.3" #endif msr-tools-1.3/rdmsr.c0000644000000000000000000001673512213504271013316 0ustar rootroot/* ----------------------------------------------------------------------- * * * Copyright 2000 Transmeta Corporation - All Rights Reserved * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston MA 02110-1301, USA; either version 2 of the License, or * (at your option) any later version; incorporated herein by reference. * * ----------------------------------------------------------------------- */ /* * rdmsr.c * * Utility to read an MSR. */ #include #include #include #include #include #include #include #include #include #include #include "version.h" static const struct option long_options[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"hexadecimal", 0, 0, 'x'}, {"capital-hexadecimal", 0, 0, 'X'}, {"decimal", 0, 0, 'd'}, {"signed-decimal", 0, 0, 'd'}, {"unsigned-decimal", 0, 0, 'u'}, {"octal", 0, 0, 'o'}, {"c-language", 0, 0, 'c'}, {"zero-fill", 0, 0, '0'}, {"zero-pad", 0, 0, '0'}, {"raw", 0, 0, 'r'}, {"all", 0, 0, 'a'}, {"processor", 1, 0, 'p'}, {"cpu", 1, 0, 'p'}, {"bitfield", 1, 0, 'f'}, {0, 0, 0, 0} }; static const char short_options[] = "hVxXdoruc0ap:f:"; /* Number of decimal digits for a certain number of bits */ /* (int) ceil(log(2^n)/log(10)) */ int decdigits[] = { 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20 }; #define mo_hex 0x01 #define mo_dec 0x02 #define mo_oct 0x03 #define mo_raw 0x04 #define mo_uns 0x05 #define mo_chx 0x06 #define mo_mask 0x0f #define mo_fill 0x40 #define mo_c 0x80 const char *program; void usage(void) { fprintf(stderr, "Usage: %s [options] regno\n" " --help -h Print this help\n" " --version -V Print current version\n" " --hexadecimal -x Hexadecimal output (lower case)\n" " --capital-hex -X Hexadecimal output (upper case)\n" " --decimal -d Signed decimal output\n" " --unsigned -u Unsigned decimal output\n" " --octal -o Octal output\n" " --c-language -c Format output as a C language constant\n" " --zero-pad -0 Output leading zeroes\n" " --raw -r Raw binary output\n" " --all -a all processors\n" " --processor # -p Select processor number (default 0)\n" " --bitfield h:l -f Output bits [h:l] only\n", program); } void rdmsr_on_cpu(uint32_t reg, int cpu); /* filter out ".", "..", "microcode" in /dev/cpu */ int dir_filter(const struct dirent *dirp) { if (isdigit(dirp->d_name[0])) return 1; else return 0; } void rdmsr_on_all_cpus(uint32_t reg) { struct dirent **namelist; int dir_entries; dir_entries = scandir("/dev/cpu", &namelist, dir_filter, 0); while (dir_entries--) { rdmsr_on_cpu(reg, atoi(namelist[dir_entries]->d_name)); free(namelist[dir_entries]); } free(namelist); } unsigned int highbit = 63, lowbit = 0; int mode = mo_hex; int main(int argc, char *argv[]) { uint32_t reg; int c; int cpu = 0; unsigned long arg; char *endarg; program = argv[0]; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (c) { case 'h': usage(); exit(0); case 'V': fprintf(stderr, "%s: version %s\n", program, VERSION_STRING); exit(0); case 'x': mode = (mode & ~mo_mask) | mo_hex; break; case 'X': mode = (mode & ~mo_mask) | mo_chx; break; case 'o': mode = (mode & ~mo_mask) | mo_oct; break; case 'd': mode = (mode & ~mo_mask) | mo_dec; break; case 'r': mode = (mode & ~mo_mask) | mo_raw; break; case 'u': mode = (mode & ~mo_mask) | mo_uns; break; case 'c': mode |= mo_c; break; case '0': mode |= mo_fill; break; case 'a': cpu = -1; break; case 'p': arg = strtoul(optarg, &endarg, 0); if (*endarg || arg > 255) { usage(); exit(127); } cpu = (int)arg; break; case 'f': if (sscanf(optarg, "%u:%u", &highbit, &lowbit) != 2 || highbit > 63 || lowbit > highbit) { usage(); exit(127); } break; default: usage(); exit(127); } } if (optind != argc - 1) { /* Should have exactly one argument */ usage(); exit(127); } reg = strtoul(argv[optind], NULL, 0); if (cpu == -1) { rdmsr_on_all_cpus(reg); } else rdmsr_on_cpu(reg, cpu); exit(0); } void rdmsr_on_cpu(uint32_t reg, int cpu) { uint64_t data; int fd; char *pat; int width; char msr_file_name[64]; unsigned int bits; sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu); fd = open(msr_file_name, O_RDONLY); if (fd < 0) { if (errno == ENXIO) { fprintf(stderr, "rdmsr: No CPU %d\n", cpu); exit(2); } else if (errno == EIO) { fprintf(stderr, "rdmsr: CPU %d doesn't support MSRs\n", cpu); exit(3); } else { perror("rdmsr: open"); exit(127); } } if (pread(fd, &data, sizeof data, reg) != sizeof data) { if (errno == EIO) { fprintf(stderr, "rdmsr: CPU %d cannot read " "MSR 0x%08"PRIx32"\n", cpu, reg); exit(4); } else { perror("rdmsr: pread"); exit(127); } } close(fd); bits = highbit - lowbit + 1; if (bits < 64) { /* Show only part of register */ data >>= lowbit; data &= (1ULL << bits) - 1; } pat = NULL; width = 1; /* Default */ switch (mode) { case mo_hex: pat = "%*llx\n"; break; case mo_chx: pat = "%*llX\n"; break; case mo_dec: case mo_dec | mo_c: case mo_dec | mo_fill | mo_c: /* Make sure we get sign correct */ if (data & (1ULL << (bits - 1))) { data &= ~(1ULL << (bits - 1)); data = -data; } pat = "%*lld\n"; break; case mo_uns: pat = "%*llu\n"; break; case mo_oct: pat = "%*llo\n"; break; case mo_hex | mo_c: pat = "0x%*llx\n"; break; case mo_chx | mo_c: pat = "0x%*llX\n"; break; case mo_oct | mo_c: pat = "0%*llo\n"; break; case mo_uns | mo_c: case mo_uns | mo_fill | mo_c: pat = "%*lluU\n"; break; case mo_hex | mo_fill: pat = "%0*llx\n"; width = (bits + 3) / 4; break; case mo_chx | mo_fill: pat = "%0*llX\n"; width = (bits + 3) / 4; break; case mo_dec | mo_fill: /* Make sure we get sign correct */ if (data & (1ULL << (bits - 1))) { data &= ~(1ULL << (bits - 1)); data = -data; } pat = "%0*lld\n"; width = decdigits[bits - 1] + 1; break; case mo_uns | mo_fill: pat = "%0*llu\n"; width = decdigits[bits]; break; case mo_oct | mo_fill: pat = "%0*llo\n"; width = (bits + 2) / 3; break; case mo_hex | mo_fill | mo_c: pat = "0x%0*llx\n"; width = (bits + 3) / 4; break; case mo_chx | mo_fill | mo_c: pat = "0x%0*llX\n"; width = (bits + 3) / 4; break; case mo_oct | mo_fill | mo_c: pat = "0%0*llo\n"; width = (bits + 2) / 3; break; case mo_raw: case mo_raw | mo_fill: fwrite(&data, sizeof data, 1, stdout); break; case mo_raw | mo_c: case mo_raw | mo_fill | mo_c: { unsigned char *p = (unsigned char *)&data; int i; for (i = 0; i < sizeof data; i++) { printf("%s0x%02x", i ? "," : "{", (unsigned int)(*p++)); } printf("}\n"); } break; default: fprintf(stderr, "%s: Impossible case, line %d\n", program, __LINE__); exit(127); } if (width < 1) width = 1; if (pat) printf(pat, width, data); return; }