| .. | .. |
|---|
| 55 | 55 | }; |
|---|
| 56 | 56 | |
|---|
| 57 | 57 | static u32 ucode_new_rev; |
|---|
| 58 | | -static u8 amd_ucode_patch[PATCH_MAX_SIZE]; |
|---|
| 58 | + |
|---|
| 59 | +/* One blob per node. */ |
|---|
| 60 | +static u8 amd_ucode_patch[MAX_NUMNODES][PATCH_MAX_SIZE]; |
|---|
| 59 | 61 | |
|---|
| 60 | 62 | /* |
|---|
| 61 | 63 | * Microcode patch container file is prepended to the initrd in cpio |
|---|
| .. | .. |
|---|
| 429 | 431 | patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch); |
|---|
| 430 | 432 | #else |
|---|
| 431 | 433 | new_rev = &ucode_new_rev; |
|---|
| 432 | | - patch = &amd_ucode_patch; |
|---|
| 434 | + patch = &amd_ucode_patch[0]; |
|---|
| 433 | 435 | #endif |
|---|
| 434 | 436 | |
|---|
| 435 | 437 | desc.cpuid_1_eax = cpuid_1_eax; |
|---|
| .. | .. |
|---|
| 548 | 550 | apply_microcode_early_amd(cpuid_1_eax, cp.data, cp.size, false); |
|---|
| 549 | 551 | } |
|---|
| 550 | 552 | |
|---|
| 551 | | -static enum ucode_state |
|---|
| 552 | | -load_microcode_amd(bool save, u8 family, const u8 *data, size_t size); |
|---|
| 553 | +static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); |
|---|
| 553 | 554 | |
|---|
| 554 | 555 | int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax) |
|---|
| 555 | 556 | { |
|---|
| .. | .. |
|---|
| 567 | 568 | if (!desc.mc) |
|---|
| 568 | 569 | return -EINVAL; |
|---|
| 569 | 570 | |
|---|
| 570 | | - ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size); |
|---|
| 571 | + ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); |
|---|
| 571 | 572 | if (ret > UCODE_UPDATED) |
|---|
| 572 | 573 | return -EINVAL; |
|---|
| 573 | 574 | |
|---|
| 574 | 575 | return 0; |
|---|
| 575 | 576 | } |
|---|
| 576 | 577 | |
|---|
| 577 | | -void reload_ucode_amd(void) |
|---|
| 578 | +void reload_ucode_amd(unsigned int cpu) |
|---|
| 578 | 579 | { |
|---|
| 579 | | - struct microcode_amd *mc; |
|---|
| 580 | 580 | u32 rev, dummy __always_unused; |
|---|
| 581 | + struct microcode_amd *mc; |
|---|
| 581 | 582 | |
|---|
| 582 | | - mc = (struct microcode_amd *)amd_ucode_patch; |
|---|
| 583 | + mc = (struct microcode_amd *)amd_ucode_patch[cpu_to_node(cpu)]; |
|---|
| 583 | 584 | |
|---|
| 584 | 585 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); |
|---|
| 585 | 586 | |
|---|
| .. | .. |
|---|
| 699 | 700 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); |
|---|
| 700 | 701 | |
|---|
| 701 | 702 | /* need to apply patch? */ |
|---|
| 702 | | - if (rev >= mc_amd->hdr.patch_id) { |
|---|
| 703 | + if (rev > mc_amd->hdr.patch_id) { |
|---|
| 703 | 704 | ret = UCODE_OK; |
|---|
| 704 | 705 | goto out; |
|---|
| 705 | 706 | } |
|---|
| .. | .. |
|---|
| 845 | 846 | return UCODE_OK; |
|---|
| 846 | 847 | } |
|---|
| 847 | 848 | |
|---|
| 848 | | -static enum ucode_state |
|---|
| 849 | | -load_microcode_amd(bool save, u8 family, const u8 *data, size_t size) |
|---|
| 849 | +static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) |
|---|
| 850 | 850 | { |
|---|
| 851 | + struct cpuinfo_x86 *c; |
|---|
| 852 | + unsigned int nid, cpu; |
|---|
| 851 | 853 | struct ucode_patch *p; |
|---|
| 852 | 854 | enum ucode_state ret; |
|---|
| 853 | 855 | |
|---|
| .. | .. |
|---|
| 860 | 862 | return ret; |
|---|
| 861 | 863 | } |
|---|
| 862 | 864 | |
|---|
| 863 | | - p = find_patch(0); |
|---|
| 864 | | - if (!p) { |
|---|
| 865 | | - return ret; |
|---|
| 866 | | - } else { |
|---|
| 867 | | - if (boot_cpu_data.microcode >= p->patch_id) |
|---|
| 868 | | - return ret; |
|---|
| 865 | + for_each_node(nid) { |
|---|
| 866 | + cpu = cpumask_first(cpumask_of_node(nid)); |
|---|
| 867 | + c = &cpu_data(cpu); |
|---|
| 868 | + |
|---|
| 869 | + p = find_patch(cpu); |
|---|
| 870 | + if (!p) |
|---|
| 871 | + continue; |
|---|
| 872 | + |
|---|
| 873 | + if (c->microcode >= p->patch_id) |
|---|
| 874 | + continue; |
|---|
| 869 | 875 | |
|---|
| 870 | 876 | ret = UCODE_NEW; |
|---|
| 877 | + |
|---|
| 878 | + memset(&amd_ucode_patch[nid], 0, PATCH_MAX_SIZE); |
|---|
| 879 | + memcpy(&amd_ucode_patch[nid], p->data, min_t(u32, p->size, PATCH_MAX_SIZE)); |
|---|
| 871 | 880 | } |
|---|
| 872 | | - |
|---|
| 873 | | - /* save BSP's matching patch for early load */ |
|---|
| 874 | | - if (!save) |
|---|
| 875 | | - return ret; |
|---|
| 876 | | - |
|---|
| 877 | | - memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); |
|---|
| 878 | | - memcpy(amd_ucode_patch, p->data, min_t(u32, p->size, PATCH_MAX_SIZE)); |
|---|
| 879 | 881 | |
|---|
| 880 | 882 | return ret; |
|---|
| 881 | 883 | } |
|---|
| .. | .. |
|---|
| 901 | 903 | { |
|---|
| 902 | 904 | char fw_name[36] = "amd-ucode/microcode_amd.bin"; |
|---|
| 903 | 905 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
|---|
| 904 | | - bool bsp = c->cpu_index == boot_cpu_data.cpu_index; |
|---|
| 905 | 906 | enum ucode_state ret = UCODE_NFOUND; |
|---|
| 906 | 907 | const struct firmware *fw; |
|---|
| 907 | 908 | |
|---|
| 908 | 909 | /* reload ucode container only on the boot cpu */ |
|---|
| 909 | | - if (!refresh_fw || !bsp) |
|---|
| 910 | + if (!refresh_fw) |
|---|
| 910 | 911 | return UCODE_OK; |
|---|
| 911 | 912 | |
|---|
| 912 | 913 | if (c->x86 >= 0x15) |
|---|
| .. | .. |
|---|
| 921 | 922 | if (!verify_container(fw->data, fw->size, false)) |
|---|
| 922 | 923 | goto fw_release; |
|---|
| 923 | 924 | |
|---|
| 924 | | - ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size); |
|---|
| 925 | + ret = load_microcode_amd(c->x86, fw->data, fw->size); |
|---|
| 925 | 926 | |
|---|
| 926 | 927 | fw_release: |
|---|
| 927 | 928 | release_firmware(fw); |
|---|