2 * This file is part of msrtool.
4 * Copyright (c) 2008 Peter Stuge <peter@stuge.se>
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.
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.
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
26 static void print_bitdef(FILE *f, const struct msrbits *mb, const char *tail) {
28 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
31 fprintf(f, "# %5d", mb->start);
33 endbit = mb->start - mb->size + 1;
34 fprintf(f, "# %*d:%d", endbit < 10 ? 3 : 2, mb->start, endbit);
36 if (0 == strcmp(mb->name, "RSVD"))
37 fprintf(f, " [%s]", mb->desc);
39 fprintf(f, " %s %s", mb->name, mb->desc);
40 fprintf(f, "%s", tail);
43 static void print_bitval(FILE *f, const struct msrbits *mb, const struct msr val) {
45 struct msr tmp, mask = MSR1(1);
46 const struct msrbitvalues *mbv = mb->bitval;
47 while (mbv->text && !msr_eq(mbv->value, val))
49 switch (mb->present) {
51 mask = msr_shl(mask, mb->size - 1);
52 for (i = 0; i < mb->size; i++) {
53 memcpy(&tmp, &val, sizeof(val));
55 fprintf(f, "%d", (tmp.hi || tmp.lo) ? 1 : 0);
56 mask = msr_shr(mask, 1);
60 fprintf(f, "%d", val.lo);
63 fprintf(f, "0%o", val.lo);
66 hexprint(f, val, mb->size);
69 hexprint(f, val, mb->size);
70 fprintf(f, " %d", val.lo);
74 fprintf(f, ": %s", mbv->text);
78 void hexprint(FILE *f, const struct msr val, const uint8_t bits) {
80 fprintf(f, "0x%01x", val.lo & 0xf);
82 fprintf(f, "0x%02x", val.lo & 0xff);
84 fprintf(f, "0x%03x", val.lo & 0xfff);
86 fprintf(f, "0x%04x", val.lo & 0xffff);
88 fprintf(f, "0x%05x", val.lo & 0xfffff);
90 fprintf(f, "0x%06x", val.lo & 0xffffff);
92 fprintf(f, "0x%07x", val.lo & 0xfffffff);
94 fprintf(f, "0x%08x", val.lo);
96 fprintf(f, "0x%01x%08x", val.hi & 0xf, val.lo);
98 fprintf(f, "0x%02x%08x", val.hi & 0xff, val.lo);
100 fprintf(f, "0x%03x%08x", val.hi & 0xfff, val.lo);
102 fprintf(f, "0x%04x%08x", val.hi & 0xffff, val.lo);
104 fprintf(f, "0x%05x%08x", val.hi & 0xfffff, val.lo);
106 fprintf(f, "0x%06x%08x", val.hi & 0xffffff, val.lo);
108 fprintf(f, "0x%07x%08x", val.hi & 0xfffffff, val.lo);
110 fprintf(f, "0x%08x%08x", val.hi, val.lo);
113 int msr_eq(const struct msr a, const struct msr b) {
114 return a.hi == b.hi && a.lo == b.lo;
117 struct msr msr_shl(const struct msr a, const uint8_t bits) {
120 ret.hi = bits < 32 ? a.hi << bits : 0;
121 ret.lo = bits < 32 ? a.lo << bits : 0;
124 ret.hi |= bits ? a.lo >> (32 - bits) : 0;
126 ret.hi |= a.lo << (bits - 32);
131 struct msr msr_shr(const struct msr a, const uint8_t bits) {
134 ret.hi = bits < 32 ? a.hi >> bits : 0;
135 ret.lo = bits < 32 ? a.lo >> bits : 0;
138 ret.lo |= bits ? a.hi << (32 - bits) : 0;
140 ret.lo |= a.hi >> (bits - 32);
145 void msr_and(struct msr *a, const struct msr b) {
150 const struct msrdef *findmsrdef(const uint32_t addr) {
152 const struct msrdef *m;
155 for (t = 0; t < targets_found; t++)
156 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++)
162 uint32_t msraddrbyname(const char *name) {
164 const uint32_t addr = strtoul(name, NULL, 16);
165 const struct msrdef *m;
168 for (t = 0; t < targets_found; t++)
169 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++) {
172 if (!strcasecmp(name, m->symbol))
178 void dumpmsrdefs(const struct targetdef *t) {
179 const struct msrdef *m;
180 const struct msrbits *mb;
183 printf("# %s MSRs:\n", t->name);
184 for (m = t->msrs; !MSR_ISEOT(*m); m++) {
187 printf("# %s\n", m->symbol);
188 for (mb = m->bits; mb->size; mb++)
189 print_bitdef(stdout, mb, "\n");
190 printf("0x%08x\n", m->addr);
194 int dumpmsrdefsvals(FILE *f, const struct targetdef *t, const uint8_t cpu) {
195 struct msr val = MSR1(0);
196 const struct msrdef *m;
197 const struct msrbits *mb;
200 fprintf(f, "# %s MSRs:\n", t->name);
201 for (m = t->msrs; !MSR_ISEOT(*m); m++) {
204 if (!sys->rdmsr(cpu, m->addr, &val))
206 fprintf(f, "# %s\n", m->symbol);
207 for (mb = m->bits; mb->size; mb++)
208 print_bitdef(f, mb, "\n");
209 fprintf(f, "0x%08x 0x%08x%08x\n", m->addr, val.hi, val.lo);
215 * Parse a hexadecimal string into an MSR value.
217 * Leading 0x or 0X is optional, the string is always parsed as hexadecimal.
218 * Any non-hexadecimal character except ' ' can separate the high 32 bits and
219 * the low 32 bits. If there is such a separator, high and low values do not
220 * need to be zero padded. If there is no separator, the last <=8 digits are
221 * the low 32 bits and any characters before them are the high 32 bits.
222 * When there is no separator and less than eight digits, the high 32 bits
224 * Parsing fails when there is a separator and it is followed by another
225 * non-hexadecimal character.
227 * @param str The string to parse. The string must be writable but will be
228 * restored before return.
229 * @param msr Pointer to the struct msr where the value will be stored.
230 * @param endptr If endptr is not NULL, *endptr will point to after the MSR.
231 * @return 1 on success, 0 on parse failure. msr is unchanged on failure.
233 uint8_t str2msr(char *str, struct msr *msr, char **endptr) {
236 if (0 == strncmp(str, "0x", 2) || 0 == strncmp(str, "0X", 2))
238 len = strspn(str, HEXCHARS);
239 if (len <= 8 && (0 == str[len] || ' ' == str[len])) {
242 } else if (len <= 8) {
243 lo = len + strcspn(str + len, HEXCHARS);
244 if (0 == len && 0 == strspn(str + lo, HEXCHARS))
248 msr->hi = strtoul(str, NULL, 16);
254 msr->hi = strtoul(str, NULL, 16);
257 msr->lo = strtoul(str + lo, endptr, 16);
261 void decodemsr(const uint8_t cpu, const uint32_t addr, const struct msr val) {
262 struct msr bitval, mask;
263 const struct msrdef *m = findmsrdef(addr);
264 const struct msrbits *mb;
267 printf("# %s ", m->symbol);
268 printf("0x%08x = 0x%08x%08x\n", addr, val.hi, val.lo);
270 fprintf(stderr, "Sorry - no definition exists for this MSR! Please add it and send a signed-off\n");
271 fprintf(stderr, "patch to coreboot@coreboot.org. Thanks for your help!\n");
275 for (mb = m->bits; mb->size; mb++) {
276 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
278 print_bitdef(stdout, mb, " = ");
279 mask.hi = mask.lo = 0xffffffff;
280 mask = msr_shr(mask, 64 - mb->size);
281 bitval = msr_shr(val, mb->start - mb->size + 1);
282 msr_and(&bitval, mask);
283 print_bitval(stdout, mb, bitval);
288 * Compare two MSR values and print any differences with field definitions and
289 * both old and new values decoded.
291 * @param f Output stream.
292 * @param addr MSR address.
293 * @param a Left value.
294 * @param b Right value.
295 * @return 1 when a and b differ, 0 when they are equal or only reserved bits
296 * differ and processing of reserved bits was not requested (with -r).
298 uint8_t diff_msr(FILE *f, const uint32_t addr, const struct msr a, const struct msr b) {
299 uint8_t ret = 0, first = 1;
300 struct msr aval, bval, mask;
301 const struct msrdef *m = findmsrdef(addr);
302 const struct msrbits *mb;
304 if (a.hi == b.hi && a.lo == b.lo)
308 fprintf(stderr, "MSR 0x%08x has no definition! Please add it and send a Signed-off-by patch\n", addr);
309 fprintf(stderr, "to coreboot@coreboot.org. Thank you for your help!\n");
313 for (mb = m->bits; mb->size; mb++) {
314 if (!reserved && 0 == strcmp(mb->name, "RSVD"))
316 mask.hi = mask.lo = 0xffffffff;
317 mask = msr_shr(mask, 64 - mb->size);
318 aval = msr_shr(a, mb->start - mb->size + 1);
319 bval = msr_shr(b, mb->start - mb->size + 1);
320 msr_and(&aval, mask);
321 msr_and(&bval, mask);
322 if (msr_eq(aval, bval))
325 fprintf(f, "# %s\n", m->symbol);
326 fprintf(f, "-0x%08x 0x%08x%08x\n", addr, a.hi, a.lo);
327 fprintf(f, "+0x%08x 0x%08x%08x\n", addr, b.hi, b.lo);
331 print_bitdef(f, mb, "\n-");
332 print_bitval(f, mb, aval);
334 print_bitval(f, mb, bval);