blob: de3333e6dbeeea6d61b96cb9af94231b203265ad [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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <stdio.h>
21#include <string.h>
22#include <stdlib.h>
23
24#include "msrtool.h"
25
26static void print_bitdef(FILE *f, const struct msrbits *mb, const char *tail) {
27 uint8_t endbit;
Peter Stugecc9db9d2008-11-22 18:29:44 +000028 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
Peter Stugedad1e302008-11-22 17:13:36 +000029 return;
30 if (1 == mb->size)
31 fprintf(f, "# %5d", mb->start);
32 else {
33 endbit = mb->start - mb->size + 1;
34 fprintf(f, "# %*d:%d", endbit < 10 ? 3 : 2, mb->start, endbit);
35 }
Peter Stugecc9db9d2008-11-22 18:29:44 +000036 if (0 == strcmp(mb->name, "RSVD"))
Peter Stugedad1e302008-11-22 17:13:36 +000037 fprintf(f, " [%s]", mb->desc);
38 else
39 fprintf(f, " %s %s", mb->name, mb->desc);
40 fprintf(f, "%s", tail);
41}
42
43static void print_bitval(FILE *f, const struct msrbits *mb, const struct msr val) {
44 uint8_t i;
45 struct msr tmp, mask = MSR1(1);
46 const struct msrbitvalues *mbv = mb->bitval;
47 while (mbv->text && !msr_eq(mbv->value, val))
48 mbv++;
49 switch (mb->present) {
50 case PRESENT_BIN:
51 mask = msr_shl(mask, mb->size - 1);
52 for (i = 0; i < mb->size; i++) {
53 memcpy(&tmp, &val, sizeof(val));
54 msr_and(&tmp, mask);
55 fprintf(f, "%d", (tmp.hi || tmp.lo) ? 1 : 0);
56 mask = msr_shr(mask, 1);
57 }
Peter Stugedad1e302008-11-22 17:13:36 +000058 break;
59 case PRESENT_DEC:
60 fprintf(f, "%d", val.lo);
61 break;
62 case PRESENT_OCT:
63 fprintf(f, "0%o", val.lo);
64 break;
65 case PRESENT_HEX:
66 hexprint(f, val, mb->size);
67 break;
68 case PRESENT_HEXDEC:
69 hexprint(f, val, mb->size);
70 fprintf(f, " %d", val.lo);
71 break;
72 }
73 if (mbv->text)
74 fprintf(f, ": %s", mbv->text);
75 fprintf(f, "\n");
76}
77
78void hexprint(FILE *f, const struct msr val, const uint8_t bits) {
79 if (bits <= 4)
80 fprintf(f, "0x%x", (uint8_t)(val.lo & 0x0f));
81 else if (bits <= 8)
82 fprintf(f, "0x%02x", (uint8_t)(val.lo & 0xff));
83 else if (bits <= 16)
84 fprintf(f, "0x%04x", (uint16_t)(val.lo & 0xffff));
85 else if (bits <= 32)
86 fprintf(f, "0x%08x", val.lo);
87 else
88 fprintf(f, "0x%08x%08x", val.hi, val.lo);
89}
90
91int msr_eq(const struct msr a, const struct msr b) {
92 return a.hi == b.hi && a.lo == b.lo;
93}
94
95struct msr msr_shl(const struct msr a, const uint8_t bits) {
96 struct msr ret;
97
98 ret.hi = bits < 32 ? a.hi << bits : 0;
99 ret.lo = bits < 32 ? a.lo << bits : 0;
100
101 if (bits < 32)
102 ret.hi |= bits ? a.lo >> (32 - bits) : 0;
103 else
104 ret.hi |= a.lo << (bits - 32);
105
106 return ret;
107}
108
109struct msr msr_shr(const struct msr a, const uint8_t bits) {
110 struct msr ret;
111
112 ret.hi = bits < 32 ? a.hi >> bits : 0;
113 ret.lo = bits < 32 ? a.lo >> bits : 0;
114
115 if (bits < 32)
116 ret.lo |= bits ? a.hi << (32 - bits) : 0;
117 else
118 ret.lo |= a.hi >> (bits - 32);
119
120 return ret;
121}
122
123void msr_and(struct msr *a, const struct msr b) {
124 a->hi &= b.hi;
125 a->lo &= b.lo;
126}
127
128const struct msrdef *findmsrdef(const uint32_t addr) {
129 uint8_t t;
130 const struct msrdef *m;
131 if (!targets)
132 return NULL;
133 for (t = 0; t < targets_found; t++)
134 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++)
135 if (addr == m->addr)
136 return m;
137 return NULL;
138}
139
Marc Jones8f210762009-03-08 04:37:39 +0000140uint32_t msraddrbyname(const char *name) {
Peter Stuge3108a122009-01-26 17:18:31 +0000141 uint8_t t;
142 const uint32_t addr = strtoul(name, NULL, 16);
143 const struct msrdef *m;
144 if (!targets)
Peter Stuge5f28c092009-03-23 17:43:12 +0000145 return addr;
Peter Stuge3108a122009-01-26 17:18:31 +0000146 for (t = 0; t < targets_found; t++)
147 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++) {
148 if (addr == m->addr)
149 return m->addr;
150 if (!strcasecmp(name, m->symbol))
151 return m->addr;
152 }
Peter Stuge5f28c092009-03-23 17:43:12 +0000153 return addr;
Peter Stuge3108a122009-01-26 17:18:31 +0000154}
155
Peter Stugedad1e302008-11-22 17:13:36 +0000156void dumpmsrdefs(const struct targetdef *t) {
157 const struct msrdef *m;
158 const struct msrbits *mb;
Peter Stugecc9db9d2008-11-22 18:29:44 +0000159 if (NULL == t)
Peter Stugedad1e302008-11-22 17:13:36 +0000160 return;
161 printf("# %s MSRs:\n", t->name);
162 for (m = t->msrs; !MSR_ISEOT(*m); m++) {
163 if (t->msrs != m)
164 printf("\n");
165 printf("# %s\n", m->symbol);
166 for (mb = m->bits; mb->size; mb++)
167 print_bitdef(stdout, mb, "\n");
168 printf("0x%08x\n", m->addr);
169 }
170}
171
172int dumpmsrdefsvals(FILE *f, const struct targetdef *t, const uint8_t cpu) {
173 struct msr val = MSR1(0);
174 const struct msrdef *m;
175 const struct msrbits *mb;
Peter Stugecc9db9d2008-11-22 18:29:44 +0000176 if (NULL == t)
Peter Stugedad1e302008-11-22 17:13:36 +0000177 return 1;
178 fprintf(f, "# %s MSRs:\n", t->name);
179 for (m = t->msrs; !MSR_ISEOT(*m); m++) {
180 if (t->msrs != m)
181 fprintf(f, "\n");
182 if (!sys->rdmsr(cpu, m->addr, &val))
183 return 1;
184 fprintf(f, "# %s\n", m->symbol);
185 for (mb = m->bits; mb->size; mb++)
186 print_bitdef(f, mb, "\n");
187 fprintf(f, "0x%08x 0x%08x%08x\n", m->addr, val.hi, val.lo);
188 }
189 return 0;
190}
191
192/**
193 * Parse a hexadecimal string into an MSR value.
Uwe Hermann708ccac2009-04-10 21:05:56 +0000194 *
Peter Stugedad1e302008-11-22 17:13:36 +0000195 * Leading 0x or 0X is optional, the string is always parsed as hexadecimal.
Peter Stuge34f29072010-01-17 18:33:53 +0000196 * Any non-hexadecimal character except ' ' can separate the high 32 bits and
Peter Stugedad1e302008-11-22 17:13:36 +0000197 * the low 32 bits. If there is such a separator, high and low values do not
198 * need to be zero padded. If there is no separator, the last <=8 digits are
199 * the low 32 bits and any characters before them are the high 32 bits.
200 * When there is no separator and less than eight digits, the high 32 bits
201 * are set to 0.
202 * Parsing fails when there is a separator and it is followed by another
203 * non-hexadecimal character.
204 *
205 * @param str The string to parse. The string must be writable but will be
206 * restored before return.
207 * @param msr Pointer to the struct msr where the value will be stored.
Paul Menzel85bb83a2010-01-17 21:59:27 +0000208 * @param endptr If endptr is not NULL, *endptr will point to after the MSR.
Peter Stugedad1e302008-11-22 17:13:36 +0000209 * @return 1 on success, 0 on parse failure. msr is unchanged on failure.
210 */
Peter Stuge34f29072010-01-17 18:33:53 +0000211uint8_t str2msr(char *str, struct msr *msr, char **endptr) {
Peter Stugedad1e302008-11-22 17:13:36 +0000212 char c;
213 size_t len, lo;
214 if (0 == strncmp(str, "0x", 2) || 0 == strncmp(str, "0X", 2))
215 str += 2;
216 len = strspn(str, HEXCHARS);
Peter Stuge34f29072010-01-17 18:33:53 +0000217 if (len <= 8 && (0 == str[len] || ' ' == str[len])) {
Peter Stugedad1e302008-11-22 17:13:36 +0000218 msr->hi = 0;
219 lo = 0;
220 } else if (len <= 8) {
221 lo = len + strcspn(str + len, HEXCHARS);
222 if (0 == len && 0 == strspn(str + lo, HEXCHARS))
223 return 0;
224 c = str[len];
225 str[len] = 0;
226 msr->hi = strtoul(str, NULL, 16);
227 str[len] = c;
228 } else {
229 lo = len - 8;
230 c = str[lo];
231 str[lo] = 0;
232 msr->hi = strtoul(str, NULL, 16);
233 str[lo] = c;
234 }
Peter Stuge34f29072010-01-17 18:33:53 +0000235 msr->lo = strtoul(str + lo, endptr, 16);
Peter Stugedad1e302008-11-22 17:13:36 +0000236 return 1;
237}
238
239void decodemsr(const uint8_t cpu, const uint32_t addr, const struct msr val) {
240 struct msr bitval, mask;
241 const struct msrdef *m = findmsrdef(addr);
242 const struct msrbits *mb;
243
Peter Stugecc9db9d2008-11-22 18:29:44 +0000244 if (NULL != m)
Peter Stugedad1e302008-11-22 17:13:36 +0000245 printf("# %s ", m->symbol);
246 printf("0x%08x = 0x%08x%08x\n", addr, val.hi, val.lo);
Peter Stugecc9db9d2008-11-22 18:29:44 +0000247 if (NULL == m) {
Peter Stugedad1e302008-11-22 17:13:36 +0000248 fprintf(stderr, "Sorry - no definition exists for this MSR! Please add it and send a signed-off\n");
249 fprintf(stderr, "patch to coreboot@coreboot.org. Thanks for your help!\n");
250 return;
251 }
252
253 for (mb = m->bits; mb->size; mb++) {
254 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
255 continue;
256 print_bitdef(stdout, mb, " = ");
257 mask.hi = mask.lo = 0xffffffff;
258 mask = msr_shr(mask, 64 - mb->size);
259 bitval = msr_shr(val, mb->start - mb->size + 1);
260 msr_and(&bitval, mask);
261 print_bitval(stdout, mb, bitval);
262 }
263}
264
265/**
266 * Compare two MSR values and print any differences with field definitions and
267 * both old and new values decoded.
268 *
269 * @param f Output stream.
270 * @param addr MSR address.
271 * @param a Left value.
272 * @param b Right value.
273 * @return 1 when a and b differ, 0 when they are equal or only reserved bits
274 * differ and processing of reserved bits was not requested (with -r).
275 */
276uint8_t diff_msr(FILE *f, const uint32_t addr, const struct msr a, const struct msr b) {
277 uint8_t ret = 0, first = 1;
278 struct msr aval, bval, mask;
279 const struct msrdef *m = findmsrdef(addr);
280 const struct msrbits *mb;
281
282 if (a.hi == b.hi && a.lo == b.lo)
283 return 0;
284
Peter Stugecc9db9d2008-11-22 18:29:44 +0000285 if (NULL == m) {
Peter Stugedad1e302008-11-22 17:13:36 +0000286 fprintf(stderr, "MSR 0x%08x has no definition! Please add it and send a Signed-off-by patch\n", addr);
287 fprintf(stderr, "to coreboot@coreboot.org. Thank you for your help!\n");
288 return 1;
289 }
290
291 for (mb = m->bits; mb->size; mb++) {
292 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
293 continue;
294 mask.hi = mask.lo = 0xffffffff;
295 mask = msr_shr(mask, 64 - mb->size);
296 aval = msr_shr(a, mb->start - mb->size + 1);
297 bval = msr_shr(b, mb->start - mb->size + 1);
298 msr_and(&aval, mask);
299 msr_and(&bval, mask);
300 if (msr_eq(aval, bval))
301 continue;
302 if (first) {
303 fprintf(f, "# %s\n", m->symbol);
304 fprintf(f, "-0x%08x 0x%08x%08x\n", addr, a.hi, a.lo);
305 fprintf(f, "+0x%08x 0x%08x%08x\n", addr, b.hi, b.lo);
306 first = 0;
307 ret = 1;
308 }
309 print_bitdef(f, mb, "\n-");
310 print_bitval(f, mb, aval);
311 fprintf(f, "+");
312 print_bitval(f, mb, bval);
313 }
314 return ret;
315}