diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-13 16:25:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-13 16:25:33 -0400 |
commit | 0ad5c6b3c2d1183740d225944059b0fdedb2afba (patch) | |
tree | 39ddc26c06ada9c039e6d90a071aea4af84a4b02 | |
parent | 421ec9017f3a1f3f032d894c55c15870f3d474aa (diff) | |
parent | 46423ffaf45c2494626841238d8bf75123a28caa (diff) |
Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 microcode changes from Ingo Molnar:
"Microcode driver updates: mostly cleanups but also some fixes
(Borislav Petkov)"
* 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/microcode/amd: Drop the pci_ids.h dependency
x86/microcode/intel: Fix printing of microcode blobs in show_saved_mc()
x86/microcode/intel: Check scan_microcode()'s retval
x86/microcode/intel: Sanitize microcode_pointer()
x86/microcode/intel: Move mc arg last in get_matching_{microcode|sig}
x86/microcode/intel: Simplify generic_load_microcode_early()
x86/microcode: Consolidate family,model, ... code
x86/microcode/intel: Rename update_match_revision()
x86/microcode/intel: Sanitize _save_mc()
x86/microcode/intel: Make _save_mc() return the updated saved count
x86/microcode/intel: Simplify load_ucode_intel_bsp()
x86/microcode/intel: Get rid of last arg to load_ucode_intel_bsp()
x86/microcode/intel: Do the mc_saved_src NULL check first
x86/microcode/intel: Check if microcode was found before applying
x86/microcode/intel: Fix out of bounds memory access to the extended header
-rw-r--r-- | arch/x86/include/asm/microcode.h | 73 | ||||
-rw-r--r-- | arch/x86/include/asm/microcode_intel.h | 13 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core_early.c | 75 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_early.c | 345 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_lib.c | 22 |
7 files changed, 259 insertions, 274 deletions
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 201b520521ed..2fb20d6f7e23 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -75,6 +75,79 @@ static inline void __exit exit_amd_microcode(void) {} | |||
75 | 75 | ||
76 | #ifdef CONFIG_MICROCODE_EARLY | 76 | #ifdef CONFIG_MICROCODE_EARLY |
77 | #define MAX_UCODE_COUNT 128 | 77 | #define MAX_UCODE_COUNT 128 |
78 | |||
79 | #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) | ||
80 | #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') | ||
81 | #define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') | ||
82 | #define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') | ||
83 | #define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') | ||
84 | #define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') | ||
85 | #define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') | ||
86 | |||
87 | #define CPUID_IS(a, b, c, ebx, ecx, edx) \ | ||
88 | (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) | ||
89 | |||
90 | /* | ||
91 | * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. | ||
92 | * x86_vendor() gets vendor id for BSP. | ||
93 | * | ||
94 | * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify | ||
95 | * coding, we still use x86_vendor() to get vendor id for AP. | ||
96 | * | ||
97 | * x86_vendor() gets vendor information directly from CPUID. | ||
98 | */ | ||
99 | static inline int x86_vendor(void) | ||
100 | { | ||
101 | u32 eax = 0x00000000; | ||
102 | u32 ebx, ecx = 0, edx; | ||
103 | |||
104 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
105 | |||
106 | if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) | ||
107 | return X86_VENDOR_INTEL; | ||
108 | |||
109 | if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) | ||
110 | return X86_VENDOR_AMD; | ||
111 | |||
112 | return X86_VENDOR_UNKNOWN; | ||
113 | } | ||
114 | |||
115 | static inline unsigned int __x86_family(unsigned int sig) | ||
116 | { | ||
117 | unsigned int x86; | ||
118 | |||
119 | x86 = (sig >> 8) & 0xf; | ||
120 | |||
121 | if (x86 == 0xf) | ||
122 | x86 += (sig >> 20) & 0xff; | ||
123 | |||
124 | return x86; | ||
125 | } | ||
126 | |||
127 | static inline unsigned int x86_family(void) | ||
128 | { | ||
129 | u32 eax = 0x00000001; | ||
130 | u32 ebx, ecx = 0, edx; | ||
131 | |||
132 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
133 | |||
134 | return __x86_family(eax); | ||
135 | } | ||
136 | |||
137 | static inline unsigned int x86_model(unsigned int sig) | ||
138 | { | ||
139 | unsigned int x86, model; | ||
140 | |||
141 | x86 = __x86_family(sig); | ||
142 | |||
143 | model = (sig >> 4) & 0xf; | ||
144 | |||
145 | if (x86 == 0x6 || x86 == 0xf) | ||
146 | model += ((sig >> 16) & 0xf) << 4; | ||
147 | |||
148 | return model; | ||
149 | } | ||
150 | |||
78 | extern void __init load_ucode_bsp(void); | 151 | extern void __init load_ucode_bsp(void); |
79 | extern void load_ucode_ap(void); | 152 | extern void load_ucode_ap(void); |
80 | extern int __init save_microcode_in_initrd(void); | 153 | extern int __init save_microcode_in_initrd(void); |
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index dd4c20043ce7..2b9209c46ca9 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h | |||
@@ -56,12 +56,15 @@ struct extended_sigtable { | |||
56 | 56 | ||
57 | #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) | 57 | #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) |
58 | 58 | ||
59 | extern int | 59 | extern int get_matching_microcode(unsigned int csig, int cpf, int rev, void *mc); |
60 | get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev); | ||
61 | extern int microcode_sanity_check(void *mc, int print_err); | 60 | extern int microcode_sanity_check(void *mc, int print_err); |
62 | extern int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev); | 61 | extern int get_matching_sig(unsigned int csig, int cpf, int rev, void *mc); |
63 | extern int | 62 | |
64 | update_match_revision(struct microcode_header_intel *mc_header, int rev); | 63 | static inline int |
64 | revision_is_newer(struct microcode_header_intel *mc_header, int rev) | ||
65 | { | ||
66 | return (mc_header->rev <= rev) ? 0 : 1; | ||
67 | } | ||
65 | 68 | ||
66 | #ifdef CONFIG_MICROCODE_INTEL_EARLY | 69 | #ifdef CONFIG_MICROCODE_INTEL_EARLY |
67 | extern void __init load_ucode_intel_bsp(void); | 70 | extern void __init load_ucode_intel_bsp(void); |
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index bfbbe6195e2d..12829c3ced3c 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
22 | 22 | ||
23 | #include <linux/firmware.h> | 23 | #include <linux/firmware.h> |
24 | #include <linux/pci_ids.h> | ||
25 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
26 | #include <linux/vmalloc.h> | 25 | #include <linux/vmalloc.h> |
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c index d45df4bd16ab..a413a69cbd74 100644 --- a/arch/x86/kernel/cpu/microcode/core_early.c +++ b/arch/x86/kernel/cpu/microcode/core_early.c | |||
@@ -23,57 +23,6 @@ | |||
23 | #include <asm/processor.h> | 23 | #include <asm/processor.h> |
24 | #include <asm/cmdline.h> | 24 | #include <asm/cmdline.h> |
25 | 25 | ||
26 | #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) | ||
27 | #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') | ||
28 | #define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') | ||
29 | #define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') | ||
30 | #define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') | ||
31 | #define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') | ||
32 | #define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') | ||
33 | |||
34 | #define CPUID_IS(a, b, c, ebx, ecx, edx) \ | ||
35 | (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) | ||
36 | |||
37 | /* | ||
38 | * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. | ||
39 | * x86_vendor() gets vendor id for BSP. | ||
40 | * | ||
41 | * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify | ||
42 | * coding, we still use x86_vendor() to get vendor id for AP. | ||
43 | * | ||
44 | * x86_vendor() gets vendor information directly through cpuid. | ||
45 | */ | ||
46 | static int x86_vendor(void) | ||
47 | { | ||
48 | u32 eax = 0x00000000; | ||
49 | u32 ebx, ecx = 0, edx; | ||
50 | |||
51 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
52 | |||
53 | if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) | ||
54 | return X86_VENDOR_INTEL; | ||
55 | |||
56 | if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) | ||
57 | return X86_VENDOR_AMD; | ||
58 | |||
59 | return X86_VENDOR_UNKNOWN; | ||
60 | } | ||
61 | |||
62 | static int x86_family(void) | ||
63 | { | ||
64 | u32 eax = 0x00000001; | ||
65 | u32 ebx, ecx = 0, edx; | ||
66 | int x86; | ||
67 | |||
68 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
69 | |||
70 | x86 = (eax >> 8) & 0xf; | ||
71 | if (x86 == 15) | ||
72 | x86 += (eax >> 20) & 0xff; | ||
73 | |||
74 | return x86; | ||
75 | } | ||
76 | |||
77 | static bool __init check_loader_disabled_bsp(void) | 26 | static bool __init check_loader_disabled_bsp(void) |
78 | { | 27 | { |
79 | #ifdef CONFIG_X86_32 | 28 | #ifdef CONFIG_X86_32 |
@@ -96,7 +45,7 @@ static bool __init check_loader_disabled_bsp(void) | |||
96 | 45 | ||
97 | void __init load_ucode_bsp(void) | 46 | void __init load_ucode_bsp(void) |
98 | { | 47 | { |
99 | int vendor, x86; | 48 | int vendor, family; |
100 | 49 | ||
101 | if (check_loader_disabled_bsp()) | 50 | if (check_loader_disabled_bsp()) |
102 | return; | 51 | return; |
@@ -105,15 +54,15 @@ void __init load_ucode_bsp(void) | |||
105 | return; | 54 | return; |
106 | 55 | ||
107 | vendor = x86_vendor(); | 56 | vendor = x86_vendor(); |
108 | x86 = x86_family(); | 57 | family = x86_family(); |
109 | 58 | ||
110 | switch (vendor) { | 59 | switch (vendor) { |
111 | case X86_VENDOR_INTEL: | 60 | case X86_VENDOR_INTEL: |
112 | if (x86 >= 6) | 61 | if (family >= 6) |
113 | load_ucode_intel_bsp(); | 62 | load_ucode_intel_bsp(); |
114 | break; | 63 | break; |
115 | case X86_VENDOR_AMD: | 64 | case X86_VENDOR_AMD: |
116 | if (x86 >= 0x10) | 65 | if (family >= 0x10) |
117 | load_ucode_amd_bsp(); | 66 | load_ucode_amd_bsp(); |
118 | break; | 67 | break; |
119 | default: | 68 | default: |
@@ -132,7 +81,7 @@ static bool check_loader_disabled_ap(void) | |||
132 | 81 | ||
133 | void load_ucode_ap(void) | 82 | void load_ucode_ap(void) |
134 | { | 83 | { |
135 | int vendor, x86; | 84 | int vendor, family; |
136 | 85 | ||
137 | if (check_loader_disabled_ap()) | 86 | if (check_loader_disabled_ap()) |
138 | return; | 87 | return; |
@@ -141,15 +90,15 @@ void load_ucode_ap(void) | |||
141 | return; | 90 | return; |
142 | 91 | ||
143 | vendor = x86_vendor(); | 92 | vendor = x86_vendor(); |
144 | x86 = x86_family(); | 93 | family = x86_family(); |
145 | 94 | ||
146 | switch (vendor) { | 95 | switch (vendor) { |
147 | case X86_VENDOR_INTEL: | 96 | case X86_VENDOR_INTEL: |
148 | if (x86 >= 6) | 97 | if (family >= 6) |
149 | load_ucode_intel_ap(); | 98 | load_ucode_intel_ap(); |
150 | break; | 99 | break; |
151 | case X86_VENDOR_AMD: | 100 | case X86_VENDOR_AMD: |
152 | if (x86 >= 0x10) | 101 | if (family >= 0x10) |
153 | load_ucode_amd_ap(); | 102 | load_ucode_amd_ap(); |
154 | break; | 103 | break; |
155 | default: | 104 | default: |
@@ -179,18 +128,18 @@ int __init save_microcode_in_initrd(void) | |||
179 | 128 | ||
180 | void reload_early_microcode(void) | 129 | void reload_early_microcode(void) |
181 | { | 130 | { |
182 | int vendor, x86; | 131 | int vendor, family; |
183 | 132 | ||
184 | vendor = x86_vendor(); | 133 | vendor = x86_vendor(); |
185 | x86 = x86_family(); | 134 | family = x86_family(); |
186 | 135 | ||
187 | switch (vendor) { | 136 | switch (vendor) { |
188 | case X86_VENDOR_INTEL: | 137 | case X86_VENDOR_INTEL: |
189 | if (x86 >= 6) | 138 | if (family >= 6) |
190 | reload_ucode_intel(); | 139 | reload_ucode_intel(); |
191 | break; | 140 | break; |
192 | case X86_VENDOR_AMD: | 141 | case X86_VENDOR_AMD: |
193 | if (x86 >= 0x10) | 142 | if (family >= 0x10) |
194 | reload_ucode_amd(); | 143 | reload_ucode_amd(); |
195 | break; | 144 | break; |
196 | default: | 145 | default: |
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 746e7fd08aad..a41beadb3db9 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c | |||
@@ -124,7 +124,7 @@ static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) | |||
124 | cpf = cpu_sig.pf; | 124 | cpf = cpu_sig.pf; |
125 | crev = cpu_sig.rev; | 125 | crev = cpu_sig.rev; |
126 | 126 | ||
127 | return get_matching_microcode(csig, cpf, mc_intel, crev); | 127 | return get_matching_microcode(csig, cpf, crev, mc_intel); |
128 | } | 128 | } |
129 | 129 | ||
130 | static int apply_microcode_intel(int cpu) | 130 | static int apply_microcode_intel(int cpu) |
@@ -226,7 +226,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
226 | 226 | ||
227 | csig = uci->cpu_sig.sig; | 227 | csig = uci->cpu_sig.sig; |
228 | cpf = uci->cpu_sig.pf; | 228 | cpf = uci->cpu_sig.pf; |
229 | if (get_matching_microcode(csig, cpf, mc, new_rev)) { | 229 | if (get_matching_microcode(csig, cpf, new_rev, mc)) { |
230 | vfree(new_mc); | 230 | vfree(new_mc); |
231 | new_rev = mc_header.rev; | 231 | new_rev = mc_header.rev; |
232 | new_mc = mc; | 232 | new_mc = mc; |
diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c index 420eb933189c..2f49ab4ac0ae 100644 --- a/arch/x86/kernel/cpu/microcode/intel_early.c +++ b/arch/x86/kernel/cpu/microcode/intel_early.c | |||
@@ -16,6 +16,14 @@ | |||
16 | * as published by the Free Software Foundation; either version | 16 | * as published by the Free Software Foundation; either version |
17 | * 2 of the License, or (at your option) any later version. | 17 | * 2 of the License, or (at your option) any later version. |
18 | */ | 18 | */ |
19 | |||
20 | /* | ||
21 | * This needs to be before all headers so that pr_debug in printk.h doesn't turn | ||
22 | * printk calls into no_printk(). | ||
23 | * | ||
24 | *#define DEBUG | ||
25 | */ | ||
26 | |||
19 | #include <linux/module.h> | 27 | #include <linux/module.h> |
20 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
21 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
@@ -28,6 +36,9 @@ | |||
28 | #include <asm/tlbflush.h> | 36 | #include <asm/tlbflush.h> |
29 | #include <asm/setup.h> | 37 | #include <asm/setup.h> |
30 | 38 | ||
39 | #undef pr_fmt | ||
40 | #define pr_fmt(fmt) "microcode: " fmt | ||
41 | |||
31 | static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; | 42 | static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; |
32 | static struct mc_saved_data { | 43 | static struct mc_saved_data { |
33 | unsigned int mc_saved_count; | 44 | unsigned int mc_saved_count; |
@@ -35,50 +46,45 @@ static struct mc_saved_data { | |||
35 | } mc_saved_data; | 46 | } mc_saved_data; |
36 | 47 | ||
37 | static enum ucode_state | 48 | static enum ucode_state |
38 | generic_load_microcode_early(struct microcode_intel **mc_saved_p, | 49 | load_microcode_early(struct microcode_intel **saved, |
39 | unsigned int mc_saved_count, | 50 | unsigned int num_saved, struct ucode_cpu_info *uci) |
40 | struct ucode_cpu_info *uci) | ||
41 | { | 51 | { |
42 | struct microcode_intel *ucode_ptr, *new_mc = NULL; | 52 | struct microcode_intel *ucode_ptr, *new_mc = NULL; |
43 | int new_rev = uci->cpu_sig.rev; | 53 | struct microcode_header_intel *mc_hdr; |
44 | enum ucode_state state = UCODE_OK; | 54 | int new_rev, ret, i; |
45 | unsigned int mc_size; | ||
46 | struct microcode_header_intel *mc_header; | ||
47 | unsigned int csig = uci->cpu_sig.sig; | ||
48 | unsigned int cpf = uci->cpu_sig.pf; | ||
49 | int i; | ||
50 | 55 | ||
51 | for (i = 0; i < mc_saved_count; i++) { | 56 | new_rev = uci->cpu_sig.rev; |
52 | ucode_ptr = mc_saved_p[i]; | ||
53 | 57 | ||
54 | mc_header = (struct microcode_header_intel *)ucode_ptr; | 58 | for (i = 0; i < num_saved; i++) { |
55 | mc_size = get_totalsize(mc_header); | 59 | ucode_ptr = saved[i]; |
56 | if (get_matching_microcode(csig, cpf, ucode_ptr, new_rev)) { | 60 | mc_hdr = (struct microcode_header_intel *)ucode_ptr; |
57 | new_rev = mc_header->rev; | ||
58 | new_mc = ucode_ptr; | ||
59 | } | ||
60 | } | ||
61 | 61 | ||
62 | if (!new_mc) { | 62 | ret = get_matching_microcode(uci->cpu_sig.sig, |
63 | state = UCODE_NFOUND; | 63 | uci->cpu_sig.pf, |
64 | goto out; | 64 | new_rev, |
65 | ucode_ptr); | ||
66 | if (!ret) | ||
67 | continue; | ||
68 | |||
69 | new_rev = mc_hdr->rev; | ||
70 | new_mc = ucode_ptr; | ||
65 | } | 71 | } |
66 | 72 | ||
73 | if (!new_mc) | ||
74 | return UCODE_NFOUND; | ||
75 | |||
67 | uci->mc = (struct microcode_intel *)new_mc; | 76 | uci->mc = (struct microcode_intel *)new_mc; |
68 | out: | 77 | return UCODE_OK; |
69 | return state; | ||
70 | } | 78 | } |
71 | 79 | ||
72 | static void | 80 | static inline void |
73 | microcode_pointer(struct microcode_intel **mc_saved, | 81 | copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd, |
74 | unsigned long *mc_saved_in_initrd, | 82 | unsigned long off, int num_saved) |
75 | unsigned long initrd_start, int mc_saved_count) | ||
76 | { | 83 | { |
77 | int i; | 84 | int i; |
78 | 85 | ||
79 | for (i = 0; i < mc_saved_count; i++) | 86 | for (i = 0; i < num_saved; i++) |
80 | mc_saved[i] = (struct microcode_intel *) | 87 | mc_saved[i] = (struct microcode_intel *)(initrd[i] + off); |
81 | (mc_saved_in_initrd[i] + initrd_start); | ||
82 | } | 88 | } |
83 | 89 | ||
84 | #ifdef CONFIG_X86_32 | 90 | #ifdef CONFIG_X86_32 |
@@ -102,55 +108,27 @@ microcode_phys(struct microcode_intel **mc_saved_tmp, | |||
102 | #endif | 108 | #endif |
103 | 109 | ||
104 | static enum ucode_state | 110 | static enum ucode_state |
105 | load_microcode(struct mc_saved_data *mc_saved_data, | 111 | load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, |
106 | unsigned long *mc_saved_in_initrd, | 112 | unsigned long initrd_start, struct ucode_cpu_info *uci) |
107 | unsigned long initrd_start, | ||
108 | struct ucode_cpu_info *uci) | ||
109 | { | 113 | { |
110 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | 114 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
111 | unsigned int count = mc_saved_data->mc_saved_count; | 115 | unsigned int count = mc_saved_data->mc_saved_count; |
112 | 116 | ||
113 | if (!mc_saved_data->mc_saved) { | 117 | if (!mc_saved_data->mc_saved) { |
114 | microcode_pointer(mc_saved_tmp, mc_saved_in_initrd, | 118 | copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count); |
115 | initrd_start, count); | ||
116 | 119 | ||
117 | return generic_load_microcode_early(mc_saved_tmp, count, uci); | 120 | return load_microcode_early(mc_saved_tmp, count, uci); |
118 | } else { | 121 | } else { |
119 | #ifdef CONFIG_X86_32 | 122 | #ifdef CONFIG_X86_32 |
120 | microcode_phys(mc_saved_tmp, mc_saved_data); | 123 | microcode_phys(mc_saved_tmp, mc_saved_data); |
121 | return generic_load_microcode_early(mc_saved_tmp, count, uci); | 124 | return load_microcode_early(mc_saved_tmp, count, uci); |
122 | #else | 125 | #else |
123 | return generic_load_microcode_early(mc_saved_data->mc_saved, | 126 | return load_microcode_early(mc_saved_data->mc_saved, |
124 | count, uci); | 127 | count, uci); |
125 | #endif | 128 | #endif |
126 | } | 129 | } |
127 | } | 130 | } |
128 | 131 | ||
129 | static u8 get_x86_family(unsigned long sig) | ||
130 | { | ||
131 | u8 x86; | ||
132 | |||
133 | x86 = (sig >> 8) & 0xf; | ||
134 | |||
135 | if (x86 == 0xf) | ||
136 | x86 += (sig >> 20) & 0xff; | ||
137 | |||
138 | return x86; | ||
139 | } | ||
140 | |||
141 | static u8 get_x86_model(unsigned long sig) | ||
142 | { | ||
143 | u8 x86, x86_model; | ||
144 | |||
145 | x86 = get_x86_family(sig); | ||
146 | x86_model = (sig >> 4) & 0xf; | ||
147 | |||
148 | if (x86 == 0x6 || x86 == 0xf) | ||
149 | x86_model += ((sig >> 16) & 0xf) << 4; | ||
150 | |||
151 | return x86_model; | ||
152 | } | ||
153 | |||
154 | /* | 132 | /* |
155 | * Given CPU signature and a microcode patch, this function finds if the | 133 | * Given CPU signature and a microcode patch, this function finds if the |
156 | * microcode patch has matching family and model with the CPU. | 134 | * microcode patch has matching family and model with the CPU. |
@@ -159,42 +137,40 @@ static enum ucode_state | |||
159 | matching_model_microcode(struct microcode_header_intel *mc_header, | 137 | matching_model_microcode(struct microcode_header_intel *mc_header, |
160 | unsigned long sig) | 138 | unsigned long sig) |
161 | { | 139 | { |
162 | u8 x86, x86_model; | 140 | unsigned int fam, model; |
163 | u8 x86_ucode, x86_model_ucode; | 141 | unsigned int fam_ucode, model_ucode; |
164 | struct extended_sigtable *ext_header; | 142 | struct extended_sigtable *ext_header; |
165 | unsigned long total_size = get_totalsize(mc_header); | 143 | unsigned long total_size = get_totalsize(mc_header); |
166 | unsigned long data_size = get_datasize(mc_header); | 144 | unsigned long data_size = get_datasize(mc_header); |
167 | int ext_sigcount, i; | 145 | int ext_sigcount, i; |
168 | struct extended_signature *ext_sig; | 146 | struct extended_signature *ext_sig; |
169 | 147 | ||
170 | x86 = get_x86_family(sig); | 148 | fam = __x86_family(sig); |
171 | x86_model = get_x86_model(sig); | 149 | model = x86_model(sig); |
172 | 150 | ||
173 | x86_ucode = get_x86_family(mc_header->sig); | 151 | fam_ucode = __x86_family(mc_header->sig); |
174 | x86_model_ucode = get_x86_model(mc_header->sig); | 152 | model_ucode = x86_model(mc_header->sig); |
175 | 153 | ||
176 | if (x86 == x86_ucode && x86_model == x86_model_ucode) | 154 | if (fam == fam_ucode && model == model_ucode) |
177 | return UCODE_OK; | 155 | return UCODE_OK; |
178 | 156 | ||
179 | /* Look for ext. headers: */ | 157 | /* Look for ext. headers: */ |
180 | if (total_size <= data_size + MC_HEADER_SIZE) | 158 | if (total_size <= data_size + MC_HEADER_SIZE) |
181 | return UCODE_NFOUND; | 159 | return UCODE_NFOUND; |
182 | 160 | ||
183 | ext_header = (struct extended_sigtable *) | 161 | ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE; |
184 | mc_header + data_size + MC_HEADER_SIZE; | 162 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; |
185 | ext_sigcount = ext_header->count; | 163 | ext_sigcount = ext_header->count; |
186 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | ||
187 | 164 | ||
188 | for (i = 0; i < ext_sigcount; i++) { | 165 | for (i = 0; i < ext_sigcount; i++) { |
189 | x86_ucode = get_x86_family(ext_sig->sig); | 166 | fam_ucode = __x86_family(ext_sig->sig); |
190 | x86_model_ucode = get_x86_model(ext_sig->sig); | 167 | model_ucode = x86_model(ext_sig->sig); |
191 | 168 | ||
192 | if (x86 == x86_ucode && x86_model == x86_model_ucode) | 169 | if (fam == fam_ucode && model == model_ucode) |
193 | return UCODE_OK; | 170 | return UCODE_OK; |
194 | 171 | ||
195 | ext_sig++; | 172 | ext_sig++; |
196 | } | 173 | } |
197 | |||
198 | return UCODE_NFOUND; | 174 | return UCODE_NFOUND; |
199 | } | 175 | } |
200 | 176 | ||
@@ -204,7 +180,7 @@ save_microcode(struct mc_saved_data *mc_saved_data, | |||
204 | unsigned int mc_saved_count) | 180 | unsigned int mc_saved_count) |
205 | { | 181 | { |
206 | int i, j; | 182 | int i, j; |
207 | struct microcode_intel **mc_saved_p; | 183 | struct microcode_intel **saved_ptr; |
208 | int ret; | 184 | int ret; |
209 | 185 | ||
210 | if (!mc_saved_count) | 186 | if (!mc_saved_count) |
@@ -213,39 +189,45 @@ save_microcode(struct mc_saved_data *mc_saved_data, | |||
213 | /* | 189 | /* |
214 | * Copy new microcode data. | 190 | * Copy new microcode data. |
215 | */ | 191 | */ |
216 | mc_saved_p = kmalloc(mc_saved_count*sizeof(struct microcode_intel *), | 192 | saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL); |
217 | GFP_KERNEL); | 193 | if (!saved_ptr) |
218 | if (!mc_saved_p) | ||
219 | return -ENOMEM; | 194 | return -ENOMEM; |
220 | 195 | ||
221 | for (i = 0; i < mc_saved_count; i++) { | 196 | for (i = 0; i < mc_saved_count; i++) { |
222 | struct microcode_intel *mc = mc_saved_src[i]; | 197 | struct microcode_header_intel *mc_hdr; |
223 | struct microcode_header_intel *mc_header = &mc->hdr; | 198 | struct microcode_intel *mc; |
224 | unsigned long mc_size = get_totalsize(mc_header); | 199 | unsigned long size; |
225 | mc_saved_p[i] = kmalloc(mc_size, GFP_KERNEL); | 200 | |
226 | if (!mc_saved_p[i]) { | ||
227 | ret = -ENOMEM; | ||
228 | goto err; | ||
229 | } | ||
230 | if (!mc_saved_src[i]) { | 201 | if (!mc_saved_src[i]) { |
231 | ret = -EINVAL; | 202 | ret = -EINVAL; |
232 | goto err; | 203 | goto err; |
233 | } | 204 | } |
234 | memcpy(mc_saved_p[i], mc, mc_size); | 205 | |
206 | mc = mc_saved_src[i]; | ||
207 | mc_hdr = &mc->hdr; | ||
208 | size = get_totalsize(mc_hdr); | ||
209 | |||
210 | saved_ptr[i] = kmalloc(size, GFP_KERNEL); | ||
211 | if (!saved_ptr[i]) { | ||
212 | ret = -ENOMEM; | ||
213 | goto err; | ||
214 | } | ||
215 | |||
216 | memcpy(saved_ptr[i], mc, size); | ||
235 | } | 217 | } |
236 | 218 | ||
237 | /* | 219 | /* |
238 | * Point to newly saved microcode. | 220 | * Point to newly saved microcode. |
239 | */ | 221 | */ |
240 | mc_saved_data->mc_saved = mc_saved_p; | 222 | mc_saved_data->mc_saved = saved_ptr; |
241 | mc_saved_data->mc_saved_count = mc_saved_count; | 223 | mc_saved_data->mc_saved_count = mc_saved_count; |
242 | 224 | ||
243 | return 0; | 225 | return 0; |
244 | 226 | ||
245 | err: | 227 | err: |
246 | for (j = 0; j <= i; j++) | 228 | for (j = 0; j <= i; j++) |
247 | kfree(mc_saved_p[j]); | 229 | kfree(saved_ptr[j]); |
248 | kfree(mc_saved_p); | 230 | kfree(saved_ptr); |
249 | 231 | ||
250 | return ret; | 232 | return ret; |
251 | } | 233 | } |
@@ -257,48 +239,45 @@ err: | |||
257 | * - or if it is a newly discovered microcode patch. | 239 | * - or if it is a newly discovered microcode patch. |
258 | * | 240 | * |
259 | * The microcode patch should have matching model with CPU. | 241 | * The microcode patch should have matching model with CPU. |
242 | * | ||
243 | * Returns: The updated number @num_saved of saved microcode patches. | ||
260 | */ | 244 | */ |
261 | static void _save_mc(struct microcode_intel **mc_saved, u8 *ucode_ptr, | 245 | static unsigned int _save_mc(struct microcode_intel **mc_saved, |
262 | unsigned int *mc_saved_count_p) | 246 | u8 *ucode_ptr, unsigned int num_saved) |
263 | { | 247 | { |
264 | int i; | 248 | struct microcode_header_intel *mc_hdr, *mc_saved_hdr; |
265 | int found = 0; | 249 | unsigned int sig, pf, new_rev; |
266 | unsigned int mc_saved_count = *mc_saved_count_p; | 250 | int found = 0, i; |
267 | struct microcode_header_intel *mc_header; | 251 | |
252 | mc_hdr = (struct microcode_header_intel *)ucode_ptr; | ||
253 | |||
254 | for (i = 0; i < num_saved; i++) { | ||
255 | mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i]; | ||
256 | sig = mc_saved_hdr->sig; | ||
257 | pf = mc_saved_hdr->pf; | ||
258 | new_rev = mc_hdr->rev; | ||
259 | |||
260 | if (!get_matching_sig(sig, pf, new_rev, ucode_ptr)) | ||
261 | continue; | ||
262 | |||
263 | found = 1; | ||
264 | |||
265 | if (!revision_is_newer(mc_hdr, new_rev)) | ||
266 | continue; | ||
268 | 267 | ||
269 | mc_header = (struct microcode_header_intel *)ucode_ptr; | ||
270 | for (i = 0; i < mc_saved_count; i++) { | ||
271 | unsigned int sig, pf; | ||
272 | unsigned int new_rev; | ||
273 | struct microcode_header_intel *mc_saved_header = | ||
274 | (struct microcode_header_intel *)mc_saved[i]; | ||
275 | sig = mc_saved_header->sig; | ||
276 | pf = mc_saved_header->pf; | ||
277 | new_rev = mc_header->rev; | ||
278 | |||
279 | if (get_matching_sig(sig, pf, ucode_ptr, new_rev)) { | ||
280 | found = 1; | ||
281 | if (update_match_revision(mc_header, new_rev)) { | ||
282 | /* | ||
283 | * Found an older ucode saved before. | ||
284 | * Replace the older one with this newer | ||
285 | * one. | ||
286 | */ | ||
287 | mc_saved[i] = | ||
288 | (struct microcode_intel *)ucode_ptr; | ||
289 | break; | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | if (i >= mc_saved_count && !found) | ||
294 | /* | 268 | /* |
295 | * This ucode is first time discovered in ucode file. | 269 | * Found an older ucode saved earlier. Replace it with |
296 | * Save it to memory. | 270 | * this newer one. |
297 | */ | 271 | */ |
298 | mc_saved[mc_saved_count++] = | 272 | mc_saved[i] = (struct microcode_intel *)ucode_ptr; |
299 | (struct microcode_intel *)ucode_ptr; | 273 | break; |
274 | } | ||
275 | |||
276 | /* Newly detected microcode, save it to memory. */ | ||
277 | if (i >= num_saved && !found) | ||
278 | mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr; | ||
300 | 279 | ||
301 | *mc_saved_count_p = mc_saved_count; | 280 | return num_saved; |
302 | } | 281 | } |
303 | 282 | ||
304 | /* | 283 | /* |
@@ -346,7 +325,7 @@ get_matching_model_microcode(int cpu, unsigned long start, | |||
346 | continue; | 325 | continue; |
347 | } | 326 | } |
348 | 327 | ||
349 | _save_mc(mc_saved_tmp, ucode_ptr, &mc_saved_count); | 328 | mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count); |
350 | 329 | ||
351 | ucode_ptr += mc_size; | 330 | ucode_ptr += mc_size; |
352 | } | 331 | } |
@@ -372,7 +351,7 @@ out: | |||
372 | static int collect_cpu_info_early(struct ucode_cpu_info *uci) | 351 | static int collect_cpu_info_early(struct ucode_cpu_info *uci) |
373 | { | 352 | { |
374 | unsigned int val[2]; | 353 | unsigned int val[2]; |
375 | u8 x86, x86_model; | 354 | unsigned int family, model; |
376 | struct cpu_signature csig; | 355 | struct cpu_signature csig; |
377 | unsigned int eax, ebx, ecx, edx; | 356 | unsigned int eax, ebx, ecx, edx; |
378 | 357 | ||
@@ -387,10 +366,10 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) | |||
387 | native_cpuid(&eax, &ebx, &ecx, &edx); | 366 | native_cpuid(&eax, &ebx, &ecx, &edx); |
388 | csig.sig = eax; | 367 | csig.sig = eax; |
389 | 368 | ||
390 | x86 = get_x86_family(csig.sig); | 369 | family = __x86_family(csig.sig); |
391 | x86_model = get_x86_model(csig.sig); | 370 | model = x86_model(csig.sig); |
392 | 371 | ||
393 | if ((x86_model >= 5) || (x86 > 6)) { | 372 | if ((model >= 5) || (family > 6)) { |
394 | /* get processor flags from MSR 0x17 */ | 373 | /* get processor flags from MSR 0x17 */ |
395 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | 374 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); |
396 | csig.pf = 1 << ((val[1] >> 18) & 7); | 375 | csig.pf = 1 << ((val[1] >> 18) & 7); |
@@ -429,8 +408,7 @@ static void __ref show_saved_mc(void) | |||
429 | sig = uci.cpu_sig.sig; | 408 | sig = uci.cpu_sig.sig; |
430 | pf = uci.cpu_sig.pf; | 409 | pf = uci.cpu_sig.pf; |
431 | rev = uci.cpu_sig.rev; | 410 | rev = uci.cpu_sig.rev; |
432 | pr_debug("CPU%d: sig=0x%x, pf=0x%x, rev=0x%x\n", | 411 | pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev); |
433 | smp_processor_id(), sig, pf, rev); | ||
434 | 412 | ||
435 | for (i = 0; i < mc_saved_data.mc_saved_count; i++) { | 413 | for (i = 0; i < mc_saved_data.mc_saved_count; i++) { |
436 | struct microcode_header_intel *mc_saved_header; | 414 | struct microcode_header_intel *mc_saved_header; |
@@ -457,8 +435,7 @@ static void __ref show_saved_mc(void) | |||
457 | if (total_size <= data_size + MC_HEADER_SIZE) | 435 | if (total_size <= data_size + MC_HEADER_SIZE) |
458 | continue; | 436 | continue; |
459 | 437 | ||
460 | ext_header = (struct extended_sigtable *) | 438 | ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE; |
461 | mc_saved_header + data_size + MC_HEADER_SIZE; | ||
462 | ext_sigcount = ext_header->count; | 439 | ext_sigcount = ext_header->count; |
463 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | 440 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; |
464 | 441 | ||
@@ -515,8 +492,7 @@ int save_mc_for_early(u8 *mc) | |||
515 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer | 492 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer |
516 | * version. | 493 | * version. |
517 | */ | 494 | */ |
518 | 495 | mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count); | |
519 | _save_mc(mc_saved_tmp, mc, &mc_saved_count); | ||
520 | 496 | ||
521 | /* | 497 | /* |
522 | * Save the mc_save_tmp in global mc_saved_data. | 498 | * Save the mc_save_tmp in global mc_saved_data. |
@@ -548,12 +524,10 @@ EXPORT_SYMBOL_GPL(save_mc_for_early); | |||
548 | 524 | ||
549 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; | 525 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; |
550 | static __init enum ucode_state | 526 | static __init enum ucode_state |
551 | scan_microcode(unsigned long start, unsigned long end, | 527 | scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, |
552 | struct mc_saved_data *mc_saved_data, | 528 | unsigned long start, unsigned long size, |
553 | unsigned long *mc_saved_in_initrd, | 529 | struct ucode_cpu_info *uci) |
554 | struct ucode_cpu_info *uci) | ||
555 | { | 530 | { |
556 | unsigned int size = end - start + 1; | ||
557 | struct cpio_data cd; | 531 | struct cpio_data cd; |
558 | long offset = 0; | 532 | long offset = 0; |
559 | #ifdef CONFIG_X86_32 | 533 | #ifdef CONFIG_X86_32 |
@@ -569,10 +543,8 @@ scan_microcode(unsigned long start, unsigned long end, | |||
569 | if (!cd.data) | 543 | if (!cd.data) |
570 | return UCODE_ERROR; | 544 | return UCODE_ERROR; |
571 | 545 | ||
572 | |||
573 | return get_matching_model_microcode(0, start, cd.data, cd.size, | 546 | return get_matching_model_microcode(0, start, cd.data, cd.size, |
574 | mc_saved_data, mc_saved_in_initrd, | 547 | mc_saved_data, initrd, uci); |
575 | uci); | ||
576 | } | 548 | } |
577 | 549 | ||
578 | /* | 550 | /* |
@@ -704,7 +676,7 @@ int __init save_microcode_in_initrd_intel(void) | |||
704 | if (count == 0) | 676 | if (count == 0) |
705 | return ret; | 677 | return ret; |
706 | 678 | ||
707 | microcode_pointer(mc_saved, mc_saved_in_initrd, initrd_start, count); | 679 | copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count); |
708 | ret = save_microcode(&mc_saved_data, mc_saved, count); | 680 | ret = save_microcode(&mc_saved_data, mc_saved, count); |
709 | if (ret) | 681 | if (ret) |
710 | pr_err("Cannot save microcode patches from initrd.\n"); | 682 | pr_err("Cannot save microcode patches from initrd.\n"); |
@@ -716,52 +688,44 @@ int __init save_microcode_in_initrd_intel(void) | |||
716 | 688 | ||
717 | static void __init | 689 | static void __init |
718 | _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | 690 | _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, |
719 | unsigned long *mc_saved_in_initrd, | 691 | unsigned long *initrd, |
720 | unsigned long initrd_start_early, | 692 | unsigned long start, unsigned long size) |
721 | unsigned long initrd_end_early, | ||
722 | struct ucode_cpu_info *uci) | ||
723 | { | 693 | { |
694 | struct ucode_cpu_info uci; | ||
724 | enum ucode_state ret; | 695 | enum ucode_state ret; |
725 | 696 | ||
726 | collect_cpu_info_early(uci); | 697 | collect_cpu_info_early(&uci); |
727 | scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, | ||
728 | mc_saved_in_initrd, uci); | ||
729 | 698 | ||
730 | ret = load_microcode(mc_saved_data, mc_saved_in_initrd, | 699 | ret = scan_microcode(mc_saved_data, initrd, start, size, &uci); |
731 | initrd_start_early, uci); | 700 | if (ret != UCODE_OK) |
701 | return; | ||
732 | 702 | ||
733 | if (ret == UCODE_OK) | 703 | ret = load_microcode(mc_saved_data, initrd, start, &uci); |
734 | apply_microcode_early(uci, true); | 704 | if (ret != UCODE_OK) |
705 | return; | ||
706 | |||
707 | apply_microcode_early(&uci, true); | ||
735 | } | 708 | } |
736 | 709 | ||
737 | void __init | 710 | void __init load_ucode_intel_bsp(void) |
738 | load_ucode_intel_bsp(void) | ||
739 | { | 711 | { |
740 | u64 ramdisk_image, ramdisk_size; | 712 | u64 start, size; |
741 | unsigned long initrd_start_early, initrd_end_early; | ||
742 | struct ucode_cpu_info uci; | ||
743 | #ifdef CONFIG_X86_32 | 713 | #ifdef CONFIG_X86_32 |
744 | struct boot_params *boot_params_p; | 714 | struct boot_params *p; |
745 | 715 | ||
746 | boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); | 716 | p = (struct boot_params *)__pa_nodebug(&boot_params); |
747 | ramdisk_image = boot_params_p->hdr.ramdisk_image; | 717 | start = p->hdr.ramdisk_image; |
748 | ramdisk_size = boot_params_p->hdr.ramdisk_size; | 718 | size = p->hdr.ramdisk_size; |
749 | initrd_start_early = ramdisk_image; | ||
750 | initrd_end_early = initrd_start_early + ramdisk_size; | ||
751 | 719 | ||
752 | _load_ucode_intel_bsp( | 720 | _load_ucode_intel_bsp( |
753 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | 721 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), |
754 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), | 722 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), |
755 | initrd_start_early, initrd_end_early, &uci); | 723 | start, size); |
756 | #else | 724 | #else |
757 | ramdisk_image = boot_params.hdr.ramdisk_image; | 725 | start = boot_params.hdr.ramdisk_image + PAGE_OFFSET; |
758 | ramdisk_size = boot_params.hdr.ramdisk_size; | 726 | size = boot_params.hdr.ramdisk_size; |
759 | initrd_start_early = ramdisk_image + PAGE_OFFSET; | 727 | |
760 | initrd_end_early = initrd_start_early + ramdisk_size; | 728 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size); |
761 | |||
762 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, | ||
763 | initrd_start_early, initrd_end_early, | ||
764 | &uci); | ||
765 | #endif | 729 | #endif |
766 | } | 730 | } |
767 | 731 | ||
@@ -771,6 +735,7 @@ void load_ucode_intel_ap(void) | |||
771 | struct ucode_cpu_info uci; | 735 | struct ucode_cpu_info uci; |
772 | unsigned long *mc_saved_in_initrd_p; | 736 | unsigned long *mc_saved_in_initrd_p; |
773 | unsigned long initrd_start_addr; | 737 | unsigned long initrd_start_addr; |
738 | enum ucode_state ret; | ||
774 | #ifdef CONFIG_X86_32 | 739 | #ifdef CONFIG_X86_32 |
775 | unsigned long *initrd_start_p; | 740 | unsigned long *initrd_start_p; |
776 | 741 | ||
@@ -793,8 +758,12 @@ void load_ucode_intel_ap(void) | |||
793 | return; | 758 | return; |
794 | 759 | ||
795 | collect_cpu_info_early(&uci); | 760 | collect_cpu_info_early(&uci); |
796 | load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, | 761 | ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, |
797 | initrd_start_addr, &uci); | 762 | initrd_start_addr, &uci); |
763 | |||
764 | if (ret != UCODE_OK) | ||
765 | return; | ||
766 | |||
798 | apply_microcode_early(&uci, true); | 767 | apply_microcode_early(&uci, true); |
799 | } | 768 | } |
800 | 769 | ||
@@ -808,8 +777,8 @@ void reload_ucode_intel(void) | |||
808 | 777 | ||
809 | collect_cpu_info_early(&uci); | 778 | collect_cpu_info_early(&uci); |
810 | 779 | ||
811 | ret = generic_load_microcode_early(mc_saved_data.mc_saved, | 780 | ret = load_microcode_early(mc_saved_data.mc_saved, |
812 | mc_saved_data.mc_saved_count, &uci); | 781 | mc_saved_data.mc_saved_count, &uci); |
813 | if (ret != UCODE_OK) | 782 | if (ret != UCODE_OK) |
814 | return; | 783 | return; |
815 | 784 | ||
diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index ce69320d0179..cd47a510a3f1 100644 --- a/arch/x86/kernel/cpu/microcode/intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c | |||
@@ -38,12 +38,6 @@ update_match_cpu(unsigned int csig, unsigned int cpf, | |||
38 | return (!sigmatch(sig, csig, pf, cpf)) ? 0 : 1; | 38 | return (!sigmatch(sig, csig, pf, cpf)) ? 0 : 1; |
39 | } | 39 | } |
40 | 40 | ||
41 | int | ||
42 | update_match_revision(struct microcode_header_intel *mc_header, int rev) | ||
43 | { | ||
44 | return (mc_header->rev <= rev) ? 0 : 1; | ||
45 | } | ||
46 | |||
47 | int microcode_sanity_check(void *mc, int print_err) | 41 | int microcode_sanity_check(void *mc, int print_err) |
48 | { | 42 | { |
49 | unsigned long total_size, data_size, ext_table_size; | 43 | unsigned long total_size, data_size, ext_table_size; |
@@ -128,10 +122,9 @@ int microcode_sanity_check(void *mc, int print_err) | |||
128 | EXPORT_SYMBOL_GPL(microcode_sanity_check); | 122 | EXPORT_SYMBOL_GPL(microcode_sanity_check); |
129 | 123 | ||
130 | /* | 124 | /* |
131 | * return 0 - no update found | 125 | * Returns 1 if update has been found, 0 otherwise. |
132 | * return 1 - found update | ||
133 | */ | 126 | */ |
134 | int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev) | 127 | int get_matching_sig(unsigned int csig, int cpf, int rev, void *mc) |
135 | { | 128 | { |
136 | struct microcode_header_intel *mc_header = mc; | 129 | struct microcode_header_intel *mc_header = mc; |
137 | struct extended_sigtable *ext_header; | 130 | struct extended_sigtable *ext_header; |
@@ -159,16 +152,15 @@ int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev) | |||
159 | } | 152 | } |
160 | 153 | ||
161 | /* | 154 | /* |
162 | * return 0 - no update found | 155 | * Returns 1 if update has been found, 0 otherwise. |
163 | * return 1 - found update | ||
164 | */ | 156 | */ |
165 | int get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev) | 157 | int get_matching_microcode(unsigned int csig, int cpf, int rev, void *mc) |
166 | { | 158 | { |
167 | struct microcode_header_intel *mc_header = mc; | 159 | struct microcode_header_intel *mc_hdr = mc; |
168 | 160 | ||
169 | if (!update_match_revision(mc_header, rev)) | 161 | if (!revision_is_newer(mc_hdr, rev)) |
170 | return 0; | 162 | return 0; |
171 | 163 | ||
172 | return get_matching_sig(csig, cpf, mc, rev); | 164 | return get_matching_sig(csig, cpf, rev, mc); |
173 | } | 165 | } |
174 | EXPORT_SYMBOL_GPL(get_matching_microcode); | 166 | EXPORT_SYMBOL_GPL(get_matching_microcode); |