1 /* SPDX-License-Identifier: GPL-2.0-only */
9 static void print_bitdef(FILE *f
, const struct msrbits
*mb
, const char *tail
) {
11 if (!reserved
&& 0 == strcmp(mb
->name
, "RSVD"))
14 fprintf(f
, "# %5d", mb
->start
);
16 endbit
= mb
->start
- mb
->size
+ 1;
17 fprintf(f
, "# %*d:%d", endbit
< 10 ? 3 : 2, mb
->start
, endbit
);
19 if (0 == strcmp(mb
->name
, "RSVD"))
20 fprintf(f
, " [%s]", mb
->desc
);
22 fprintf(f
, " %s %s", mb
->name
, mb
->desc
);
23 fprintf(f
, "%s", tail
);
26 static void print_bitval(FILE *f
, const struct msrbits
*mb
, const struct msr val
) {
28 struct msr tmp
, mask
= MSR1(1);
29 const struct msrbitvalues
*mbv
= mb
->bitval
;
30 while (mbv
->text
&& !msr_eq(mbv
->value
, val
))
32 switch (mb
->present
) {
34 mask
= msr_shl(mask
, mb
->size
- 1);
35 for (i
= 0; i
< mb
->size
; i
++) {
36 memcpy(&tmp
, &val
, sizeof(val
));
38 fprintf(f
, "%d", (tmp
.hi
|| tmp
.lo
) ? 1 : 0);
39 mask
= msr_shr(mask
, 1);
43 fprintf(f
, "%d", val
.lo
);
46 fprintf(f
, "0%o", val
.lo
);
49 hexprint(f
, val
, mb
->size
);
52 hexprint(f
, val
, mb
->size
);
53 fprintf(f
, " %d", val
.lo
);
56 strprint(f
, val
, mb
->size
);
60 fprintf(f
, ": %s", mbv
->text
);
64 void hexprint(FILE *f
, const struct msr val
, const uint8_t bits
) {
66 fprintf(f
, "0x%01x", val
.lo
& 0xf);
68 fprintf(f
, "0x%02x", val
.lo
& 0xff);
70 fprintf(f
, "0x%03x", val
.lo
& 0xfff);
72 fprintf(f
, "0x%04x", val
.lo
& 0xffff);
74 fprintf(f
, "0x%05x", val
.lo
& 0xfffff);
76 fprintf(f
, "0x%06x", val
.lo
& 0xffffff);
78 fprintf(f
, "0x%07x", val
.lo
& 0xfffffff);
80 fprintf(f
, "0x%08x", val
.lo
);
82 fprintf(f
, "0x%01x%08x", val
.hi
& 0xf, val
.lo
);
84 fprintf(f
, "0x%02x%08x", val
.hi
& 0xff, val
.lo
);
86 fprintf(f
, "0x%03x%08x", val
.hi
& 0xfff, val
.lo
);
88 fprintf(f
, "0x%04x%08x", val
.hi
& 0xffff, val
.lo
);
90 fprintf(f
, "0x%05x%08x", val
.hi
& 0xfffff, val
.lo
);
92 fprintf(f
, "0x%06x%08x", val
.hi
& 0xffffff, val
.lo
);
94 fprintf(f
, "0x%07x%08x", val
.hi
& 0xfffffff, val
.lo
);
96 fprintf(f
, "0x%08x%08x", val
.hi
, val
.lo
);
99 void strprint(FILE *f
, const struct msr val
, const uint8_t bits
) {
103 fputc(val
.hi
>> 8, f
);
105 fputc(val
.hi
>> 16, f
);
107 fputc(val
.hi
>> 24, f
);
111 fputc(val
.lo
>> 8, f
);
113 fputc(val
.lo
>> 16, f
);
115 fputc(val
.lo
>> 24, f
);
118 int msr_eq(const struct msr a
, const struct msr b
) {
119 return a
.hi
== b
.hi
&& a
.lo
== b
.lo
;
122 struct msr
msr_shl(const struct msr a
, const uint8_t bits
) {
125 ret
.hi
= bits
< 32 ? a
.hi
<< bits
: 0;
126 ret
.lo
= bits
< 32 ? a
.lo
<< bits
: 0;
129 ret
.hi
|= bits
? a
.lo
>> (32 - bits
) : 0;
131 ret
.hi
|= a
.lo
<< (bits
- 32);
136 struct msr
msr_shr(const struct msr a
, const uint8_t bits
) {
139 ret
.hi
= bits
< 32 ? a
.hi
>> bits
: 0;
140 ret
.lo
= bits
< 32 ? a
.lo
>> bits
: 0;
143 ret
.lo
|= bits
? a
.hi
<< (32 - bits
) : 0;
145 ret
.lo
|= a
.hi
>> (bits
- 32);
150 void msr_and(struct msr
*a
, const struct msr b
) {
155 const struct msrdef
*findmsrdef(const uint32_t addr
) {
157 const struct msrdef
*m
;
160 for (t
= 0; t
< targets_found
; t
++)
161 for (m
= targets
[t
]->msrs
; !MSR_ISEOT(*m
); m
++)
167 uint32_t msraddrbyname(const char *name
) {
169 const uint32_t addr
= strtoul(name
, NULL
, 16);
170 const struct msrdef
*m
;
173 for (t
= 0; t
< targets_found
; t
++)
174 for (m
= targets
[t
]->msrs
; !MSR_ISEOT(*m
); m
++) {
177 if (!strcasecmp(name
, m
->symbol
))
183 void dumpmsrdefs(const struct targetdef
*t
) {
184 const struct msrdef
*m
;
185 const struct msrbits
*mb
;
188 printf("# %s MSRs:\n", t
->name
);
189 for (m
= t
->msrs
; !MSR_ISEOT(*m
); m
++) {
192 printf("# %s\n", m
->symbol
);
193 for (mb
= m
->bits
; mb
->size
; mb
++)
194 print_bitdef(stdout
, mb
, "\n");
195 printf("0x%08x\n", m
->addr
);
199 int dumpmsrdefsvals(FILE *f
, const struct targetdef
*t
, const uint8_t cpu
) {
200 struct msr val
= MSR1(0);
201 const struct msrdef
*m
;
202 const struct msrbits
*mb
;
205 fprintf(f
, "# %s MSRs:\n", t
->name
);
206 for (m
= t
->msrs
; !MSR_ISEOT(*m
); m
++) {
209 if (!sys
->rdmsr(cpu
, m
->addr
, &val
))
211 fprintf(f
, "# %s\n", m
->symbol
);
212 for (mb
= m
->bits
; mb
->size
; mb
++)
213 print_bitdef(f
, mb
, "\n");
214 fprintf(f
, "0x%08x 0x%08x%08x\n", m
->addr
, val
.hi
, val
.lo
);
220 * Parse a hexadecimal string into an MSR value.
222 * Leading 0x or 0X is optional, the string is always parsed as hexadecimal.
223 * Any non-hexadecimal character except ' ' can separate the high 32 bits and
224 * the low 32 bits. If there is such a separator, high and low values do not
225 * need to be zero padded. If there is no separator, the last <=8 digits are
226 * the low 32 bits and any characters before them are the high 32 bits.
227 * When there is no separator and less than eight digits, the high 32 bits
229 * Parsing fails when there is a separator and it is followed by another
230 * non-hexadecimal character.
232 * @param str The string to parse. The string must be writable but will be
233 * restored before return.
234 * @param msr Pointer to the struct msr where the value will be stored.
235 * @param endptr If endptr is not NULL, *endptr will point to after the MSR.
236 * @return 1 on success, 0 on parse failure. msr is unchanged on failure.
238 uint8_t str2msr(char *str
, struct msr
*msr
, char **endptr
) {
241 if (0 == strncmp(str
, "0x", 2) || 0 == strncmp(str
, "0X", 2))
243 len
= strspn(str
, HEXCHARS
);
244 if (len
<= 8 && (0 == str
[len
] || ' ' == str
[len
])) {
247 } else if (len
<= 8) {
248 lo
= len
+ strcspn(str
+ len
, HEXCHARS
);
249 if (0 == len
&& 0 == strspn(str
+ lo
, HEXCHARS
))
253 msr
->hi
= strtoul(str
, NULL
, 16);
259 msr
->hi
= strtoul(str
, NULL
, 16);
262 msr
->lo
= strtoul(str
+ lo
, endptr
, 16);
266 void decodemsr(const uint8_t cpu
, const uint32_t addr
, const struct msr val
) {
267 struct msr bitval
, mask
;
268 const struct msrdef
*m
= findmsrdef(addr
);
269 const struct msrbits
*mb
;
272 printf("# %s ", m
->symbol
);
273 printf("0x%08x = 0x%08x%08x\n", addr
, val
.hi
, val
.lo
);
275 fprintf(stderr
, "Sorry - no definition exists for this MSR! Please add it and send a signed-off\n");
276 fprintf(stderr
, "patch to coreboot@coreboot.org. Thanks for your help!\n");
280 for (mb
= m
->bits
; mb
->size
; mb
++) {
281 if (!reserved
&& 0 == strcmp(mb
->name
, "RSVD"))
283 print_bitdef(stdout
, mb
, " = ");
284 mask
.hi
= mask
.lo
= 0xffffffff;
285 mask
= msr_shr(mask
, 64 - mb
->size
);
286 bitval
= msr_shr(val
, mb
->start
- mb
->size
+ 1);
287 msr_and(&bitval
, mask
);
288 print_bitval(stdout
, mb
, bitval
);
293 * Compare two MSR values and print any differences with field definitions and
294 * both old and new values decoded.
296 * @param f Output stream.
297 * @param addr MSR address.
298 * @param a Left value.
299 * @param b Right value.
300 * @return 1 when a and b differ, 0 when they are equal or only reserved bits
301 * differ and processing of reserved bits was not requested (with -r).
303 uint8_t diff_msr(FILE *f
, const uint32_t addr
, const struct msr a
, const struct msr b
) {
304 uint8_t ret
= 0, first
= 1;
305 struct msr aval
, bval
, mask
;
306 const struct msrdef
*m
= findmsrdef(addr
);
307 const struct msrbits
*mb
;
309 if (a
.hi
== b
.hi
&& a
.lo
== b
.lo
)
313 fprintf(stderr
, "MSR 0x%08x has no definition! Please add it and send a Signed-off-by patch\n", addr
);
314 fprintf(stderr
, "to coreboot@coreboot.org. Thank you for your help!\n");
318 for (mb
= m
->bits
; mb
->size
; mb
++) {
319 if (!reserved
&& 0 == strcmp(mb
->name
, "RSVD"))
321 mask
.hi
= mask
.lo
= 0xffffffff;
322 mask
= msr_shr(mask
, 64 - mb
->size
);
323 aval
= msr_shr(a
, mb
->start
- mb
->size
+ 1);
324 bval
= msr_shr(b
, mb
->start
- mb
->size
+ 1);
325 msr_and(&aval
, mask
);
326 msr_and(&bval
, mask
);
327 if (msr_eq(aval
, bval
))
330 fprintf(f
, "# %s\n", m
->symbol
);
331 fprintf(f
, "-0x%08x 0x%08x%08x\n", addr
, a
.hi
, a
.lo
);
332 fprintf(f
, "+0x%08x 0x%08x%08x\n", addr
, b
.hi
, b
.lo
);
336 print_bitdef(f
, mb
, "\n-");
337 print_bitval(f
, mb
, aval
);
339 print_bitval(f
, mb
, bval
);