diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2010-12-31 10:57:48 -0500 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2011-02-09 10:05:34 -0500 |
commit | 7cc27349cbfec271eecec9488b4bf3f3fadb2ce4 (patch) | |
tree | 04baaf1293f67e7e661b46c7f7bcff082a14e7ee | |
parent | 10de52d6655ef0d4a1b8d2804db30208c26601ed (diff) |
x86, microcode, AMD: Simplify get_next_ucode
Do not copy the section header but look at it directly through the
pointer. Also, make it return a ptr to a ucode header directly
thus dropping a bunch of unneeded casts. Finally, simplify
generic_load_microcode(), while at it.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Acked-by: Andreas Herrmann <Andreas.Herrmann3@amd.com>
-rw-r--r-- | arch/x86/kernel/microcode_amd.c | 68 |
1 files changed, 32 insertions, 36 deletions
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 9a451d7182f0..8b58fc13e37e 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
@@ -88,9 +88,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | |||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int get_matching_microcode(int cpu, void *mc, int rev) | 91 | static int get_matching_microcode(int cpu, struct microcode_header_amd *mc_hdr, |
92 | int rev) | ||
92 | { | 93 | { |
93 | struct microcode_header_amd *mc_header = mc; | ||
94 | unsigned int current_cpu_id; | 94 | unsigned int current_cpu_id; |
95 | u16 equiv_cpu_id = 0; | 95 | u16 equiv_cpu_id = 0; |
96 | unsigned int i = 0; | 96 | unsigned int i = 0; |
@@ -109,17 +109,17 @@ static int get_matching_microcode(int cpu, void *mc, int rev) | |||
109 | if (!equiv_cpu_id) | 109 | if (!equiv_cpu_id) |
110 | return 0; | 110 | return 0; |
111 | 111 | ||
112 | if (mc_header->processor_rev_id != equiv_cpu_id) | 112 | if (mc_hdr->processor_rev_id != equiv_cpu_id) |
113 | return 0; | 113 | return 0; |
114 | 114 | ||
115 | /* ucode might be chipset specific -- currently we don't support this */ | 115 | /* ucode might be chipset specific -- currently we don't support this */ |
116 | if (mc_header->nb_dev_id || mc_header->sb_dev_id) { | 116 | if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { |
117 | pr_err("CPU%d: loading of chipset specific code not yet supported\n", | 117 | pr_err("CPU%d: loading of chipset specific code not yet supported\n", |
118 | cpu); | 118 | cpu); |
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | if (mc_header->patch_id <= rev) | 122 | if (mc_hdr->patch_id <= rev) |
123 | return 0; | 123 | return 0; |
124 | 124 | ||
125 | return 1; | 125 | return 1; |
@@ -155,21 +155,18 @@ static int apply_microcode_amd(int cpu) | |||
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
157 | 157 | ||
158 | static void * | 158 | static struct microcode_header_amd * |
159 | get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) | 159 | get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) |
160 | { | 160 | { |
161 | struct microcode_header_amd *mc; | ||
161 | unsigned int total_size; | 162 | unsigned int total_size; |
162 | u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; | ||
163 | void *mc; | ||
164 | 163 | ||
165 | get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR); | 164 | if (buf[0] != UCODE_UCODE_TYPE) { |
166 | |||
167 | if (section_hdr[0] != UCODE_UCODE_TYPE) { | ||
168 | pr_err("error: invalid type field in container file section header\n"); | 165 | pr_err("error: invalid type field in container file section header\n"); |
169 | return NULL; | 166 | return NULL; |
170 | } | 167 | } |
171 | 168 | ||
172 | total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); | 169 | total_size = buf[4] + (buf[5] << 8); |
173 | 170 | ||
174 | if (total_size > size || total_size > UCODE_MAX_SIZE) { | 171 | if (total_size > size || total_size > UCODE_MAX_SIZE) { |
175 | pr_err("error: size mismatch\n"); | 172 | pr_err("error: size mismatch\n"); |
@@ -218,12 +215,12 @@ static enum ucode_state | |||
218 | generic_load_microcode(int cpu, const u8 *data, size_t size) | 215 | generic_load_microcode(int cpu, const u8 *data, size_t size) |
219 | { | 216 | { |
220 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 217 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
218 | struct microcode_header_amd *mc_hdr = NULL; | ||
219 | unsigned int mc_size, leftover; | ||
220 | unsigned long offset; | ||
221 | const u8 *ucode_ptr = data; | 221 | const u8 *ucode_ptr = data; |
222 | void *new_mc = NULL; | 222 | void *new_mc = NULL; |
223 | void *mc; | ||
224 | int new_rev = uci->cpu_sig.rev; | 223 | int new_rev = uci->cpu_sig.rev; |
225 | unsigned int leftover; | ||
226 | unsigned long offset; | ||
227 | enum ucode_state state = UCODE_OK; | 224 | enum ucode_state state = UCODE_OK; |
228 | 225 | ||
229 | offset = install_equiv_cpu_table(ucode_ptr); | 226 | offset = install_equiv_cpu_table(ucode_ptr); |
@@ -236,38 +233,37 @@ generic_load_microcode(int cpu, const u8 *data, size_t size) | |||
236 | leftover = size - offset; | 233 | leftover = size - offset; |
237 | 234 | ||
238 | while (leftover) { | 235 | while (leftover) { |
239 | unsigned int uninitialized_var(mc_size); | 236 | mc_hdr = get_next_ucode(ucode_ptr, leftover, &mc_size); |
240 | struct microcode_header_amd *mc_header; | 237 | if (!mc_hdr) |
241 | |||
242 | mc = get_next_ucode(ucode_ptr, leftover, &mc_size); | ||
243 | if (!mc) | ||
244 | break; | 238 | break; |
245 | 239 | ||
246 | mc_header = (struct microcode_header_amd *)mc; | 240 | if (get_matching_microcode(cpu, mc_hdr, new_rev)) { |
247 | if (get_matching_microcode(cpu, mc, new_rev)) { | ||
248 | vfree(new_mc); | 241 | vfree(new_mc); |
249 | new_rev = mc_header->patch_id; | 242 | new_rev = mc_hdr->patch_id; |
250 | new_mc = mc; | 243 | new_mc = mc_hdr; |
251 | } else | 244 | } else |
252 | vfree(mc); | 245 | vfree(mc_hdr); |
253 | 246 | ||
254 | ucode_ptr += mc_size; | 247 | ucode_ptr += mc_size; |
255 | leftover -= mc_size; | 248 | leftover -= mc_size; |
256 | } | 249 | } |
257 | 250 | ||
258 | if (new_mc) { | 251 | if (!new_mc) { |
259 | if (!leftover) { | ||
260 | vfree(uci->mc); | ||
261 | uci->mc = new_mc; | ||
262 | pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", | ||
263 | cpu, new_rev, uci->cpu_sig.rev); | ||
264 | } else { | ||
265 | vfree(new_mc); | ||
266 | state = UCODE_ERROR; | ||
267 | } | ||
268 | } else | ||
269 | state = UCODE_NFOUND; | 252 | state = UCODE_NFOUND; |
253 | goto free_table; | ||
254 | } | ||
255 | |||
256 | if (!leftover) { | ||
257 | vfree(uci->mc); | ||
258 | uci->mc = new_mc; | ||
259 | pr_debug("CPU%d update ucode to version 0x%x (from 0x%x)\n", | ||
260 | cpu, new_rev, uci->cpu_sig.rev); | ||
261 | } else { | ||
262 | vfree(new_mc); | ||
263 | state = UCODE_ERROR; | ||
264 | } | ||
270 | 265 | ||
266 | free_table: | ||
271 | free_equiv_cpu_table(); | 267 | free_equiv_cpu_table(); |
272 | 268 | ||
273 | return state; | 269 | return state; |