blob: 1c6707e4c2d30df7cd28950323f12cc70ce72afc [file] [log] [blame]
Peter Stugedad1e302008-11-22 17:13:36 +00001/*
2 * This file is part of msrtool.
3 *
4 * Copyright (c) 2008 Peter Stuge <peter@stuge.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Peter Stugedad1e302008-11-22 17:13:36 +000014 */
15
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19
20#include "msrtool.h"
21
22static void print_bitdef(FILE *f, const struct msrbits *mb, const char *tail) {
23 uint8_t endbit;
Peter Stugecc9db9d2008-11-22 18:29:44 +000024 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
Peter Stugedad1e302008-11-22 17:13:36 +000025 return;
26 if (1 == mb->size)
27 fprintf(f, "# %5d", mb->start);
28 else {
29 endbit = mb->start - mb->size + 1;
30 fprintf(f, "# %*d:%d", endbit < 10 ? 3 : 2, mb->start, endbit);
31 }
Peter Stugecc9db9d2008-11-22 18:29:44 +000032 if (0 == strcmp(mb->name, "RSVD"))
Peter Stugedad1e302008-11-22 17:13:36 +000033 fprintf(f, " [%s]", mb->desc);
34 else
35 fprintf(f, " %s %s", mb->name, mb->desc);
36 fprintf(f, "%s", tail);
37}
38
39static void print_bitval(FILE *f, const struct msrbits *mb, const struct msr val) {
40 uint8_t i;
41 struct msr tmp, mask = MSR1(1);
42 const struct msrbitvalues *mbv = mb->bitval;
43 while (mbv->text && !msr_eq(mbv->value, val))
44 mbv++;
45 switch (mb->present) {
46 case PRESENT_BIN:
47 mask = msr_shl(mask, mb->size - 1);
48 for (i = 0; i < mb->size; i++) {
49 memcpy(&tmp, &val, sizeof(val));
50 msr_and(&tmp, mask);
51 fprintf(f, "%d", (tmp.hi || tmp.lo) ? 1 : 0);
52 mask = msr_shr(mask, 1);
53 }
Peter Stugedad1e302008-11-22 17:13:36 +000054 break;
55 case PRESENT_DEC:
56 fprintf(f, "%d", val.lo);
57 break;
58 case PRESENT_OCT:
59 fprintf(f, "0%o", val.lo);
60 break;
61 case PRESENT_HEX:
62 hexprint(f, val, mb->size);
63 break;
64 case PRESENT_HEXDEC:
65 hexprint(f, val, mb->size);
66 fprintf(f, " %d", val.lo);
67 break;
Lubomir Rintel38686f12017-01-22 22:19:33 +010068 case PRESENT_STR:
69 strprint(f, val, mb->size);
70 break;
Peter Stugedad1e302008-11-22 17:13:36 +000071 }
72 if (mbv->text)
73 fprintf(f, ": %s", mbv->text);
74 fprintf(f, "\n");
75}
76
77void hexprint(FILE *f, const struct msr val, const uint8_t bits) {
78 if (bits <= 4)
Peter Stugeb1180b42010-05-17 07:40:20 +000079 fprintf(f, "0x%01x", val.lo & 0xf);
Peter Stugedad1e302008-11-22 17:13:36 +000080 else if (bits <= 8)
Peter Stuge87964862010-05-17 07:29:47 +000081 fprintf(f, "0x%02x", val.lo & 0xff);
Peter Stugeb1180b42010-05-17 07:40:20 +000082 else if (bits <= 12)
83 fprintf(f, "0x%03x", val.lo & 0xfff);
Peter Stugedad1e302008-11-22 17:13:36 +000084 else if (bits <= 16)
Peter Stuge87964862010-05-17 07:29:47 +000085 fprintf(f, "0x%04x", val.lo & 0xffff);
Peter Stugeb1180b42010-05-17 07:40:20 +000086 else if (bits <= 20)
87 fprintf(f, "0x%05x", val.lo & 0xfffff);
88 else if (bits <= 24)
89 fprintf(f, "0x%06x", val.lo & 0xffffff);
90 else if (bits <= 28)
91 fprintf(f, "0x%07x", val.lo & 0xfffffff);
Peter Stugedad1e302008-11-22 17:13:36 +000092 else if (bits <= 32)
93 fprintf(f, "0x%08x", val.lo);
Peter Stugeb1180b42010-05-17 07:40:20 +000094 else if (bits <= 36)
95 fprintf(f, "0x%01x%08x", val.hi & 0xf, val.lo);
96 else if (bits <= 40)
97 fprintf(f, "0x%02x%08x", val.hi & 0xff, val.lo);
98 else if (bits <= 44)
99 fprintf(f, "0x%03x%08x", val.hi & 0xfff, val.lo);
100 else if (bits <= 48)
101 fprintf(f, "0x%04x%08x", val.hi & 0xffff, val.lo);
102 else if (bits <= 52)
103 fprintf(f, "0x%05x%08x", val.hi & 0xfffff, val.lo);
104 else if (bits <= 56)
105 fprintf(f, "0x%06x%08x", val.hi & 0xffffff, val.lo);
106 else if (bits <= 60)
107 fprintf(f, "0x%07x%08x", val.hi & 0xfffffff, val.lo);
Peter Stugedad1e302008-11-22 17:13:36 +0000108 else
109 fprintf(f, "0x%08x%08x", val.hi, val.lo);
110}
111
Lubomir Rintel38686f12017-01-22 22:19:33 +0100112void strprint(FILE *f, const struct msr val, const uint8_t bits) {
113 if (bits > 56)
114 fputc(val.hi, f);
115 if (bits > 48)
116 fputc(val.hi >> 8, f);
117 if (bits > 40)
118 fputc(val.hi >> 16, f);
119 if (bits > 32)
120 fputc(val.hi >> 24, f);
121 if (bits > 24)
122 fputc(val.lo, f);
123 if (bits > 16)
124 fputc(val.lo >> 8, f);
125 if (bits > 8)
126 fputc(val.lo >> 16, f);
127 if (bits > 0)
128 fputc(val.lo >> 24, f);
129}
130
Peter Stugedad1e302008-11-22 17:13:36 +0000131int msr_eq(const struct msr a, const struct msr b) {
132 return a.hi == b.hi && a.lo == b.lo;
133}
134
135struct msr msr_shl(const struct msr a, const uint8_t bits) {
136 struct msr ret;
137
138 ret.hi = bits < 32 ? a.hi << bits : 0;
139 ret.lo = bits < 32 ? a.lo << bits : 0;
140
141 if (bits < 32)
142 ret.hi |= bits ? a.lo >> (32 - bits) : 0;
143 else
144 ret.hi |= a.lo << (bits - 32);
145
146 return ret;
147}
148
149struct msr msr_shr(const struct msr a, const uint8_t bits) {
150 struct msr ret;
151
152 ret.hi = bits < 32 ? a.hi >> bits : 0;
153 ret.lo = bits < 32 ? a.lo >> bits : 0;
154
155 if (bits < 32)
156 ret.lo |= bits ? a.hi << (32 - bits) : 0;
157 else
158 ret.lo |= a.hi >> (bits - 32);
159
160 return ret;
161}
162
163void msr_and(struct msr *a, const struct msr b) {
164 a->hi &= b.hi;
165 a->lo &= b.lo;
166}
167
168const struct msrdef *findmsrdef(const uint32_t addr) {
169 uint8_t t;
170 const struct msrdef *m;
171 if (!targets)
172 return NULL;
173 for (t = 0; t < targets_found; t++)
174 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++)
175 if (addr == m->addr)
176 return m;
177 return NULL;
178}
179
Marc Jones8f210762009-03-08 04:37:39 +0000180uint32_t msraddrbyname(const char *name) {
Peter Stuge3108a122009-01-26 17:18:31 +0000181 uint8_t t;
182 const uint32_t addr = strtoul(name, NULL, 16);
183 const struct msrdef *m;
184 if (!targets)
Peter Stuge5f28c092009-03-23 17:43:12 +0000185 return addr;
Peter Stuge3108a122009-01-26 17:18:31 +0000186 for (t = 0; t < targets_found; t++)
187 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++) {
188 if (addr == m->addr)
189 return m->addr;
190 if (!strcasecmp(name, m->symbol))
191 return m->addr;
192 }
Peter Stuge5f28c092009-03-23 17:43:12 +0000193 return addr;
Peter Stuge3108a122009-01-26 17:18:31 +0000194}
195
Peter Stugedad1e302008-11-22 17:13:36 +0000196void dumpmsrdefs(const struct targetdef *t) {
197 const struct msrdef *m;
198 const struct msrbits *mb;
Peter Stugecc9db9d2008-11-22 18:29:44 +0000199 if (NULL == t)
Peter Stugedad1e302008-11-22 17:13:36 +0000200 return;
201 printf("# %s MSRs:\n", t->name);
202 for (m = t->msrs; !MSR_ISEOT(*m); m++) {
203 if (t->msrs != m)
204 printf("\n");
205 printf("# %s\n", m->symbol);
206 for (mb = m->bits; mb->size; mb++)
207 print_bitdef(stdout, mb, "\n");
208 printf("0x%08x\n", m->addr);
209 }
210}
211
212int dumpmsrdefsvals(FILE *f, const struct targetdef *t, const uint8_t cpu) {
213 struct msr val = MSR1(0);
214 const struct msrdef *m;
215 const struct msrbits *mb;
Peter Stugecc9db9d2008-11-22 18:29:44 +0000216 if (NULL == t)
Peter Stugedad1e302008-11-22 17:13:36 +0000217 return 1;
218 fprintf(f, "# %s MSRs:\n", t->name);
219 for (m = t->msrs; !MSR_ISEOT(*m); m++) {
220 if (t->msrs != m)
221 fprintf(f, "\n");
222 if (!sys->rdmsr(cpu, m->addr, &val))
223 return 1;
224 fprintf(f, "# %s\n", m->symbol);
225 for (mb = m->bits; mb->size; mb++)
226 print_bitdef(f, mb, "\n");
227 fprintf(f, "0x%08x 0x%08x%08x\n", m->addr, val.hi, val.lo);
228 }
229 return 0;
230}
231
232/**
233 * Parse a hexadecimal string into an MSR value.
Uwe Hermann708ccac2009-04-10 21:05:56 +0000234 *
Peter Stugedad1e302008-11-22 17:13:36 +0000235 * Leading 0x or 0X is optional, the string is always parsed as hexadecimal.
Peter Stuge34f29072010-01-17 18:33:53 +0000236 * Any non-hexadecimal character except ' ' can separate the high 32 bits and
Peter Stugedad1e302008-11-22 17:13:36 +0000237 * the low 32 bits. If there is such a separator, high and low values do not
238 * need to be zero padded. If there is no separator, the last <=8 digits are
239 * the low 32 bits and any characters before them are the high 32 bits.
240 * When there is no separator and less than eight digits, the high 32 bits
241 * are set to 0.
242 * Parsing fails when there is a separator and it is followed by another
243 * non-hexadecimal character.
244 *
245 * @param str The string to parse. The string must be writable but will be
246 * restored before return.
247 * @param msr Pointer to the struct msr where the value will be stored.
Paul Menzel85bb83a2010-01-17 21:59:27 +0000248 * @param endptr If endptr is not NULL, *endptr will point to after the MSR.
Peter Stugedad1e302008-11-22 17:13:36 +0000249 * @return 1 on success, 0 on parse failure. msr is unchanged on failure.
250 */
Peter Stuge34f29072010-01-17 18:33:53 +0000251uint8_t str2msr(char *str, struct msr *msr, char **endptr) {
Peter Stugedad1e302008-11-22 17:13:36 +0000252 char c;
253 size_t len, lo;
254 if (0 == strncmp(str, "0x", 2) || 0 == strncmp(str, "0X", 2))
255 str += 2;
256 len = strspn(str, HEXCHARS);
Peter Stuge34f29072010-01-17 18:33:53 +0000257 if (len <= 8 && (0 == str[len] || ' ' == str[len])) {
Peter Stugedad1e302008-11-22 17:13:36 +0000258 msr->hi = 0;
259 lo = 0;
260 } else if (len <= 8) {
261 lo = len + strcspn(str + len, HEXCHARS);
262 if (0 == len && 0 == strspn(str + lo, HEXCHARS))
263 return 0;
264 c = str[len];
265 str[len] = 0;
266 msr->hi = strtoul(str, NULL, 16);
267 str[len] = c;
268 } else {
269 lo = len - 8;
270 c = str[lo];
271 str[lo] = 0;
272 msr->hi = strtoul(str, NULL, 16);
273 str[lo] = c;
274 }
Peter Stuge34f29072010-01-17 18:33:53 +0000275 msr->lo = strtoul(str + lo, endptr, 16);
Peter Stugedad1e302008-11-22 17:13:36 +0000276 return 1;
277}
278
279void decodemsr(const uint8_t cpu, const uint32_t addr, const struct msr val) {
280 struct msr bitval, mask;
281 const struct msrdef *m = findmsrdef(addr);
282 const struct msrbits *mb;
283
Peter Stugecc9db9d2008-11-22 18:29:44 +0000284 if (NULL != m)
Peter Stugedad1e302008-11-22 17:13:36 +0000285 printf("# %s ", m->symbol);
286 printf("0x%08x = 0x%08x%08x\n", addr, val.hi, val.lo);
Peter Stugecc9db9d2008-11-22 18:29:44 +0000287 if (NULL == m) {
Peter Stugedad1e302008-11-22 17:13:36 +0000288 fprintf(stderr, "Sorry - no definition exists for this MSR! Please add it and send a signed-off\n");
289 fprintf(stderr, "patch to coreboot@coreboot.org. Thanks for your help!\n");
290 return;
291 }
292
293 for (mb = m->bits; mb->size; mb++) {
294 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
295 continue;
296 print_bitdef(stdout, mb, " = ");
297 mask.hi = mask.lo = 0xffffffff;
298 mask = msr_shr(mask, 64 - mb->size);
299 bitval = msr_shr(val, mb->start - mb->size + 1);
300 msr_and(&bitval, mask);
301 print_bitval(stdout, mb, bitval);
302 }
303}
304
305/**
306 * Compare two MSR values and print any differences with field definitions and
307 * both old and new values decoded.
308 *
309 * @param f Output stream.
310 * @param addr MSR address.
311 * @param a Left value.
312 * @param b Right value.
313 * @return 1 when a and b differ, 0 when they are equal or only reserved bits
314 * differ and processing of reserved bits was not requested (with -r).
315 */
316uint8_t diff_msr(FILE *f, const uint32_t addr, const struct msr a, const struct msr b) {
317 uint8_t ret = 0, first = 1;
318 struct msr aval, bval, mask;
319 const struct msrdef *m = findmsrdef(addr);
320 const struct msrbits *mb;
321
322 if (a.hi == b.hi && a.lo == b.lo)
323 return 0;
324
Peter Stugecc9db9d2008-11-22 18:29:44 +0000325 if (NULL == m) {
Peter Stugedad1e302008-11-22 17:13:36 +0000326 fprintf(stderr, "MSR 0x%08x has no definition! Please add it and send a Signed-off-by patch\n", addr);
327 fprintf(stderr, "to coreboot@coreboot.org. Thank you for your help!\n");
328 return 1;
329 }
330
331 for (mb = m->bits; mb->size; mb++) {
332 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
333 continue;
334 mask.hi = mask.lo = 0xffffffff;
335 mask = msr_shr(mask, 64 - mb->size);
336 aval = msr_shr(a, mb->start - mb->size + 1);
337 bval = msr_shr(b, mb->start - mb->size + 1);
338 msr_and(&aval, mask);
339 msr_and(&bval, mask);
340 if (msr_eq(aval, bval))
341 continue;
342 if (first) {
343 fprintf(f, "# %s\n", m->symbol);
344 fprintf(f, "-0x%08x 0x%08x%08x\n", addr, a.hi, a.lo);
345 fprintf(f, "+0x%08x 0x%08x%08x\n", addr, b.hi, b.lo);
346 first = 0;
347 ret = 1;
348 }
349 print_bitdef(f, mb, "\n-");
350 print_bitval(f, mb, aval);
351 fprintf(f, "+");
352 print_bitval(f, mb, bval);
353 }
354 return ret;
355}