* Search for an applicable microcode update, and load it. APs will load the * selected update once they come online. * * "free" is the address of the next free physical page. If a microcode update * is selected, it will be copied to this region prior to loading in order to * satisfy alignment requirements. */
| 314 | * satisfy alignment requirements. |
| 315 | */ |
| 316 | size_t |
| 317 | ucode_load_bsp(uintptr_t free) |
| 318 | { |
| 319 | union { |
| 320 | uint32_t regs[4]; |
| 321 | char vendor[13]; |
| 322 | } cpuid; |
| 323 | uint8_t *addr, *fileaddr, *match; |
| 324 | char *type; |
| 325 | uint64_t nrev, orev; |
| 326 | caddr_t file; |
| 327 | size_t i, len; |
| 328 | int error; |
| 329 | |
| 330 | KASSERT(free % PAGE_SIZE == 0, ("unaligned boundary %p", (void *)free)); |
| 331 | |
| 332 | do_cpuid(0, cpuid.regs); |
| 333 | cpuid.regs[0] = cpuid.regs[1]; |
| 334 | cpuid.regs[1] = cpuid.regs[3]; |
| 335 | cpuid.vendor[12] = '\0'; |
| 336 | for (i = 0; i < nitems(loaders); i++) |
| 337 | if (strcmp(cpuid.vendor, loaders[i].vendor) == 0) { |
| 338 | ucode_loader = &loaders[i]; |
| 339 | break; |
| 340 | } |
| 341 | if (ucode_loader == NULL) |
| 342 | return (0); |
| 343 | |
| 344 | file = 0; |
| 345 | fileaddr = match = NULL; |
| 346 | for (;;) { |
| 347 | file = preload_search_next_name(file); |
| 348 | if (file == 0) |
| 349 | break; |
| 350 | type = (char *)preload_search_info(file, MODINFO_TYPE); |
| 351 | if (type == NULL || strcmp(type, "cpu_microcode") != 0) |
| 352 | continue; |
| 353 | |
| 354 | fileaddr = preload_fetch_addr(file); |
| 355 | len = preload_fetch_size(file); |
| 356 | match = ucode_loader->match(fileaddr, &len); |
| 357 | if (match != NULL) { |
| 358 | addr = map_ucode(free, len); |
| 359 | /* We can't use memcpy() before ifunc resolution. */ |
| 360 | memcpy_early(addr, match, len); |
| 361 | match = addr; |
| 362 | |
| 363 | error = ucode_loader->load(match, false, &nrev, &orev); |
| 364 | if (error == 0) { |
| 365 | ucode_data = early_ucode_data = match; |
| 366 | ucode_nrev = nrev; |
| 367 | ucode_orev = orev; |
| 368 | return (len); |
| 369 | } |
| 370 | unmap_ucode(free, len); |
| 371 | } |
| 372 | } |
| 373 | if (fileaddr != NULL && ucode_error == NO_ERROR) |
no test coverage detected