msrutils.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <stdio.h> 4 #include <string.h> 5 #include <stdlib.h> 6 7 #include "msrtool.h" 8 9 static void print_bitdef(FILE *f, const struct msrbits *mb, const char *tail) { 10 uint8_t endbit; 11 if (!reserved && 0 == strcmp(mb->name, "RSVD")) 12 return; 13 if (1 == mb->size) 14 fprintf(f, "# %5d", mb->start); 15 else { 16 endbit = mb->start - mb->size + 1; 17 fprintf(f, "# %*d:%d", endbit < 10 ? 3 : 2, mb->start, endbit); 18 } 19 if (0 == strcmp(mb->name, "RSVD")) 20 fprintf(f, " [%s]", mb->desc); 21 else 22 fprintf(f, " %s %s", mb->name, mb->desc); 23 fprintf(f, "%s", tail); 24 } 25 26 static void print_bitval(FILE *f, const struct msrbits *mb, const struct msr val) { 27 uint8_t i; 28 struct msr tmp, mask = MSR1(1); 29 const struct msrbitvalues *mbv = mb->bitval; 30 while (mbv->text && !msr_eq(mbv->value, val)) 31 mbv++; 32 switch (mb->present) { 33 case PRESENT_BIN: 34 mask = msr_shl(mask, mb->size - 1); 35 for (i = 0; i < mb->size; i++) { 36 memcpy(&tmp, &val, sizeof(val)); 37 msr_and(&tmp, mask); 38 fprintf(f, "%d", (tmp.hi || tmp.lo) ? 1 : 0); 39 mask = msr_shr(mask, 1); 40 } 41 break; 42 case PRESENT_DEC: 43 fprintf(f, "%d", val.lo); 44 break; 45 case PRESENT_OCT: 46 fprintf(f, "0%o", val.lo); 47 break; 48 case PRESENT_HEX: 49 hexprint(f, val, mb->size); 50 break; 51 case PRESENT_HEXDEC: 52 hexprint(f, val, mb->size); 53 fprintf(f, " %d", val.lo); 54 break; 55 case PRESENT_STR: 56 strprint(f, val, mb->size); 57 break; 58 } 59 if (mbv->text) 60 fprintf(f, ": %s", mbv->text); 61 fprintf(f, "\n"); 62 } 63 64 void hexprint(FILE *f, const struct msr val, const uint8_t bits) { 65 if (bits <= 4) 66 fprintf(f, "0x%01x", val.lo & 0xf); 67 else if (bits <= 8) 68 fprintf(f, "0x%02x", val.lo & 0xff); 69 else if (bits <= 12) 70 fprintf(f, "0x%03x", val.lo & 0xfff); 71 else if (bits <= 16) 72 fprintf(f, "0x%04x", val.lo & 0xffff); 73 else if (bits <= 20) 74 fprintf(f, "0x%05x", val.lo & 0xfffff); 75 else if (bits <= 24) 76 fprintf(f, "0x%06x", val.lo & 0xffffff); 77 else if (bits <= 28) 78 fprintf(f, "0x%07x", val.lo & 0xfffffff); 79 else if (bits <= 32) 80 fprintf(f, "0x%08x", val.lo); 81 else if (bits <= 36) 82 fprintf(f, "0x%01x%08x", val.hi & 0xf, val.lo); 83 else if (bits <= 40) 84 fprintf(f, "0x%02x%08x", val.hi & 0xff, val.lo); 85 else if (bits <= 44) 86 fprintf(f, "0x%03x%08x", val.hi & 0xfff, val.lo); 87 else if (bits <= 48) 88 fprintf(f, "0x%04x%08x", val.hi & 0xffff, val.lo); 89 else if (bits <= 52) 90 fprintf(f, "0x%05x%08x", val.hi & 0xfffff, val.lo); 91 else if (bits <= 56) 92 fprintf(f, "0x%06x%08x", val.hi & 0xffffff, val.lo); 93 else if (bits <= 60) 94 fprintf(f, "0x%07x%08x", val.hi & 0xfffffff, val.lo); 95 else 96 fprintf(f, "0x%08x%08x", val.hi, val.lo); 97 } 98 99 void strprint(FILE *f, const struct msr val, const uint8_t bits) { 100 if (bits > 56) 101 fputc(val.hi, f); 102 if (bits > 48) 103 fputc(val.hi >> 8, f); 104 if (bits > 40) 105 fputc(val.hi >> 16, f); 106 if (bits > 32) 107 fputc(val.hi >> 24, f); 108 if (bits > 24) 109 fputc(val.lo, f); 110 if (bits > 16) 111 fputc(val.lo >> 8, f); 112 if (bits > 8) 113 fputc(val.lo >> 16, f); 114 if (bits > 0) 115 fputc(val.lo >> 24, f); 116 } 117 118 int msr_eq(const struct msr a, const struct msr b) { 119 return a.hi == b.hi && a.lo == b.lo; 120 } 121 122 struct msr msr_shl(const struct msr a, const uint8_t bits) { 123 struct msr ret; 124 125 ret.hi = bits < 32 ? a.hi << bits : 0; 126 ret.lo = bits < 32 ? a.lo << bits : 0; 127 128 if (bits < 32) 129 ret.hi |= bits ? a.lo >> (32 - bits) : 0; 130 else 131 ret.hi |= a.lo << (bits - 32); 132 133 return ret; 134 } 135 136 struct msr msr_shr(const struct msr a, const uint8_t bits) { 137 struct msr ret; 138 139 ret.hi = bits < 32 ? a.hi >> bits : 0; 140 ret.lo = bits < 32 ? a.lo >> bits : 0; 141 142 if (bits < 32) 143 ret.lo |= bits ? a.hi << (32 - bits) : 0; 144 else 145 ret.lo |= a.hi >> (bits - 32); 146 147 return ret; 148 } 149 150 void msr_and(struct msr *a, const struct msr b) { 151 a->hi &= b.hi; 152 a->lo &= b.lo; 153 } 154 155 const struct msrdef *findmsrdef(const uint32_t addr) { 156 uint8_t t; 157 const struct msrdef *m; 158 if (!targets) 159 return NULL; 160 for (t = 0; t < targets_found; t++) 161 for (m = targets[t]->msrs; !MSR_ISEOT(*m); m++) 162 if (addr == m->addr) 163 return m; 164 return NULL; 165 } 166 167 uint32_t msraddrbyname(const char *name) { 168 uint8_t t; 169 const uint32_t addr = strtoul(name, NULL, 16); 170 const struct msrdef *m; 171 if (!targets) 172 return addr; 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->addr; 177 if (!strcasecmp(name, m->symbol)) 178 return m->addr; 179 } 180 return addr; 181 } 182 183 void dumpmsrdefs(const struct targetdef *t) { 184 const struct msrdef *m; 185 const struct msrbits *mb; 186 if (NULL == t) 187 return; 188 printf("# %s MSRs:\n", t->name); 189 for (m = t->msrs; !MSR_ISEOT(*m); m++) { 190 if (t->msrs != m) 191 printf("\n"); 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); 196 } 197 } 198 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; 203 if (NULL == t) 204 return 1; 205 fprintf(f, "# %s MSRs:\n", t->name); 206 for (m = t->msrs; !MSR_ISEOT(*m); m++) { 207 if (t->msrs != m) 208 fprintf(f, "\n"); 209 if (!sys->rdmsr(cpu, m->addr, &val)) 210 return 1; 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); 215 } 216 return 0; 217 } 218 219 /** 220 * Parse a hexadecimal string into an MSR value. 221 * 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 228 * are set to 0. 229 * Parsing fails when there is a separator and it is followed by another 230 * non-hexadecimal character. 231 * 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. 237 */ 238 uint8_t str2msr(char *str, struct msr *msr, char **endptr) { 239 char c; 240 size_t len, lo; 241 if (0 == strncmp(str, "0x", 2) || 0 == strncmp(str, "0X", 2)) 242 str += 2; 243 len = strspn(str, HEXCHARS); 244 if (len <= 8 && (0 == str[len] || ' ' == str[len])) { 245 msr->hi = 0; 246 lo = 0; 247 } else if (len <= 8) { 248 lo = len + strcspn(str + len, HEXCHARS); 249 if (0 == len && 0 == strspn(str + lo, HEXCHARS)) 250 return 0; 251 c = str[len]; 252 str[len] = 0; 253 msr->hi = strtoul(str, NULL, 16); 254 str[len] = c; 255 } else { 256 lo = len - 8; 257 c = str[lo]; 258 str[lo] = 0; 259 msr->hi = strtoul(str, NULL, 16); 260 str[lo] = c; 261 } 262 msr->lo = strtoul(str + lo, endptr, 16); 263 return 1; 264 } 265 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; 270 271 if (NULL != m) 272 printf("# %s ", m->symbol); 273 printf("0x%08x = 0x%08x%08x\n", addr, val.hi, val.lo); 274 if (NULL == m) { 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"); 277 return; 278 } 279 280 for (mb = m->bits; mb->size; mb++) { 281 if (!reserved && 0 == strcmp(mb->name, "RSVD")) 282 continue; 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); 289 } 290 } 291 292 /** 293 * Compare two MSR values and print any differences with field definitions and 294 * both old and new values decoded. 295 * 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). 302 */ 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; 308 309 if (a.hi == b.hi && a.lo == b.lo) 310 return 0; 311 312 if (NULL == m) { 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"); 315 return 1; 316 } 317 318 for (mb = m->bits; mb->size; mb++) { 319 if (!reserved && 0 == strcmp(mb->name, "RSVD")) 320 continue; 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)) 328 continue; 329 if (first) { 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); 333 first = 0; 334 ret = 1; 335 } 336 print_bitdef(f, mb, "\n-"); 337 print_bitval(f, mb, aval); 338 fprintf(f, "+"); 339 print_bitval(f, mb, bval); 340 } 341 return ret; 342 }