| 254 | static uint64 |
| 255 | read_msr(uint32 msr) |
| 256 | { |
| 257 | uint32 low, high; |
| 258 | asm volatile ("rdmsr" : "=a"(low), "=d"(high) : "c"(msr)); |
| 259 | return ((uint64)high << 32) | low; |
| 260 | } |
| 261 | |
| 262 | |
| 263 | static void |
| 264 | write_msr(uint32 msr, uint64 value) |
| 265 | { |
| 266 | uint32 low = (uint32)value; |
| 267 | uint32 high = (uint32)(value >> 32); |
| 268 | asm volatile ("wrmsr" : : "a"(low), "d"(high), "c"(msr)); |
| 269 | } |
| 270 | |
| 271 | |
| 272 | static const char * |
| 273 | mtrr_type_to_string(uint8 type) |
| 274 | { |
| 275 | switch (type) { |
| 276 | case 0: |
| 277 | return "uncacheable"; |
| 278 | case 1: |
| 279 | return "write combining"; |
| 280 | case 4: |
| 281 | return "write-through"; |
| 282 | case 5: |
| 283 | return "write-protected"; |
| 284 | case 6: |
| 285 | return "write-back"; |
| 286 | default: |
| 287 | return "reserved"; |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | |
| 292 | static bool |
| 293 | get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type) |
| 294 | { |
| 295 | uint64 mask = read_msr(0x201 + index * 2); |
| 296 | if ((mask & (1 << 11)) == 0) |
| 297 | return false; |
| 298 | |
| 299 | uint64 base = read_msr(0x200 + index * 2); |
| 300 | |
| 301 | *_base = base & ~(B_PAGE_SIZE - 1); |
| 302 | *_length = (~mask & ((1ULL << 36) - 1)) + B_PAGE_SIZE; |
| 303 | *_type = base & 0xff; |
| 304 | |
| 305 | return true; |
| 306 | } |
| 307 | |
| 308 | |
| 310 | mtrr_dump() |
| 311 | { |
| 312 | uint32 count = (read_msr(0xfe) & 0xff); |
| 313 | dprintf("mtrr: %lu variable ranges\n", count); |
| 314 | |
| 315 | uint64 defaultType = read_msr(0x2ff); |
| 316 | dprintf("mtrr: default type: 0x%llx (%s, variable %sabled, fixed %sabled)\n", |
| 317 | defaultType, mtrr_type_to_string(defaultType), |
| 318 | (defaultType & (1 << 11)) != 0 ? "en" : "dis", |
| 319 | (defaultType & (1 << 10)) != 0 ? "en" : "dis"); |
| 320 | |
| 321 | for (uint32 i = 0; i < count; i++) { |
| 322 | uint64 base, length; |
| 323 | uint8 type; |
| 324 | if (get_mtrr(i, &base, &length, &type)) { |
| 325 | dprintf("mtrr: entry %lu: base: 0x%llx; length: 0x%llx; type: %u %s\n", |
| 326 | i, base, length, type, mtrr_type_to_string(type)); |
| 327 | } else |
| 328 | dprintf("mtrr: entry %lu: empty\n", i); |
| 329 | } |
| 330 | |
| 331 | // set default to uncachable |
| 332 | write_msr(0x2ff, read_msr(0x2ff) & ~0xff); |
| 333 | } |
| 334 | |
| 335 | |
| 336 | extern "C" void |