diff options
| -rw-r--r-- | Documentation/x86/early-microcode.txt | 25 | ||||
| -rw-r--r-- | arch/x86/Kconfig | 27 | ||||
| -rw-r--r-- | arch/x86/include/asm/microcode.h | 26 | ||||
| -rw-r--r-- | arch/x86/include/asm/microcode_intel.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 15 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 19 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 285 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_lib.c | 58 |
8 files changed, 253 insertions, 203 deletions
diff --git a/Documentation/x86/early-microcode.txt b/Documentation/x86/early-microcode.txt index d62bea6796da..c956d99cf1de 100644 --- a/Documentation/x86/early-microcode.txt +++ b/Documentation/x86/early-microcode.txt | |||
| @@ -40,3 +40,28 @@ cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin) | |||
| 40 | find . | cpio -o -H newc >../ucode.cpio | 40 | find . | cpio -o -H newc >../ucode.cpio |
| 41 | cd .. | 41 | cd .. |
| 42 | cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img | 42 | cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img |
| 43 | |||
| 44 | Builtin microcode | ||
| 45 | ================= | ||
| 46 | |||
| 47 | We can also load builtin microcode supplied through the regular firmware | ||
| 48 | builtin method CONFIG_FIRMWARE_IN_KERNEL. Here's an example: | ||
| 49 | |||
| 50 | CONFIG_FIRMWARE_IN_KERNEL=y | ||
| 51 | CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin" | ||
| 52 | CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware" | ||
| 53 | |||
| 54 | This basically means, you have the following tree structure locally: | ||
| 55 | |||
| 56 | /lib/firmware/ | ||
| 57 | |-- amd-ucode | ||
| 58 | ... | ||
| 59 | | |-- microcode_amd_fam15h.bin | ||
| 60 | ... | ||
| 61 | |-- intel-ucode | ||
| 62 | ... | ||
| 63 | | |-- 06-3a-09 | ||
| 64 | ... | ||
| 65 | |||
| 66 | so that the build system can find those files and integrate them into | ||
| 67 | the final kernel image. The early loader finds them and applies them. | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b1051057e5b0..8f2e6659281b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -1163,22 +1163,23 @@ config MICROCODE | |||
| 1163 | bool "CPU microcode loading support" | 1163 | bool "CPU microcode loading support" |
| 1164 | default y | 1164 | default y |
| 1165 | depends on CPU_SUP_AMD || CPU_SUP_INTEL | 1165 | depends on CPU_SUP_AMD || CPU_SUP_INTEL |
| 1166 | depends on BLK_DEV_INITRD | ||
| 1167 | select FW_LOADER | 1166 | select FW_LOADER |
| 1168 | ---help--- | 1167 | ---help--- |
| 1169 | |||
| 1170 | If you say Y here, you will be able to update the microcode on | 1168 | If you say Y here, you will be able to update the microcode on |
| 1171 | certain Intel and AMD processors. The Intel support is for the | 1169 | Intel and AMD processors. The Intel support is for the IA32 family, |
| 1172 | IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, | 1170 | e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The |
| 1173 | Xeon etc. The AMD support is for families 0x10 and later. You will | 1171 | AMD support is for families 0x10 and later. You will obviously need |
| 1174 | obviously need the actual microcode binary data itself which is not | 1172 | the actual microcode binary data itself which is not shipped with |
| 1175 | shipped with the Linux kernel. | 1173 | the Linux kernel. |
| 1176 | 1174 | ||
| 1177 | This option selects the general module only, you need to select | 1175 | The preferred method to load microcode from a detached initrd is described |
| 1178 | at least one vendor specific module as well. | 1176 | in Documentation/x86/early-microcode.txt. For that you need to enable |
| 1179 | 1177 | CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the | |
| 1180 | To compile this driver as a module, choose M here: the module | 1178 | initrd for microcode blobs. |
| 1181 | will be called microcode. | 1179 | |
| 1180 | In addition, you can build-in the microcode into the kernel. For that you | ||
| 1181 | need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied microcode | ||
| 1182 | to the CONFIG_EXTRA_FIRMWARE config option. | ||
| 1182 | 1183 | ||
| 1183 | config MICROCODE_INTEL | 1184 | config MICROCODE_INTEL |
| 1184 | bool "Intel microcode loading support" | 1185 | bool "Intel microcode loading support" |
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 1e1b07a5a738..9d3a96c4da78 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <asm/cpu.h> | 4 | #include <asm/cpu.h> |
| 5 | #include <linux/earlycpio.h> | 5 | #include <linux/earlycpio.h> |
| 6 | #include <linux/initrd.h> | ||
| 6 | 7 | ||
| 7 | #define native_rdmsr(msr, val1, val2) \ | 8 | #define native_rdmsr(msr, val1, val2) \ |
| 8 | do { \ | 9 | do { \ |
| @@ -143,4 +144,29 @@ static inline void reload_early_microcode(void) { } | |||
| 143 | static inline bool | 144 | static inline bool |
| 144 | get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } | 145 | get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } |
| 145 | #endif | 146 | #endif |
| 147 | |||
| 148 | static inline unsigned long get_initrd_start(void) | ||
| 149 | { | ||
| 150 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 151 | return initrd_start; | ||
| 152 | #else | ||
| 153 | return 0; | ||
| 154 | #endif | ||
| 155 | } | ||
| 156 | |||
| 157 | static inline unsigned long get_initrd_start_addr(void) | ||
| 158 | { | ||
| 159 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 160 | #ifdef CONFIG_X86_32 | ||
| 161 | unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); | ||
| 162 | |||
| 163 | return (unsigned long)__pa_nodebug(*initrd_start_p); | ||
| 164 | #else | ||
| 165 | return get_initrd_start(); | ||
| 166 | #endif | ||
| 167 | #else /* CONFIG_BLK_DEV_INITRD */ | ||
| 168 | return 0; | ||
| 169 | #endif | ||
| 170 | } | ||
| 171 | |||
| 146 | #endif /* _ASM_X86_MICROCODE_H */ | 172 | #endif /* _ASM_X86_MICROCODE_H */ |
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index 8559b0102ea1..603417f8dd6c 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h | |||
| @@ -40,7 +40,6 @@ struct extended_sigtable { | |||
| 40 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | 40 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) |
| 41 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) | 41 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) |
| 42 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) | 42 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) |
| 43 | #define DWSIZE (sizeof(u32)) | ||
| 44 | 43 | ||
| 45 | #define get_totalsize(mc) \ | 44 | #define get_totalsize(mc) \ |
| 46 | (((struct microcode_intel *)mc)->hdr.datasize ? \ | 45 | (((struct microcode_intel *)mc)->hdr.datasize ? \ |
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 75d3aab5f7b2..8581963894c7 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
| @@ -431,10 +431,6 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 431 | else | 431 | else |
| 432 | container = cont_va; | 432 | container = cont_va; |
| 433 | 433 | ||
| 434 | if (ucode_new_rev) | ||
| 435 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | ||
| 436 | ucode_new_rev); | ||
| 437 | |||
| 438 | eax = cpuid_eax(0x00000001); | 434 | eax = cpuid_eax(0x00000001); |
| 439 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | 435 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); |
| 440 | 436 | ||
| @@ -469,8 +465,7 @@ void reload_ucode_amd(void) | |||
| 469 | if (mc && rev < mc->hdr.patch_id) { | 465 | if (mc && rev < mc->hdr.patch_id) { |
| 470 | if (!__apply_microcode_amd(mc)) { | 466 | if (!__apply_microcode_amd(mc)) { |
| 471 | ucode_new_rev = mc->hdr.patch_id; | 467 | ucode_new_rev = mc->hdr.patch_id; |
| 472 | pr_info("microcode: reload patch_level=0x%08x\n", | 468 | pr_info("reload patch_level=0x%08x\n", ucode_new_rev); |
| 473 | ucode_new_rev); | ||
| 474 | } | 469 | } |
| 475 | } | 470 | } |
| 476 | } | 471 | } |
| @@ -793,15 +788,13 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover) | |||
| 793 | return -EINVAL; | 788 | return -EINVAL; |
| 794 | } | 789 | } |
| 795 | 790 | ||
| 796 | patch->data = kzalloc(patch_size, GFP_KERNEL); | 791 | patch->data = kmemdup(fw + SECTION_HDR_SIZE, patch_size, GFP_KERNEL); |
| 797 | if (!patch->data) { | 792 | if (!patch->data) { |
| 798 | pr_err("Patch data allocation failure.\n"); | 793 | pr_err("Patch data allocation failure.\n"); |
| 799 | kfree(patch); | 794 | kfree(patch); |
| 800 | return -EINVAL; | 795 | return -EINVAL; |
| 801 | } | 796 | } |
| 802 | 797 | ||
| 803 | /* All looks ok, copy patch... */ | ||
| 804 | memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size); | ||
| 805 | INIT_LIST_HEAD(&patch->plist); | 798 | INIT_LIST_HEAD(&patch->plist); |
| 806 | patch->patch_id = mc_hdr->patch_id; | 799 | patch->patch_id = mc_hdr->patch_id; |
| 807 | patch->equiv_cpu = proc_id; | 800 | patch->equiv_cpu = proc_id; |
| @@ -957,6 +950,10 @@ struct microcode_ops * __init init_amd_microcode(void) | |||
| 957 | return NULL; | 950 | return NULL; |
| 958 | } | 951 | } |
| 959 | 952 | ||
| 953 | if (ucode_new_rev) | ||
| 954 | pr_info_once("microcode updated early to new patch_level=0x%08x\n", | ||
| 955 | ucode_new_rev); | ||
| 956 | |||
| 960 | return µcode_amd_ops; | 957 | return µcode_amd_ops; |
| 961 | } | 958 | } |
| 962 | 959 | ||
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index faec7120c508..ac360bfbbdb6 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
| @@ -43,16 +43,8 @@ | |||
| 43 | #define MICROCODE_VERSION "2.01" | 43 | #define MICROCODE_VERSION "2.01" |
| 44 | 44 | ||
| 45 | static struct microcode_ops *microcode_ops; | 45 | static struct microcode_ops *microcode_ops; |
| 46 | |||
| 47 | static bool dis_ucode_ldr; | 46 | static bool dis_ucode_ldr; |
| 48 | 47 | ||
| 49 | static int __init disable_loader(char *str) | ||
| 50 | { | ||
| 51 | dis_ucode_ldr = true; | ||
| 52 | return 1; | ||
| 53 | } | ||
| 54 | __setup("dis_ucode_ldr", disable_loader); | ||
| 55 | |||
| 56 | /* | 48 | /* |
| 57 | * Synchronization. | 49 | * Synchronization. |
| 58 | * | 50 | * |
| @@ -81,15 +73,16 @@ struct cpu_info_ctx { | |||
| 81 | 73 | ||
| 82 | static bool __init check_loader_disabled_bsp(void) | 74 | static bool __init check_loader_disabled_bsp(void) |
| 83 | { | 75 | { |
| 76 | static const char *__dis_opt_str = "dis_ucode_ldr"; | ||
| 77 | |||
| 84 | #ifdef CONFIG_X86_32 | 78 | #ifdef CONFIG_X86_32 |
| 85 | const char *cmdline = (const char *)__pa_nodebug(boot_command_line); | 79 | const char *cmdline = (const char *)__pa_nodebug(boot_command_line); |
| 86 | const char *opt = "dis_ucode_ldr"; | 80 | const char *option = (const char *)__pa_nodebug(__dis_opt_str); |
| 87 | const char *option = (const char *)__pa_nodebug(opt); | ||
| 88 | bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr); | 81 | bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr); |
| 89 | 82 | ||
| 90 | #else /* CONFIG_X86_64 */ | 83 | #else /* CONFIG_X86_64 */ |
| 91 | const char *cmdline = boot_command_line; | 84 | const char *cmdline = boot_command_line; |
| 92 | const char *option = "dis_ucode_ldr"; | 85 | const char *option = __dis_opt_str; |
| 93 | bool *res = &dis_ucode_ldr; | 86 | bool *res = &dis_ucode_ldr; |
| 94 | #endif | 87 | #endif |
| 95 | 88 | ||
| @@ -479,7 +472,7 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) | |||
| 479 | enum ucode_state ustate; | 472 | enum ucode_state ustate; |
| 480 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 473 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| 481 | 474 | ||
| 482 | if (uci && uci->valid) | 475 | if (uci->valid) |
| 483 | return UCODE_OK; | 476 | return UCODE_OK; |
| 484 | 477 | ||
| 485 | if (collect_cpu_info(cpu)) | 478 | if (collect_cpu_info(cpu)) |
| @@ -630,7 +623,7 @@ int __init microcode_init(void) | |||
| 630 | struct cpuinfo_x86 *c = &boot_cpu_data; | 623 | struct cpuinfo_x86 *c = &boot_cpu_data; |
| 631 | int error; | 624 | int error; |
| 632 | 625 | ||
| 633 | if (paravirt_enabled() || dis_ucode_ldr) | 626 | if (dis_ucode_ldr) |
| 634 | return -EINVAL; | 627 | return -EINVAL; |
| 635 | 628 | ||
| 636 | if (c->x86_vendor == X86_VENDOR_INTEL) | 629 | if (c->x86_vendor == X86_VENDOR_INTEL) |
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index ee81c544ee0d..cbb3cf09b065 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c | |||
| @@ -39,9 +39,15 @@ | |||
| 39 | #include <asm/setup.h> | 39 | #include <asm/setup.h> |
| 40 | #include <asm/msr.h> | 40 | #include <asm/msr.h> |
| 41 | 41 | ||
| 42 | static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; | 42 | /* |
| 43 | * Temporary microcode blobs pointers storage. We note here the pointers to | ||
| 44 | * microcode blobs we've got from whatever storage (detached initrd, builtin). | ||
| 45 | * Later on, we put those into final storage mc_saved_data.mc_saved. | ||
| 46 | */ | ||
| 47 | static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT]; | ||
| 48 | |||
| 43 | static struct mc_saved_data { | 49 | static struct mc_saved_data { |
| 44 | unsigned int mc_saved_count; | 50 | unsigned int num_saved; |
| 45 | struct microcode_intel **mc_saved; | 51 | struct microcode_intel **mc_saved; |
| 46 | } mc_saved_data; | 52 | } mc_saved_data; |
| 47 | 53 | ||
| @@ -78,53 +84,50 @@ load_microcode_early(struct microcode_intel **saved, | |||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | static inline void | 86 | static inline void |
| 81 | copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd, | 87 | copy_ptrs(struct microcode_intel **mc_saved, unsigned long *mc_ptrs, |
| 82 | unsigned long off, int num_saved) | 88 | unsigned long off, int num_saved) |
| 83 | { | 89 | { |
| 84 | int i; | 90 | int i; |
| 85 | 91 | ||
| 86 | for (i = 0; i < num_saved; i++) | 92 | for (i = 0; i < num_saved; i++) |
| 87 | mc_saved[i] = (struct microcode_intel *)(initrd[i] + off); | 93 | mc_saved[i] = (struct microcode_intel *)(mc_ptrs[i] + off); |
| 88 | } | 94 | } |
| 89 | 95 | ||
| 90 | #ifdef CONFIG_X86_32 | 96 | #ifdef CONFIG_X86_32 |
| 91 | static void | 97 | static void |
| 92 | microcode_phys(struct microcode_intel **mc_saved_tmp, | 98 | microcode_phys(struct microcode_intel **mc_saved_tmp, struct mc_saved_data *mcs) |
| 93 | struct mc_saved_data *mc_saved_data) | ||
| 94 | { | 99 | { |
| 95 | int i; | 100 | int i; |
| 96 | struct microcode_intel ***mc_saved; | 101 | struct microcode_intel ***mc_saved; |
| 97 | 102 | ||
| 98 | mc_saved = (struct microcode_intel ***) | 103 | mc_saved = (struct microcode_intel ***)__pa_nodebug(&mcs->mc_saved); |
| 99 | __pa_nodebug(&mc_saved_data->mc_saved); | 104 | |
| 100 | for (i = 0; i < mc_saved_data->mc_saved_count; i++) { | 105 | for (i = 0; i < mcs->num_saved; i++) { |
| 101 | struct microcode_intel *p; | 106 | struct microcode_intel *p; |
| 102 | 107 | ||
| 103 | p = *(struct microcode_intel **) | 108 | p = *(struct microcode_intel **)__pa_nodebug(mcs->mc_saved + i); |
| 104 | __pa_nodebug(mc_saved_data->mc_saved + i); | ||
| 105 | mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p); | 109 | mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p); |
| 106 | } | 110 | } |
| 107 | } | 111 | } |
| 108 | #endif | 112 | #endif |
| 109 | 113 | ||
| 110 | static enum ucode_state | 114 | static enum ucode_state |
| 111 | load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | 115 | load_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
| 112 | unsigned long initrd_start, struct ucode_cpu_info *uci) | 116 | unsigned long offset, struct ucode_cpu_info *uci) |
| 113 | { | 117 | { |
| 114 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | 118 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
| 115 | unsigned int count = mc_saved_data->mc_saved_count; | 119 | unsigned int count = mcs->num_saved; |
| 116 | 120 | ||
| 117 | if (!mc_saved_data->mc_saved) { | 121 | if (!mcs->mc_saved) { |
| 118 | copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count); | 122 | copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count); |
| 119 | 123 | ||
| 120 | return load_microcode_early(mc_saved_tmp, count, uci); | 124 | return load_microcode_early(mc_saved_tmp, count, uci); |
| 121 | } else { | 125 | } else { |
| 122 | #ifdef CONFIG_X86_32 | 126 | #ifdef CONFIG_X86_32 |
| 123 | microcode_phys(mc_saved_tmp, mc_saved_data); | 127 | microcode_phys(mc_saved_tmp, mcs); |
| 124 | return load_microcode_early(mc_saved_tmp, count, uci); | 128 | return load_microcode_early(mc_saved_tmp, count, uci); |
| 125 | #else | 129 | #else |
| 126 | return load_microcode_early(mc_saved_data->mc_saved, | 130 | return load_microcode_early(mcs->mc_saved, count, uci); |
| 127 | count, uci); | ||
| 128 | #endif | 131 | #endif |
| 129 | } | 132 | } |
| 130 | } | 133 | } |
| @@ -175,25 +178,25 @@ matching_model_microcode(struct microcode_header_intel *mc_header, | |||
| 175 | } | 178 | } |
| 176 | 179 | ||
| 177 | static int | 180 | static int |
| 178 | save_microcode(struct mc_saved_data *mc_saved_data, | 181 | save_microcode(struct mc_saved_data *mcs, |
| 179 | struct microcode_intel **mc_saved_src, | 182 | struct microcode_intel **mc_saved_src, |
| 180 | unsigned int mc_saved_count) | 183 | unsigned int num_saved) |
| 181 | { | 184 | { |
| 182 | int i, j; | 185 | int i, j; |
| 183 | struct microcode_intel **saved_ptr; | 186 | struct microcode_intel **saved_ptr; |
| 184 | int ret; | 187 | int ret; |
| 185 | 188 | ||
| 186 | if (!mc_saved_count) | 189 | if (!num_saved) |
| 187 | return -EINVAL; | 190 | return -EINVAL; |
| 188 | 191 | ||
| 189 | /* | 192 | /* |
| 190 | * Copy new microcode data. | 193 | * Copy new microcode data. |
| 191 | */ | 194 | */ |
| 192 | saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL); | 195 | saved_ptr = kcalloc(num_saved, sizeof(struct microcode_intel *), GFP_KERNEL); |
| 193 | if (!saved_ptr) | 196 | if (!saved_ptr) |
| 194 | return -ENOMEM; | 197 | return -ENOMEM; |
| 195 | 198 | ||
| 196 | for (i = 0; i < mc_saved_count; i++) { | 199 | for (i = 0; i < num_saved; i++) { |
| 197 | struct microcode_header_intel *mc_hdr; | 200 | struct microcode_header_intel *mc_hdr; |
| 198 | struct microcode_intel *mc; | 201 | struct microcode_intel *mc; |
| 199 | unsigned long size; | 202 | unsigned long size; |
| @@ -207,20 +210,18 @@ save_microcode(struct mc_saved_data *mc_saved_data, | |||
| 207 | mc_hdr = &mc->hdr; | 210 | mc_hdr = &mc->hdr; |
| 208 | size = get_totalsize(mc_hdr); | 211 | size = get_totalsize(mc_hdr); |
| 209 | 212 | ||
| 210 | saved_ptr[i] = kmalloc(size, GFP_KERNEL); | 213 | saved_ptr[i] = kmemdup(mc, size, GFP_KERNEL); |
| 211 | if (!saved_ptr[i]) { | 214 | if (!saved_ptr[i]) { |
| 212 | ret = -ENOMEM; | 215 | ret = -ENOMEM; |
| 213 | goto err; | 216 | goto err; |
| 214 | } | 217 | } |
| 215 | |||
| 216 | memcpy(saved_ptr[i], mc, size); | ||
| 217 | } | 218 | } |
| 218 | 219 | ||
| 219 | /* | 220 | /* |
| 220 | * Point to newly saved microcode. | 221 | * Point to newly saved microcode. |
| 221 | */ | 222 | */ |
| 222 | mc_saved_data->mc_saved = saved_ptr; | 223 | mcs->mc_saved = saved_ptr; |
| 223 | mc_saved_data->mc_saved_count = mc_saved_count; | 224 | mcs->num_saved = num_saved; |
| 224 | 225 | ||
| 225 | return 0; | 226 | return 0; |
| 226 | 227 | ||
| @@ -284,22 +285,20 @@ static unsigned int _save_mc(struct microcode_intel **mc_saved, | |||
| 284 | * BSP can stay in the platform. | 285 | * BSP can stay in the platform. |
| 285 | */ | 286 | */ |
| 286 | static enum ucode_state __init | 287 | static enum ucode_state __init |
| 287 | get_matching_model_microcode(int cpu, unsigned long start, | 288 | get_matching_model_microcode(unsigned long start, void *data, size_t size, |
| 288 | void *data, size_t size, | 289 | struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
| 289 | struct mc_saved_data *mc_saved_data, | ||
| 290 | unsigned long *mc_saved_in_initrd, | ||
| 291 | struct ucode_cpu_info *uci) | 290 | struct ucode_cpu_info *uci) |
| 292 | { | 291 | { |
| 293 | u8 *ucode_ptr = data; | 292 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
| 294 | unsigned int leftover = size; | 293 | struct microcode_header_intel *mc_header; |
| 294 | unsigned int num_saved = mcs->num_saved; | ||
| 295 | enum ucode_state state = UCODE_OK; | 295 | enum ucode_state state = UCODE_OK; |
| 296 | unsigned int leftover = size; | ||
| 297 | u8 *ucode_ptr = data; | ||
| 296 | unsigned int mc_size; | 298 | unsigned int mc_size; |
| 297 | struct microcode_header_intel *mc_header; | ||
| 298 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | ||
| 299 | unsigned int mc_saved_count = mc_saved_data->mc_saved_count; | ||
| 300 | int i; | 299 | int i; |
| 301 | 300 | ||
| 302 | while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) { | 301 | while (leftover && num_saved < ARRAY_SIZE(mc_saved_tmp)) { |
| 303 | 302 | ||
| 304 | if (leftover < sizeof(mc_header)) | 303 | if (leftover < sizeof(mc_header)) |
| 305 | break; | 304 | break; |
| @@ -318,32 +317,31 @@ get_matching_model_microcode(int cpu, unsigned long start, | |||
| 318 | * the platform, we need to find and save microcode patches | 317 | * the platform, we need to find and save microcode patches |
| 319 | * with the same family and model as the BSP. | 318 | * with the same family and model as the BSP. |
| 320 | */ | 319 | */ |
| 321 | if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != | 320 | if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != UCODE_OK) { |
| 322 | UCODE_OK) { | ||
| 323 | ucode_ptr += mc_size; | 321 | ucode_ptr += mc_size; |
| 324 | continue; | 322 | continue; |
| 325 | } | 323 | } |
| 326 | 324 | ||
| 327 | mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count); | 325 | num_saved = _save_mc(mc_saved_tmp, ucode_ptr, num_saved); |
| 328 | 326 | ||
| 329 | ucode_ptr += mc_size; | 327 | ucode_ptr += mc_size; |
| 330 | } | 328 | } |
| 331 | 329 | ||
| 332 | if (leftover) { | 330 | if (leftover) { |
| 333 | state = UCODE_ERROR; | 331 | state = UCODE_ERROR; |
| 334 | goto out; | 332 | return state; |
| 335 | } | 333 | } |
| 336 | 334 | ||
| 337 | if (mc_saved_count == 0) { | 335 | if (!num_saved) { |
| 338 | state = UCODE_NFOUND; | 336 | state = UCODE_NFOUND; |
| 339 | goto out; | 337 | return state; |
| 340 | } | 338 | } |
| 341 | 339 | ||
| 342 | for (i = 0; i < mc_saved_count; i++) | 340 | for (i = 0; i < num_saved; i++) |
| 343 | mc_saved_in_initrd[i] = (unsigned long)mc_saved_tmp[i] - start; | 341 | mc_ptrs[i] = (unsigned long)mc_saved_tmp[i] - start; |
| 342 | |||
| 343 | mcs->num_saved = num_saved; | ||
| 344 | 344 | ||
| 345 | mc_saved_data->mc_saved_count = mc_saved_count; | ||
| 346 | out: | ||
| 347 | return state; | 345 | return state; |
| 348 | } | 346 | } |
| 349 | 347 | ||
| @@ -373,7 +371,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) | |||
| 373 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | 371 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); |
| 374 | csig.pf = 1 << ((val[1] >> 18) & 7); | 372 | csig.pf = 1 << ((val[1] >> 18) & 7); |
| 375 | } | 373 | } |
| 376 | native_wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 374 | native_wrmsrl(MSR_IA32_UCODE_REV, 0); |
| 377 | 375 | ||
| 378 | /* As documented in the SDM: Do a CPUID 1 here */ | 376 | /* As documented in the SDM: Do a CPUID 1 here */ |
| 379 | sync_core(); | 377 | sync_core(); |
| @@ -396,11 +394,11 @@ static void show_saved_mc(void) | |||
| 396 | unsigned int sig, pf, rev, total_size, data_size, date; | 394 | unsigned int sig, pf, rev, total_size, data_size, date; |
| 397 | struct ucode_cpu_info uci; | 395 | struct ucode_cpu_info uci; |
| 398 | 396 | ||
| 399 | if (mc_saved_data.mc_saved_count == 0) { | 397 | if (!mc_saved_data.num_saved) { |
| 400 | pr_debug("no microcode data saved.\n"); | 398 | pr_debug("no microcode data saved.\n"); |
| 401 | return; | 399 | return; |
| 402 | } | 400 | } |
| 403 | pr_debug("Total microcode saved: %d\n", mc_saved_data.mc_saved_count); | 401 | pr_debug("Total microcode saved: %d\n", mc_saved_data.num_saved); |
| 404 | 402 | ||
| 405 | collect_cpu_info_early(&uci); | 403 | collect_cpu_info_early(&uci); |
| 406 | 404 | ||
| @@ -409,7 +407,7 @@ static void show_saved_mc(void) | |||
| 409 | rev = uci.cpu_sig.rev; | 407 | rev = uci.cpu_sig.rev; |
| 410 | pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev); | 408 | pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev); |
| 411 | 409 | ||
| 412 | for (i = 0; i < mc_saved_data.mc_saved_count; i++) { | 410 | for (i = 0; i < mc_saved_data.num_saved; i++) { |
| 413 | struct microcode_header_intel *mc_saved_header; | 411 | struct microcode_header_intel *mc_saved_header; |
| 414 | struct extended_sigtable *ext_header; | 412 | struct extended_sigtable *ext_header; |
| 415 | int ext_sigcount; | 413 | int ext_sigcount; |
| @@ -465,7 +463,7 @@ int save_mc_for_early(u8 *mc) | |||
| 465 | { | 463 | { |
| 466 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | 464 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
| 467 | unsigned int mc_saved_count_init; | 465 | unsigned int mc_saved_count_init; |
| 468 | unsigned int mc_saved_count; | 466 | unsigned int num_saved; |
| 469 | struct microcode_intel **mc_saved; | 467 | struct microcode_intel **mc_saved; |
| 470 | int ret = 0; | 468 | int ret = 0; |
| 471 | int i; | 469 | int i; |
| @@ -476,23 +474,23 @@ int save_mc_for_early(u8 *mc) | |||
| 476 | */ | 474 | */ |
| 477 | mutex_lock(&x86_cpu_microcode_mutex); | 475 | mutex_lock(&x86_cpu_microcode_mutex); |
| 478 | 476 | ||
| 479 | mc_saved_count_init = mc_saved_data.mc_saved_count; | 477 | mc_saved_count_init = mc_saved_data.num_saved; |
| 480 | mc_saved_count = mc_saved_data.mc_saved_count; | 478 | num_saved = mc_saved_data.num_saved; |
| 481 | mc_saved = mc_saved_data.mc_saved; | 479 | mc_saved = mc_saved_data.mc_saved; |
| 482 | 480 | ||
| 483 | if (mc_saved && mc_saved_count) | 481 | if (mc_saved && num_saved) |
| 484 | memcpy(mc_saved_tmp, mc_saved, | 482 | memcpy(mc_saved_tmp, mc_saved, |
| 485 | mc_saved_count * sizeof(struct microcode_intel *)); | 483 | num_saved * sizeof(struct microcode_intel *)); |
| 486 | /* | 484 | /* |
| 487 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer | 485 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer |
| 488 | * version. | 486 | * version. |
| 489 | */ | 487 | */ |
| 490 | mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count); | 488 | num_saved = _save_mc(mc_saved_tmp, mc, num_saved); |
| 491 | 489 | ||
| 492 | /* | 490 | /* |
| 493 | * Save the mc_save_tmp in global mc_saved_data. | 491 | * Save the mc_save_tmp in global mc_saved_data. |
| 494 | */ | 492 | */ |
| 495 | ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count); | 493 | ret = save_microcode(&mc_saved_data, mc_saved_tmp, num_saved); |
| 496 | if (ret) { | 494 | if (ret) { |
| 497 | pr_err("Cannot save microcode patch.\n"); | 495 | pr_err("Cannot save microcode patch.\n"); |
| 498 | goto out; | 496 | goto out; |
| @@ -536,7 +534,7 @@ static bool __init load_builtin_intel_microcode(struct cpio_data *cp) | |||
| 536 | 534 | ||
| 537 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; | 535 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; |
| 538 | static __init enum ucode_state | 536 | static __init enum ucode_state |
| 539 | scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | 537 | scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
| 540 | unsigned long start, unsigned long size, | 538 | unsigned long start, unsigned long size, |
| 541 | struct ucode_cpu_info *uci) | 539 | struct ucode_cpu_info *uci) |
| 542 | { | 540 | { |
| @@ -551,14 +549,18 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | |||
| 551 | cd.data = NULL; | 549 | cd.data = NULL; |
| 552 | cd.size = 0; | 550 | cd.size = 0; |
| 553 | 551 | ||
| 554 | cd = find_cpio_data(p, (void *)start, size, &offset); | 552 | /* try built-in microcode if no initrd */ |
| 555 | if (!cd.data) { | 553 | if (!size) { |
| 556 | if (!load_builtin_intel_microcode(&cd)) | 554 | if (!load_builtin_intel_microcode(&cd)) |
| 557 | return UCODE_ERROR; | 555 | return UCODE_ERROR; |
| 556 | } else { | ||
| 557 | cd = find_cpio_data(p, (void *)start, size, &offset); | ||
| 558 | if (!cd.data) | ||
| 559 | return UCODE_ERROR; | ||
| 558 | } | 560 | } |
| 559 | 561 | ||
| 560 | return get_matching_model_microcode(0, start, cd.data, cd.size, | 562 | return get_matching_model_microcode(start, cd.data, cd.size, |
| 561 | mc_saved_data, initrd, uci); | 563 | mcs, mc_ptrs, uci); |
| 562 | } | 564 | } |
| 563 | 565 | ||
| 564 | /* | 566 | /* |
| @@ -567,14 +569,11 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | |||
| 567 | static void | 569 | static void |
| 568 | print_ucode_info(struct ucode_cpu_info *uci, unsigned int date) | 570 | print_ucode_info(struct ucode_cpu_info *uci, unsigned int date) |
| 569 | { | 571 | { |
| 570 | int cpu = smp_processor_id(); | 572 | pr_info_once("microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n", |
| 571 | 573 | uci->cpu_sig.rev, | |
| 572 | pr_info("CPU%d microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n", | 574 | date & 0xffff, |
| 573 | cpu, | 575 | date >> 24, |
| 574 | uci->cpu_sig.rev, | 576 | (date >> 16) & 0xff); |
| 575 | date & 0xffff, | ||
| 576 | date >> 24, | ||
| 577 | (date >> 16) & 0xff); | ||
| 578 | } | 577 | } |
| 579 | 578 | ||
| 580 | #ifdef CONFIG_X86_32 | 579 | #ifdef CONFIG_X86_32 |
| @@ -603,19 +602,19 @@ void show_ucode_info_early(void) | |||
| 603 | */ | 602 | */ |
| 604 | static void print_ucode(struct ucode_cpu_info *uci) | 603 | static void print_ucode(struct ucode_cpu_info *uci) |
| 605 | { | 604 | { |
| 606 | struct microcode_intel *mc_intel; | 605 | struct microcode_intel *mc; |
| 607 | int *delay_ucode_info_p; | 606 | int *delay_ucode_info_p; |
| 608 | int *current_mc_date_p; | 607 | int *current_mc_date_p; |
| 609 | 608 | ||
| 610 | mc_intel = uci->mc; | 609 | mc = uci->mc; |
| 611 | if (mc_intel == NULL) | 610 | if (!mc) |
| 612 | return; | 611 | return; |
| 613 | 612 | ||
| 614 | delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info); | 613 | delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info); |
| 615 | current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date); | 614 | current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date); |
| 616 | 615 | ||
| 617 | *delay_ucode_info_p = 1; | 616 | *delay_ucode_info_p = 1; |
| 618 | *current_mc_date_p = mc_intel->hdr.date; | 617 | *current_mc_date_p = mc->hdr.date; |
| 619 | } | 618 | } |
| 620 | #else | 619 | #else |
| 621 | 620 | ||
| @@ -630,37 +629,35 @@ static inline void flush_tlb_early(void) | |||
| 630 | 629 | ||
| 631 | static inline void print_ucode(struct ucode_cpu_info *uci) | 630 | static inline void print_ucode(struct ucode_cpu_info *uci) |
| 632 | { | 631 | { |
| 633 | struct microcode_intel *mc_intel; | 632 | struct microcode_intel *mc; |
| 634 | 633 | ||
| 635 | mc_intel = uci->mc; | 634 | mc = uci->mc; |
| 636 | if (mc_intel == NULL) | 635 | if (!mc) |
| 637 | return; | 636 | return; |
| 638 | 637 | ||
| 639 | print_ucode_info(uci, mc_intel->hdr.date); | 638 | print_ucode_info(uci, mc->hdr.date); |
| 640 | } | 639 | } |
| 641 | #endif | 640 | #endif |
| 642 | 641 | ||
| 643 | static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) | 642 | static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) |
| 644 | { | 643 | { |
| 645 | struct microcode_intel *mc_intel; | 644 | struct microcode_intel *mc; |
| 646 | unsigned int val[2]; | 645 | unsigned int val[2]; |
| 647 | 646 | ||
| 648 | mc_intel = uci->mc; | 647 | mc = uci->mc; |
| 649 | if (mc_intel == NULL) | 648 | if (!mc) |
| 650 | return 0; | 649 | return 0; |
| 651 | 650 | ||
| 652 | /* write microcode via MSR 0x79 */ | 651 | /* write microcode via MSR 0x79 */ |
| 653 | native_wrmsr(MSR_IA32_UCODE_WRITE, | 652 | native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); |
| 654 | (unsigned long) mc_intel->bits, | 653 | native_wrmsrl(MSR_IA32_UCODE_REV, 0); |
| 655 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
| 656 | native_wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 657 | 654 | ||
| 658 | /* As documented in the SDM: Do a CPUID 1 here */ | 655 | /* As documented in the SDM: Do a CPUID 1 here */ |
| 659 | sync_core(); | 656 | sync_core(); |
| 660 | 657 | ||
| 661 | /* get the current revision from MSR 0x8B */ | 658 | /* get the current revision from MSR 0x8B */ |
| 662 | native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | 659 | native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); |
| 663 | if (val[1] != mc_intel->hdr.rev) | 660 | if (val[1] != mc->hdr.rev) |
| 664 | return -1; | 661 | return -1; |
| 665 | 662 | ||
| 666 | #ifdef CONFIG_X86_64 | 663 | #ifdef CONFIG_X86_64 |
| @@ -672,25 +669,26 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) | |||
| 672 | if (early) | 669 | if (early) |
| 673 | print_ucode(uci); | 670 | print_ucode(uci); |
| 674 | else | 671 | else |
| 675 | print_ucode_info(uci, mc_intel->hdr.date); | 672 | print_ucode_info(uci, mc->hdr.date); |
| 676 | 673 | ||
| 677 | return 0; | 674 | return 0; |
| 678 | } | 675 | } |
| 679 | 676 | ||
| 680 | /* | 677 | /* |
| 681 | * This function converts microcode patch offsets previously stored in | 678 | * This function converts microcode patch offsets previously stored in |
| 682 | * mc_saved_in_initrd to pointers and stores the pointers in mc_saved_data. | 679 | * mc_tmp_ptrs to pointers and stores the pointers in mc_saved_data. |
| 683 | */ | 680 | */ |
| 684 | int __init save_microcode_in_initrd_intel(void) | 681 | int __init save_microcode_in_initrd_intel(void) |
| 685 | { | 682 | { |
| 686 | unsigned int count = mc_saved_data.mc_saved_count; | 683 | unsigned int count = mc_saved_data.num_saved; |
| 687 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; | 684 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; |
| 688 | int ret = 0; | 685 | int ret = 0; |
| 689 | 686 | ||
| 690 | if (count == 0) | 687 | if (!count) |
| 691 | return ret; | 688 | return ret; |
| 692 | 689 | ||
| 693 | copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count); | 690 | copy_ptrs(mc_saved, mc_tmp_ptrs, get_initrd_start(), count); |
| 691 | |||
| 694 | ret = save_microcode(&mc_saved_data, mc_saved, count); | 692 | ret = save_microcode(&mc_saved_data, mc_saved, count); |
| 695 | if (ret) | 693 | if (ret) |
| 696 | pr_err("Cannot save microcode patches from initrd.\n"); | 694 | pr_err("Cannot save microcode patches from initrd.\n"); |
| @@ -701,8 +699,7 @@ int __init save_microcode_in_initrd_intel(void) | |||
| 701 | } | 699 | } |
| 702 | 700 | ||
| 703 | static void __init | 701 | static void __init |
| 704 | _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | 702 | _load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
| 705 | unsigned long *initrd, | ||
| 706 | unsigned long start, unsigned long size) | 703 | unsigned long start, unsigned long size) |
| 707 | { | 704 | { |
| 708 | struct ucode_cpu_info uci; | 705 | struct ucode_cpu_info uci; |
| @@ -710,11 +707,11 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | |||
| 710 | 707 | ||
| 711 | collect_cpu_info_early(&uci); | 708 | collect_cpu_info_early(&uci); |
| 712 | 709 | ||
| 713 | ret = scan_microcode(mc_saved_data, initrd, start, size, &uci); | 710 | ret = scan_microcode(mcs, mc_ptrs, start, size, &uci); |
| 714 | if (ret != UCODE_OK) | 711 | if (ret != UCODE_OK) |
| 715 | return; | 712 | return; |
| 716 | 713 | ||
| 717 | ret = load_microcode(mc_saved_data, initrd, start, &uci); | 714 | ret = load_microcode(mcs, mc_ptrs, start, &uci); |
| 718 | if (ret != UCODE_OK) | 715 | if (ret != UCODE_OK) |
| 719 | return; | 716 | return; |
| 720 | 717 | ||
| @@ -728,53 +725,49 @@ void __init load_ucode_intel_bsp(void) | |||
| 728 | struct boot_params *p; | 725 | struct boot_params *p; |
| 729 | 726 | ||
| 730 | p = (struct boot_params *)__pa_nodebug(&boot_params); | 727 | p = (struct boot_params *)__pa_nodebug(&boot_params); |
| 731 | start = p->hdr.ramdisk_image; | ||
| 732 | size = p->hdr.ramdisk_size; | 728 | size = p->hdr.ramdisk_size; |
| 733 | 729 | ||
| 734 | _load_ucode_intel_bsp( | 730 | /* |
| 735 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | 731 | * Set start only if we have an initrd image. We cannot use initrd_start |
| 736 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), | 732 | * because it is not set that early yet. |
| 737 | start, size); | 733 | */ |
| 734 | start = (size ? p->hdr.ramdisk_image : 0); | ||
| 735 | |||
| 736 | _load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | ||
| 737 | (unsigned long *)__pa_nodebug(&mc_tmp_ptrs), | ||
| 738 | start, size); | ||
| 738 | #else | 739 | #else |
| 739 | start = boot_params.hdr.ramdisk_image + PAGE_OFFSET; | ||
| 740 | size = boot_params.hdr.ramdisk_size; | 740 | size = boot_params.hdr.ramdisk_size; |
| 741 | start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0); | ||
| 741 | 742 | ||
| 742 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size); | 743 | _load_ucode_intel_bsp(&mc_saved_data, mc_tmp_ptrs, start, size); |
| 743 | #endif | 744 | #endif |
| 744 | } | 745 | } |
| 745 | 746 | ||
| 746 | void load_ucode_intel_ap(void) | 747 | void load_ucode_intel_ap(void) |
| 747 | { | 748 | { |
| 748 | struct mc_saved_data *mc_saved_data_p; | 749 | unsigned long *mcs_tmp_p; |
| 750 | struct mc_saved_data *mcs_p; | ||
| 749 | struct ucode_cpu_info uci; | 751 | struct ucode_cpu_info uci; |
| 750 | unsigned long *mc_saved_in_initrd_p; | ||
| 751 | unsigned long initrd_start_addr; | ||
| 752 | enum ucode_state ret; | 752 | enum ucode_state ret; |
| 753 | #ifdef CONFIG_X86_32 | 753 | #ifdef CONFIG_X86_32 |
| 754 | unsigned long *initrd_start_p; | ||
| 755 | 754 | ||
| 756 | mc_saved_in_initrd_p = | 755 | mcs_tmp_p = (unsigned long *)__pa_nodebug(mc_tmp_ptrs); |
| 757 | (unsigned long *)__pa_nodebug(mc_saved_in_initrd); | 756 | mcs_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); |
| 758 | mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); | ||
| 759 | initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); | ||
| 760 | initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p); | ||
| 761 | #else | 757 | #else |
| 762 | mc_saved_data_p = &mc_saved_data; | 758 | mcs_tmp_p = mc_tmp_ptrs; |
| 763 | mc_saved_in_initrd_p = mc_saved_in_initrd; | 759 | mcs_p = &mc_saved_data; |
| 764 | initrd_start_addr = initrd_start; | ||
| 765 | #endif | 760 | #endif |
| 766 | 761 | ||
| 767 | /* | 762 | /* |
| 768 | * If there is no valid ucode previously saved in memory, no need to | 763 | * If there is no valid ucode previously saved in memory, no need to |
| 769 | * update ucode on this AP. | 764 | * update ucode on this AP. |
| 770 | */ | 765 | */ |
| 771 | if (mc_saved_data_p->mc_saved_count == 0) | 766 | if (!mcs_p->num_saved) |
| 772 | return; | 767 | return; |
| 773 | 768 | ||
| 774 | collect_cpu_info_early(&uci); | 769 | collect_cpu_info_early(&uci); |
| 775 | ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, | 770 | ret = load_microcode(mcs_p, mcs_tmp_p, get_initrd_start_addr(), &uci); |
| 776 | initrd_start_addr, &uci); | ||
| 777 | |||
| 778 | if (ret != UCODE_OK) | 771 | if (ret != UCODE_OK) |
| 779 | return; | 772 | return; |
| 780 | 773 | ||
| @@ -786,13 +779,13 @@ void reload_ucode_intel(void) | |||
| 786 | struct ucode_cpu_info uci; | 779 | struct ucode_cpu_info uci; |
| 787 | enum ucode_state ret; | 780 | enum ucode_state ret; |
| 788 | 781 | ||
| 789 | if (!mc_saved_data.mc_saved_count) | 782 | if (!mc_saved_data.num_saved) |
| 790 | return; | 783 | return; |
| 791 | 784 | ||
| 792 | collect_cpu_info_early(&uci); | 785 | collect_cpu_info_early(&uci); |
| 793 | 786 | ||
| 794 | ret = load_microcode_early(mc_saved_data.mc_saved, | 787 | ret = load_microcode_early(mc_saved_data.mc_saved, |
| 795 | mc_saved_data.mc_saved_count, &uci); | 788 | mc_saved_data.num_saved, &uci); |
| 796 | if (ret != UCODE_OK) | 789 | if (ret != UCODE_OK) |
| 797 | return; | 790 | return; |
| 798 | 791 | ||
| @@ -825,7 +818,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
| 825 | * return 0 - no update found | 818 | * return 0 - no update found |
| 826 | * return 1 - found update | 819 | * return 1 - found update |
| 827 | */ | 820 | */ |
| 828 | static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) | 821 | static int get_matching_mc(struct microcode_intel *mc, int cpu) |
| 829 | { | 822 | { |
| 830 | struct cpu_signature cpu_sig; | 823 | struct cpu_signature cpu_sig; |
| 831 | unsigned int csig, cpf, crev; | 824 | unsigned int csig, cpf, crev; |
| @@ -836,39 +829,36 @@ static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) | |||
| 836 | cpf = cpu_sig.pf; | 829 | cpf = cpu_sig.pf; |
| 837 | crev = cpu_sig.rev; | 830 | crev = cpu_sig.rev; |
| 838 | 831 | ||
| 839 | return has_newer_microcode(mc_intel, csig, cpf, crev); | 832 | return has_newer_microcode(mc, csig, cpf, crev); |
| 840 | } | 833 | } |
| 841 | 834 | ||
| 842 | static int apply_microcode_intel(int cpu) | 835 | static int apply_microcode_intel(int cpu) |
| 843 | { | 836 | { |
| 844 | struct microcode_intel *mc_intel; | 837 | struct microcode_intel *mc; |
| 845 | struct ucode_cpu_info *uci; | 838 | struct ucode_cpu_info *uci; |
| 839 | struct cpuinfo_x86 *c; | ||
| 846 | unsigned int val[2]; | 840 | unsigned int val[2]; |
| 847 | int cpu_num = raw_smp_processor_id(); | ||
| 848 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
| 849 | |||
| 850 | uci = ucode_cpu_info + cpu; | ||
| 851 | mc_intel = uci->mc; | ||
| 852 | 841 | ||
| 853 | /* We should bind the task to the CPU */ | 842 | /* We should bind the task to the CPU */ |
| 854 | BUG_ON(cpu_num != cpu); | 843 | if (WARN_ON(raw_smp_processor_id() != cpu)) |
| 844 | return -1; | ||
| 855 | 845 | ||
| 856 | if (mc_intel == NULL) | 846 | uci = ucode_cpu_info + cpu; |
| 847 | mc = uci->mc; | ||
| 848 | if (!mc) | ||
| 857 | return 0; | 849 | return 0; |
| 858 | 850 | ||
| 859 | /* | 851 | /* |
| 860 | * Microcode on this CPU could be updated earlier. Only apply the | 852 | * Microcode on this CPU could be updated earlier. Only apply the |
| 861 | * microcode patch in mc_intel when it is newer than the one on this | 853 | * microcode patch in mc when it is newer than the one on this |
| 862 | * CPU. | 854 | * CPU. |
| 863 | */ | 855 | */ |
| 864 | if (get_matching_mc(mc_intel, cpu) == 0) | 856 | if (!get_matching_mc(mc, cpu)) |
| 865 | return 0; | 857 | return 0; |
| 866 | 858 | ||
| 867 | /* write microcode via MSR 0x79 */ | 859 | /* write microcode via MSR 0x79 */ |
| 868 | wrmsr(MSR_IA32_UCODE_WRITE, | 860 | wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); |
| 869 | (unsigned long) mc_intel->bits, | 861 | wrmsrl(MSR_IA32_UCODE_REV, 0); |
| 870 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
| 871 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 872 | 862 | ||
| 873 | /* As documented in the SDM: Do a CPUID 1 here */ | 863 | /* As documented in the SDM: Do a CPUID 1 here */ |
| 874 | sync_core(); | 864 | sync_core(); |
| @@ -876,16 +866,19 @@ static int apply_microcode_intel(int cpu) | |||
| 876 | /* get the current revision from MSR 0x8B */ | 866 | /* get the current revision from MSR 0x8B */ |
| 877 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | 867 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); |
| 878 | 868 | ||
| 879 | if (val[1] != mc_intel->hdr.rev) { | 869 | if (val[1] != mc->hdr.rev) { |
| 880 | pr_err("CPU%d update to revision 0x%x failed\n", | 870 | pr_err("CPU%d update to revision 0x%x failed\n", |
| 881 | cpu_num, mc_intel->hdr.rev); | 871 | cpu, mc->hdr.rev); |
| 882 | return -1; | 872 | return -1; |
| 883 | } | 873 | } |
| 874 | |||
| 884 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", | 875 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", |
| 885 | cpu_num, val[1], | 876 | cpu, val[1], |
| 886 | mc_intel->hdr.date & 0xffff, | 877 | mc->hdr.date & 0xffff, |
| 887 | mc_intel->hdr.date >> 24, | 878 | mc->hdr.date >> 24, |
| 888 | (mc_intel->hdr.date >> 16) & 0xff); | 879 | (mc->hdr.date >> 16) & 0xff); |
| 880 | |||
| 881 | c = &cpu_data(cpu); | ||
| 889 | 882 | ||
| 890 | uci->cpu_sig.rev = val[1]; | 883 | uci->cpu_sig.rev = val[1]; |
| 891 | c->microcode = val[1]; | 884 | c->microcode = val[1]; |
diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index b96896bcbdaf..2ce1a7dc45b7 100644 --- a/arch/x86/kernel/cpu/microcode/intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c | |||
| @@ -49,7 +49,7 @@ int microcode_sanity_check(void *mc, int print_err) | |||
| 49 | unsigned long total_size, data_size, ext_table_size; | 49 | unsigned long total_size, data_size, ext_table_size; |
| 50 | struct microcode_header_intel *mc_header = mc; | 50 | struct microcode_header_intel *mc_header = mc; |
| 51 | struct extended_sigtable *ext_header = NULL; | 51 | struct extended_sigtable *ext_header = NULL; |
| 52 | int sum, orig_sum, ext_sigcount = 0, i; | 52 | u32 sum, orig_sum, ext_sigcount = 0, i; |
| 53 | struct extended_signature *ext_sig; | 53 | struct extended_signature *ext_sig; |
| 54 | 54 | ||
| 55 | total_size = get_totalsize(mc_header); | 55 | total_size = get_totalsize(mc_header); |
| @@ -57,69 +57,85 @@ int microcode_sanity_check(void *mc, int print_err) | |||
| 57 | 57 | ||
| 58 | if (data_size + MC_HEADER_SIZE > total_size) { | 58 | if (data_size + MC_HEADER_SIZE > total_size) { |
| 59 | if (print_err) | 59 | if (print_err) |
| 60 | pr_err("error! Bad data size in microcode data file\n"); | 60 | pr_err("Error: bad microcode data file size.\n"); |
| 61 | return -EINVAL; | 61 | return -EINVAL; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { | 64 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { |
| 65 | if (print_err) | 65 | if (print_err) |
| 66 | pr_err("error! Unknown microcode update format\n"); | 66 | pr_err("Error: invalid/unknown microcode update format.\n"); |
| 67 | return -EINVAL; | 67 | return -EINVAL; |
| 68 | } | 68 | } |
| 69 | |||
| 69 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | 70 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); |
| 70 | if (ext_table_size) { | 71 | if (ext_table_size) { |
| 72 | u32 ext_table_sum = 0; | ||
| 73 | u32 *ext_tablep; | ||
| 74 | |||
| 71 | if ((ext_table_size < EXT_HEADER_SIZE) | 75 | if ((ext_table_size < EXT_HEADER_SIZE) |
| 72 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { | 76 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { |
| 73 | if (print_err) | 77 | if (print_err) |
| 74 | pr_err("error! Small exttable size in microcode data file\n"); | 78 | pr_err("Error: truncated extended signature table.\n"); |
| 75 | return -EINVAL; | 79 | return -EINVAL; |
| 76 | } | 80 | } |
| 81 | |||
| 77 | ext_header = mc + MC_HEADER_SIZE + data_size; | 82 | ext_header = mc + MC_HEADER_SIZE + data_size; |
| 78 | if (ext_table_size != exttable_size(ext_header)) { | 83 | if (ext_table_size != exttable_size(ext_header)) { |
| 79 | if (print_err) | 84 | if (print_err) |
| 80 | pr_err("error! Bad exttable size in microcode data file\n"); | 85 | pr_err("Error: extended signature table size mismatch.\n"); |
| 81 | return -EFAULT; | 86 | return -EFAULT; |
| 82 | } | 87 | } |
| 88 | |||
| 83 | ext_sigcount = ext_header->count; | 89 | ext_sigcount = ext_header->count; |
| 84 | } | ||
| 85 | 90 | ||
| 86 | /* check extended table checksum */ | 91 | /* |
| 87 | if (ext_table_size) { | 92 | * Check extended table checksum: the sum of all dwords that |
| 88 | int ext_table_sum = 0; | 93 | * comprise a valid table must be 0. |
| 89 | int *ext_tablep = (int *)ext_header; | 94 | */ |
| 95 | ext_tablep = (u32 *)ext_header; | ||
| 90 | 96 | ||
| 91 | i = ext_table_size / DWSIZE; | 97 | i = ext_table_size / sizeof(u32); |
| 92 | while (i--) | 98 | while (i--) |
| 93 | ext_table_sum += ext_tablep[i]; | 99 | ext_table_sum += ext_tablep[i]; |
| 100 | |||
| 94 | if (ext_table_sum) { | 101 | if (ext_table_sum) { |
| 95 | if (print_err) | 102 | if (print_err) |
| 96 | pr_warn("aborting, bad extended signature table checksum\n"); | 103 | pr_warn("Bad extended signature table checksum, aborting.\n"); |
| 97 | return -EINVAL; | 104 | return -EINVAL; |
| 98 | } | 105 | } |
| 99 | } | 106 | } |
| 100 | 107 | ||
| 101 | /* calculate the checksum */ | 108 | /* |
| 109 | * Calculate the checksum of update data and header. The checksum of | ||
| 110 | * valid update data and header including the extended signature table | ||
| 111 | * must be 0. | ||
| 112 | */ | ||
| 102 | orig_sum = 0; | 113 | orig_sum = 0; |
| 103 | i = (MC_HEADER_SIZE + data_size) / DWSIZE; | 114 | i = (MC_HEADER_SIZE + data_size) / sizeof(u32); |
| 104 | while (i--) | 115 | while (i--) |
| 105 | orig_sum += ((int *)mc)[i]; | 116 | orig_sum += ((u32 *)mc)[i]; |
| 117 | |||
| 106 | if (orig_sum) { | 118 | if (orig_sum) { |
| 107 | if (print_err) | 119 | if (print_err) |
| 108 | pr_err("aborting, bad checksum\n"); | 120 | pr_err("Bad microcode data checksum, aborting.\n"); |
| 109 | return -EINVAL; | 121 | return -EINVAL; |
| 110 | } | 122 | } |
| 123 | |||
| 111 | if (!ext_table_size) | 124 | if (!ext_table_size) |
| 112 | return 0; | 125 | return 0; |
| 113 | /* check extended signature checksum */ | 126 | |
| 127 | /* | ||
| 128 | * Check extended signature checksum: 0 => valid. | ||
| 129 | */ | ||
| 114 | for (i = 0; i < ext_sigcount; i++) { | 130 | for (i = 0; i < ext_sigcount; i++) { |
| 115 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + | 131 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + |
| 116 | EXT_SIGNATURE_SIZE * i; | 132 | EXT_SIGNATURE_SIZE * i; |
| 117 | sum = orig_sum | 133 | |
| 118 | - (mc_header->sig + mc_header->pf + mc_header->cksum) | 134 | sum = (mc_header->sig + mc_header->pf + mc_header->cksum) - |
| 119 | + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); | 135 | (ext_sig->sig + ext_sig->pf + ext_sig->cksum); |
| 120 | if (sum) { | 136 | if (sum) { |
| 121 | if (print_err) | 137 | if (print_err) |
| 122 | pr_err("aborting, bad checksum\n"); | 138 | pr_err("Bad extended signature checksum, aborting.\n"); |
| 123 | return -EINVAL; | 139 | return -EINVAL; |
| 124 | } | 140 | } |
| 125 | } | 141 | } |
