rdmsr: fix formatting options, reorganize for readability
Unbreak the formatting options (which were broken by the --all patch),
move them all to a common structure, and reorganize the various static
functions into a more logical order. Remove dependencies on global
variables.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/rdmsr.c b/rdmsr.c
index 7062e37..3f5e2b3 100644
--- a/rdmsr.c
+++ b/rdmsr.c
@@ -53,7 +53,7 @@
/* Number of decimal digits for a certain number of bits */
/* (int) ceil(log(2^n)/log(10)) */
-int decdigits[] = {
+static const 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,
@@ -73,7 +73,7 @@
const char *program;
-void usage(void)
+static void usage(void)
{
fprintf(stderr,
"Usage: %s [options] regno\n"
@@ -92,132 +92,20 @@
" --bitfield h:l -f Output bits [h:l] only\n", program);
}
-void rdmsr_on_cpu(uint32_t reg, int cpu);
+struct format {
+ unsigned int mode;
+ unsigned int highbit;
+ unsigned int lowbit;
+};
-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;
- 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)
+static void rdmsr_on_cpu(const struct format *fmt, uint32_t reg, int cpu)
{
uint64_t data;
int fd;
- int mode = mo_hex;
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);
@@ -249,17 +137,17 @@
close(fd);
- bits = highbit - lowbit + 1;
+ bits = fmt->highbit - fmt->lowbit + 1;
if (bits < 64) {
/* Show only part of register */
- data >>= lowbit;
+ data >>= fmt->lowbit;
data &= (1ULL << bits) - 1;
}
pat = NULL;
width = 1; /* Default */
- switch (mode) {
+ switch (fmt->mode) {
case mo_hex:
pat = "%*llx\n";
break;
@@ -361,3 +249,123 @@
printf(pat, width, data);
return;
}
+
+static void rdmsr_on_all_cpus(const struct format *fmt, 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(fmt, reg, cpu);
+ }
+ fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+ uint32_t reg;
+ int c;
+ int cpu = 0;
+ unsigned long arg;
+ char *endarg;
+ struct format fmt;
+
+ fmt.mode = mo_hex;
+ fmt.highbit = 63;
+ fmt.lowbit = 0;
+
+ 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':
+ fmt.mode = (fmt.mode & ~mo_mask) | mo_hex;
+ break;
+ case 'X':
+ fmt.mode = (fmt.mode & ~mo_mask) | mo_chx;
+ break;
+ case 'o':
+ fmt.mode = (fmt.mode & ~mo_mask) | mo_oct;
+ break;
+ case 'd':
+ fmt.mode = (fmt.mode & ~mo_mask) | mo_dec;
+ break;
+ case 'r':
+ fmt.mode = (fmt.mode & ~mo_mask) | mo_raw;
+ break;
+ case 'u':
+ fmt.mode = (fmt.mode & ~mo_mask) | mo_uns;
+ break;
+ case 'c':
+ fmt.mode |= mo_c;
+ break;
+ case '0':
+ fmt.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", &fmt.highbit, &fmt.lowbit)
+ != 2 ||
+ fmt.highbit > 63 ||
+ fmt.lowbit > fmt.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(&fmt, reg);
+ else
+ rdmsr_on_cpu(&fmt, reg, cpu);
+ exit(0);
+}