summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-10 00:01:49 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2001-10-10 00:01:49 (GMT)
commit280c8d295fa67013b470d2c7706a3448cf853121 (patch)
treead6707d09f5ed8d41749e8131fd01a645e8767b9
downloadmsr-tools-280c8d295fa67013b470d2c7706a3448cf853121.zip
msr-tools-280c8d295fa67013b470d2c7706a3448cf853121.tar.gz
msr-tools-280c8d295fa67013b470d2c7706a3448cf853121.tar.bz2
msr-tools-280c8d295fa67013b470d2c7706a3448cf853121.tar.xz
Check in msr-tools 1.1msr-tools-1.1
-rwxr-xr-xMAKEDEV-cpuid-msr11
-rw-r--r--Makefile44
-rw-r--r--rdmsr.c307
-rw-r--r--version.h4
-rw-r--r--wrmsr.c125
5 files changed, 491 insertions, 0 deletions
diff --git a/MAKEDEV-cpuid-msr b/MAKEDEV-cpuid-msr
new file mode 100755
index 0000000..dd94138
--- /dev/null
+++ b/MAKEDEV-cpuid-msr
@@ -0,0 +1,11 @@
+#!/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
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c5adc16
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+#ident "$Id$"
+## -----------------------------------------------------------------------
+##
+## 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
+LDFLAGS =
+
+BIN = wrmsr rdmsr
+
+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 $@ $<
diff --git a/rdmsr.c b/rdmsr.c
new file mode 100644
index 0000000..6424e5c
--- /dev/null
+++ b/rdmsr.c
@@ -0,0 +1,307 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdmsr.c
+ *
+ * Utility to read an MSR.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include "version.h"
+
+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' },
+ { "processor", 1, 0, 'p' },
+ { "cpu", 1, 0, 'p' },
+ { "bitfield", 1, 0, 'f' },
+ { 0, 0, 0, 0 }
+};
+
+/* 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"
+ " --captial-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"
+ " --processor # -p Select processor number (default 0)\n"
+ " --bitfield h:l -f Output bits [h:l] only\n"
+ , program);
+}
+
+int main(int argc, char *argv[])
+{
+ uint32_t reg;
+ uint64_t data;
+ int c, fd;
+ int mode = mo_hex;
+ int cpu = 0;
+ unsigned int highbit = 63, lowbit = 0, bits;
+ unsigned long arg;
+ char *endarg;
+ char *pat;
+ int width;
+ char msr_file_name[64];
+
+ program = argv[0];
+
+ while ( (c = getopt_long(argc,argv,"hVxXdoruc0p:f:",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 '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);
+
+ 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 ( lseek(fd, reg, SEEK_SET) != reg ) {
+ perror("rdmsr:seek");
+ exit(127);
+ }
+
+ if ( read(fd, &data, sizeof data) != sizeof data ) {
+ perror("rdmsr:read");
+ 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);
+
+ exit(0);
+}
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..939ad2b
--- /dev/null
+++ b/version.h
@@ -0,0 +1,4 @@
+#ifndef MSR_TOOLS_VERSION_H
+#define MSR_TOOLS_VERSION_H
+#define VERSION_STRING "msr-tools-1.1"
+#endif
diff --git a/wrmsr.c b/wrmsr.c
new file mode 100644
index 0000000..1784b07
--- /dev/null
+++ b/wrmsr.c
@@ -0,0 +1,125 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * wrmsr.c
+ *
+ * Utility to write to an MSR.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include "version.h"
+
+struct option long_options[] = {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ { "processor", 1, 0, 'p' },
+ { "cpu", 1, 0, 'p' },
+ { 0, 0, 0, 0 }
+};
+
+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"
+ " --processor # -p Select processor number (default 0)\n"
+ , program);
+}
+
+int main(int argc, char *argv[])
+{
+ uint32_t reg;
+ uint64_t data;
+ int fd;
+ int c;
+ int cpu = 0;
+ unsigned long arg;
+ char *endarg;
+ char msr_file_name[64];
+
+ program = argv[0];
+
+ while ( (c = getopt_long(argc,argv,"hVp:",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 '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);
+
+ 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);
+ }
+ }
+
+ if ( lseek(fd, reg, SEEK_SET) != reg ) {
+ perror("wrmsr:seek");
+ exit(127);
+ }
+
+ while ( optind < argc ) {
+ data = strtouq(argv[optind++], NULL, 0);
+ if ( write(fd, &data, sizeof data) != sizeof data ) {
+ perror("wrmsr:write");
+ exit(127);
+ }
+ }
+
+ close(fd);
+
+ exit(0);
+}
+