[PATCH msr-tools] rdmsr, wrmsr: add '-a' parameter to operate on allprocessors

From: Len Brown
Date: Thu Aug 05 2010 - 00:44:57 EST


From: Len Brown <len.brown@xxxxxxxxx>

Now that even a laptop has multiple processors...
it is handy to have the option to simultaneously
read or write an MSR on all the processors
in the system.

We get the list of on-line processors from /proc/stat

Signed-off-by: Len Brown <len.brown@xxxxxxxxx>
---
rdmsr.c | 70 ++++++++++++++++++++++++++++++++++------
wrmsr.c | 111 +++++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 137 insertions(+), 44 deletions(-)

diff --git a/rdmsr.c b/rdmsr.c
index 5f173d7..f4be761 100644
--- a/rdmsr.c
+++ b/rdmsr.c
@@ -41,12 +41,15 @@ static const struct option long_options[] = {
{"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[] = "hVxXdoruc0p:f:";
+static const char short_options[] = "hVxXdoruc0ap:f:";
+
+static const char *proc_stat = "/proc/stat";

/* Number of decimal digits for a certain number of bits */
/* (int) ceil(log(2^n)/log(10)) */
@@ -84,23 +87,53 @@ void usage(void)
" --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);
+
+void rdmsr_on_all_cpus(uint32_t reg)
+{
+ FILE *fp;
+ int retval;
+
+ fp = fopen(proc_stat, "r");
+ if (fp == NULL) {
+ perror(proc_stat);
+ exit(-1);
+ }
+
+ retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
+ if (retval != 0) {
+ perror("/proc/stat format");
+ exit(-1);
+ }
+
+ for (;;) {
+ int cpu;
+
+ retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d"
+ " %*d\n", &cpu);
+ if (retval != 1)
+ return;
+
+ rdmsr_on_cpu(reg, cpu);
+ }
+ fclose(fp);
+}
+
+unsigned int highbit = 63, lowbit = 0, bits;
+int mode = mo_hex;
+
int main(int argc, char *argv[])
{
uint32_t reg;
- uint64_t data;
- int c, fd;
- int mode = mo_hex;
+ int c;
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];

@@ -139,6 +172,9 @@ int main(int argc, char *argv[])
case '0':
mode |= mo_fill;
break;
+ case 'a':
+ cpu = -1;
+ break;
case 'p':
arg = strtoul(optarg, &endarg, 0);
if (*endarg || arg > 255) {
@@ -168,6 +204,21 @@ int main(int argc, char *argv[])

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;
+ int mode = mo_hex;
+ char *pat;
+ int width;
+ char msr_file_name[64];
+
sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
fd = open(msr_file_name, O_RDONLY);
if (fd < 0) {
@@ -308,6 +359,5 @@ int main(int argc, char *argv[])

if (pat)
printf(pat, width, data);
-
- exit(0);
+ return;
}
diff --git a/wrmsr.c b/wrmsr.c
index ab87921..a1a5eb6 100644
--- a/wrmsr.c
+++ b/wrmsr.c
@@ -31,12 +31,14 @@
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[] = "hVp:";
+static const char short_options[] = "hVap:";

+static const char *proc_stat = "/proc/stat";
const char *program;

void usage(void)
@@ -44,20 +46,85 @@ 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, uint64_t data, int cpu)
+{
+ 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);
+ }
+ }
+ 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);
+}
+
+
+void wrmsr_on_all_cpus(uint32_t reg, uint64_t data)
+{
+ FILE *fp;
+ int retval;
+
+ fp = fopen(proc_stat, "r");
+ if (fp == NULL) {
+ perror(proc_stat);
+ exit(-1);
+ }
+
+ retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
+ if (retval != 0) {
+ perror("/proc/stat format");
+ exit(-1);
+ }
+
+ for (;;) {
+ int cpu;
+
+ retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d "
+ "%*d %*d\n", &cpu);
+ if (retval != 1)
+ return;
+
+ wrmsr_on_cpu(reg, data, cpu);
+ }
+ fclose(fp);
+}
+
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];

@@ -71,6 +138,9 @@ int main(int argc, char *argv[])
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) {
@@ -93,39 +163,12 @@ int main(int argc, char *argv[])

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);
- }
- }
-
while (optind < argc) {
data = strtoull(argv[optind++], 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);
- }
- }
+ if (cpu == -1)
+ wrmsr_on_all_cpus(reg, data);
+ else
+ wrmsr_on_cpu(reg, data, cpu);
}
-
- close(fd);
-
exit(0);
}
--
1.7.2.1.6.g61bf12

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/