1 /* SPDX-License-Identifier: GPL-2.0-only */
16 static uint8_t cpu
= DEFAULT_CPU
;
18 uint8_t targets_found
= 0;
19 const struct targetdef
**targets
= NULL
;
20 const struct sysdef
*sys
= NULL
;
21 uint8_t reserved
= 0, verbose
= 0, quiet
= 0;
23 struct pci_access
*pacc
= NULL
;
25 static struct targetdef alltargets
[] = {
26 { "geodegx2", "AMD Geode(tm) GX2", geodegx2_probe
, geodegx2_msrs
},
27 { "geodelx", "AMD Geode(tm) LX", geodelx_probe
, geodelx_msrs
},
28 { "cs5536", "AMD Geode(tm) CS5536", cs5536_probe
, cs5536_msrs
},
29 { "K8", "AMD K8 Family", k8_probe
, k8_msrs
},
30 { "via_c7", "VIA Esther processor, C7", via_c7_probe
, via_c7_msrs
},
31 { "intel_pentium3_early", "Intel Pentium III family", intel_pentium3_early_probe
, intel_pentium3_early_msrs
},
32 { "intel_pentium3", "Intel Pentium III Xeon Processor, Intel Pentium III Processor", intel_pentium3_probe
, intel_pentium3_msrs
},
33 { "intel_core1", "Intel Core Duo, Intel Core Solo processors", intel_core1_probe
, intel_core1_msrs
},
34 { "intel_core2_early", "Intel Xeon Processor 3000, 3200, 5100, 5300, 7300 series, Intel Core 2 Quad processor 6000 series, Intel Core 2 Extreme 6000 series, Intel Core 2 Duo 4000, 5000, 6000, 7000 series processors, Intel Pentium dual-core processors", intel_core2_early_probe
, intel_core2_early_msrs
},
35 { "intel_core2_later", "Intel Xeon Processor 5200, 5400 series, Intel Core 2 Quad processors 8000, 9000 series", intel_core2_later_probe
, intel_core2_later_msrs
},
36 { "intel_pentium4_early", "Intel Xeon Processor, Intel Xeon Processor MP, Intel Pentium 4 processors", intel_pentium4_early_probe
, intel_pentium4_early_msrs
},
37 { "intel_pentium4_later", "Intel Xeon Processor, Intel Xeon Processor MP, Intel Pentium 4, Pentium D processors", intel_pentium4_later_probe
, intel_pentium4_later_msrs
},
38 { "intel_pentium_d", "Intel Pentium D processors", intel_pentium_d_probe
, intel_pentium_d_msrs
},
39 { "intel_nehalem", "Intel Core i5, i7 Processors, Intel Xeon Processor 3400, 3500, 5500, based on Nehalem architecture", intel_nehalem_probe
, intel_nehalem_msrs
},
40 { "intel_atom", "Intel Atom Processors, N450", intel_atom_probe
, intel_atom_msrs
},
44 static struct sysdef allsystems
[] = {
45 { "linux", "Linux with /dev/cpu/*/msr", linux_probe
, linux_open
, linux_close
, linux_rdmsr
},
46 { "darwin", "Mac OS X with DirectHW", darwin_probe
, darwin_open
, darwin_close
, darwin_rdmsr
},
47 { "freebsd", "FreeBSD with /dev/cpuctl*", freebsd_probe
, freebsd_open
, freebsd_close
, freebsd_rdmsr
},
51 static void syntax(char *argv
[]) {
52 printf("syntax: %s [-hvqrkl] [-c cpu] [-m system] [-t target ...]\n", argv
[0]);
53 printf("\t [-i addr=hi[:]lo] | [-s file] | [-d [:]file] | addr...\n");
54 printf(" -h\t show this help text\n");
55 printf(" -v\t be verbose\n");
56 printf(" -q\t be quiet (overrides -v)\n");
57 printf(" -r\t include [Reserved] values\n");
58 printf(" -k\t list all known systems and targets\n");
59 printf(" -l\t list MSRs and bit fields for current target(s) (-kl for ALL targets!)\n");
60 printf(" -c\t access MSRs on the specified CPU, default=%d\n", DEFAULT_CPU
);
61 printf(" -m\t force a system, e.g: -m linux\n");
62 printf(" -t\t force a target, can be used multiple times, e.g: -t geodelx -t cs5536\n");
63 printf(" -i\t immediate mode\n");
64 printf("\t decode hex addr=hi:lo for the target without reading hw value\n");
65 printf("\t e.g: -i 4c00000f=f2f100ff56960004\n");
66 printf(" -s\t stream mode\n");
67 printf("\t read one MSR address per line and append current hw value to the line\n");
68 printf("\t use the filename - for stdin/stdout\n");
69 printf("\t using -l -s ignores input and will output all MSRs with values\n");
70 printf(" -d\t diff mode\n");
71 printf("\t read one address and value per line and compare with current hw value,\n");
72 printf("\t printing differences to stdout. use the filename - to read from stdin\n");
73 printf("\t use :file or :- to reverse diff, normally hw values are considered new\n");
74 printf(" addr.. direct mode, read and decode values for the given MSR address(es)\n");
77 static void *add_target(const struct targetdef
*t
) {
79 tmp
= realloc(targets
, (targets_found
+ 2) * sizeof(struct targetdef
*));
85 targets
[targets_found
++] = t
;
86 targets
[targets_found
] = NULL
;
90 static int found_system(void) {
91 if (!sys
|| (sys
&& !sys
->name
)) {
92 fprintf(stderr
, "Unable to detect the current operating system!\n");
93 fprintf(stderr
, "On Linux, please run 'modprobe msr' and try again.\n");
94 fprintf(stderr
, "Please send a report or patch to coreboot@coreboot.org. Thanks for your help!\n");
95 fprintf(stderr
, "\n");
97 return (sys
&& sys
->name
);
100 int do_stream(const char *streamfn
, uint8_t ignoreinput
) {
101 char tmpfn
[20], line
[256];
106 FILE *fin
= NULL
, *fout
= NULL
;
107 uint32_t addr
, linenum
;
108 struct msr m
= MSR1(0);
110 if (0 == strcmp(streamfn
, "-")) {
115 if (NULL
== (fin
= fopen(streamfn
, "r"))) {
119 if (snprintf(tmpfn
, sizeof(tmpfn
), "msrtoolXXXXXX") >= sizeof(tmpfn
)) {
123 if (-1 == (fdout
= mkstemp(tmpfn
))) {
127 if (NULL
== (fout
= fdopen(fdout
, "w"))) {
132 if (NULL
== (fout
= fopen(streamfn
, "w"))) {
141 if (!sys
->open(cpu
, SYS_RDONLY
))
144 for (tn
= 0; tn
< targets_found
; tn
++)
145 if (dumpmsrdefsvals(fout
, targets
[tn
], cpu
)) {
150 for (linenum
= 1; NULL
!= fgets(line
, sizeof(line
), fin
); ++linenum
) {
151 start
= (0 == strncmp("0x", line
, 2)) ? 2 : 0;
152 if (1 == sscanf(line
+ start
, "%8x", &addr
)) {
153 if (!sys
->rdmsr(cpu
, addr
, &m
))
155 fprintf(fout
, "0x%08x 0x%08x%08x\n", addr
, m
.hi
, m
.lo
);
159 fprintf(fout
, "%s", line
);
161 if (NULL
!= strchr("\r\n", line
[len
- 1]))
163 if (NULL
== fgets(line
, sizeof(line
), fin
))
169 fprintf(stderr
, "%s:%d: fgets: %s\n", streamfn
, linenum
, strerror(errno
));
176 if (strcmp(streamfn
, "-")) {
179 else if (!ignoreinput
)
180 rename(tmpfn
, streamfn
);
188 int do_diff(const char *difffn
) {
189 char tmpfn
[20], line
[512], *m1start
, *m2start
;
191 int ret
= 1, tmp
, m1pos
, sys_opened
= 0;
192 FILE *fin
= NULL
, *fout
= stdout
;
194 uint32_t addr
, linenum
;
195 struct msr m1
= MSR1(0), m2
= MSR1(0);
197 if (':' == difffn
[0]) {
201 if (0 == strcmp(difffn
, "-"))
203 else if (NULL
== (fin
= fopen(difffn
, "r"))) {
208 for (linenum
= 1; NULL
!= fgets(line
, sizeof(line
), fin
); ++linenum
) {
209 tmp
= strncmp("0x", line
, 2) ? 0 : 2;
210 if (sscanf(line
+ tmp
, "%8x %n%*x", &addr
, &m1pos
) < 1)
212 m1start
= line
+ tmp
+ m1pos
;
213 for (len
= strlen(m1start
) - 1; NULL
!= strchr("\r\n", m1start
[len
]); --len
)
215 if (!str2msr(m1start
, &m1
, &m2start
)) {
216 fprintf(stderr
, "%s:%d: invalid MSR1 value '%s'\n", difffn
, linenum
, m1start
);
219 while (' ' == *m2start
)
221 if (!str2msr(m2start
, &m2
, NULL
)) {
222 fprintf(stderr
, "%s:%d: invalid MSR2 value '%s' - reading from hardware!\n", difffn
, linenum
, m2start
);
226 sys_opened
= sys
->open(cpu
, SYS_RDONLY
);
230 if (!sys
->rdmsr(cpu
, addr
, &m2
))
233 if (diff_msr(fout
, addr
, rev
? m2
: m1
, rev
? m1
: m2
))
237 fprintf(stderr
, "%s:%d: fgets: %s\n", difffn
, linenum
, strerror(errno
));
243 if (strcmp(difffn
, "-")) {
247 rename(tmpfn
, difffn
);
254 int main(int argc
, char *argv
[]) {
257 const struct sysdef
*s
;
258 const struct targetdef
*t
;
259 uint8_t tn
, listmsrs
= 0, listknown
= 0, input
= 0;
261 const char *streamfn
= NULL
, *difffn
= NULL
;
262 struct msr msrval
= MSR2(-1, -1);
263 while ((c
= getopt(argc
, argv
, "hqvrklc:m:t:a:i:s:d:")) != -1)
287 for (s
= allsystems
; !SYSTEM_ISEOT(*s
); s
++)
288 if (!strcmp(s
->name
, optarg
)) {
294 for (t
= alltargets
; !TARGET_ISEOT(*t
); t
++)
295 if (!strcmp(t
->name
, optarg
)) {
302 addr
= msraddrbyname(optarg
);
303 optarg
= strchr(optarg
, '=');
304 if (NULL
== optarg
) {
305 fprintf(stderr
, "missing value in -i argument!\n");
308 if (!str2msr(++optarg
, &msrval
, NULL
))
309 fprintf(stderr
, "invalid value in -i argument!\n");
321 /** cpuid is called after reading argv so that verbose is set */
322 const struct cpuid_t
*id
= cpuid();
324 printf_quiet("msrtool %s\n", VERSION
);
328 fprintf(stderr
, "Could not initialize PCI library! pci_alloc() failed.\n");
334 if (!sys
&& !input
&& !listknown
)
335 for (sys
= allsystems
; !SYSTEM_ISEOT(*sys
); sys
++) {
336 printf_verbose("Probing for system %s: %s\n", sys
->name
, sys
->prettyname
);
337 if (!sys
->probe(sys
))
339 printf_quiet("Detected system %s: %s\n", sys
->name
, sys
->prettyname
);
344 for (tn
= 0; tn
< targets_found
; tn
++)
345 printf_quiet("Forced target %s: %s\n", targets
[tn
]->name
, targets
[tn
]->prettyname
);
347 for (t
= alltargets
; !TARGET_ISEOT(*t
); t
++) {
348 printf_verbose("Probing for target %s: %s\n", t
->name
, t
->prettyname
);
349 if (!t
->probe(t
, id
))
351 printf_quiet("Detected target %s: %s\n", t
->name
, t
->prettyname
);
359 printf("Known systems:\n");
360 for (s
= allsystems
; s
->name
; s
++)
361 printf("%s: %s\n", s
->name
, s
->prettyname
);
362 printf("\nKnown targets:\n");
363 for (t
= alltargets
; t
->name
; t
++) {
364 if (listmsrs
&& alltargets
!= t
)
366 printf("%s: %s\n", t
->name
, t
->prettyname
);
374 if (!targets_found
|| !targets
) {
375 fprintf(stderr
, "Unable to detect a known target; can not decode any MSRs! (Use -t to force)\n");
376 fprintf(stderr
, "Please send a report or patch to coreboot@coreboot.org. Thanks for your help!\n");
377 fprintf(stderr
, "\n");
382 decodemsr(cpu
, addr
, msrval
);
388 return do_stream(streamfn
, 1);
389 for (tn
= 0; tn
< targets_found
; tn
++) {
392 dumpmsrdefs(targets
[tn
]);
399 return do_stream(streamfn
, 0);
402 ret
= do_diff(difffn
);
406 if (optind
== argc
) {
408 printf("\nNo mode or address(es) specified!\n");
414 if (!sys
->open(cpu
, SYS_RDONLY
))
417 for (; optind
< argc
; optind
++) {
418 addr
= msraddrbyname(argv
[optind
]);
419 if (!sys
->rdmsr(cpu
, addr
, &msrval
))
421 decodemsr(cpu
, addr
, msrval
);