aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTorsten Kaiser <just.for.lkml@googlemail.com>2013-08-08 13:38:18 -0400
committerBorislav Petkov <bp@suse.de>2013-08-12 12:32:45 -0400
commit84516098b58e05821780dc0b89abcee434b4dca5 (patch)
tree8d842dce0d6a7ba771948844820dbc660e628b6b /arch
parent8c6b79bb1211d91fb31bcbc2a1eea8d6963d3ad9 (diff)
x86, microcode, AMD: Fix early microcode loading
load_microcode_amd() (and the helper it is using) should not have an cpu parameter. The microcode loading does not depend on the CPU wrt the patches loaded since they will end up in a global list for all CPUs anyway. The change from cpu to x86family in load_microcode_amd() now allows to drop the code messing with cpu_data(cpu) from collect_cpu_info_amd_early(), which is wrong anyway because at that point the per-cpu cpu_info is not yet setup (These values would later be overwritten by smp_store_boot_cpu_info() / smp_store_cpu_info()). Fold the rest of collect_cpu_info_amd_early() into load_ucode_amd_ap(), because its only used at one place and without the cpuinfo_x86 accesses it was not much left. Signed-off-by: Torsten Kaiser <just.for.lkml@googlemail.com> [ Fengguang: build fix ] Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> [ Boris: adapt it to current tree. ] Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/microcode_amd.h2
-rw-r--r--arch/x86/kernel/microcode_amd.c27
-rw-r--r--arch/x86/kernel/microcode_amd_early.c27
3 files changed, 27 insertions, 29 deletions
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h
index 50e5c58ced23..4c019179a57d 100644
--- a/arch/x86/include/asm/microcode_amd.h
+++ b/arch/x86/include/asm/microcode_amd.h
@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
59 59
60extern int __apply_microcode_amd(struct microcode_amd *mc_amd); 60extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
61extern int apply_microcode_amd(int cpu); 61extern int apply_microcode_amd(int cpu);
62extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size); 62extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
63 63
64#ifdef CONFIG_MICROCODE_AMD_EARLY 64#ifdef CONFIG_MICROCODE_AMD_EARLY
65#ifdef CONFIG_X86_32 65#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 7a0adb7ee433..7123b5df479d 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
145 return 0; 145 return 0;
146} 146}
147 147
148static unsigned int verify_patch_size(int cpu, u32 patch_size, 148static unsigned int verify_patch_size(u8 family, u32 patch_size,
149 unsigned int size) 149 unsigned int size)
150{ 150{
151 struct cpuinfo_x86 *c = &cpu_data(cpu);
152 u32 max_size; 151 u32 max_size;
153 152
154#define F1XH_MPB_MAX_SIZE 2048 153#define F1XH_MPB_MAX_SIZE 2048
@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
156#define F15H_MPB_MAX_SIZE 4096 155#define F15H_MPB_MAX_SIZE 4096
157#define F16H_MPB_MAX_SIZE 3458 156#define F16H_MPB_MAX_SIZE 3458
158 157
159 switch (c->x86) { 158 switch (family) {
160 case 0x14: 159 case 0x14:
161 max_size = F14H_MPB_MAX_SIZE; 160 max_size = F14H_MPB_MAX_SIZE;
162 break; 161 break;
@@ -277,9 +276,8 @@ static void cleanup(void)
277 * driver cannot continue functioning normally. In such cases, we tear 276 * driver cannot continue functioning normally. In such cases, we tear
278 * down everything we've used up so far and exit. 277 * down everything we've used up so far and exit.
279 */ 278 */
280static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) 279static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
281{ 280{
282 struct cpuinfo_x86 *c = &cpu_data(cpu);
283 struct microcode_header_amd *mc_hdr; 281 struct microcode_header_amd *mc_hdr;
284 struct ucode_patch *patch; 282 struct ucode_patch *patch;
285 unsigned int patch_size, crnt_size, ret; 283 unsigned int patch_size, crnt_size, ret;
@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
299 297
300 /* check if patch is for the current family */ 298 /* check if patch is for the current family */
301 proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); 299 proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
302 if (proc_fam != c->x86) 300 if (proc_fam != family)
303 return crnt_size; 301 return crnt_size;
304 302
305 if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { 303 if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
308 return crnt_size; 306 return crnt_size;
309 } 307 }
310 308
311 ret = verify_patch_size(cpu, patch_size, leftover); 309 ret = verify_patch_size(family, patch_size, leftover);
312 if (!ret) { 310 if (!ret) {
313 pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); 311 pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
314 return crnt_size; 312 return crnt_size;
@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
339 return crnt_size; 337 return crnt_size;
340} 338}
341 339
342static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size) 340static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
341 size_t size)
343{ 342{
344 enum ucode_state ret = UCODE_ERROR; 343 enum ucode_state ret = UCODE_ERROR;
345 unsigned int leftover; 344 unsigned int leftover;
@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
362 } 361 }
363 362
364 while (leftover) { 363 while (leftover) {
365 crnt_size = verify_and_add_patch(cpu, fw, leftover); 364 crnt_size = verify_and_add_patch(family, fw, leftover);
366 if (crnt_size < 0) 365 if (crnt_size < 0)
367 return ret; 366 return ret;
368 367
@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
373 return UCODE_OK; 372 return UCODE_OK;
374} 373}
375 374
376enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) 375enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
377{ 376{
378 enum ucode_state ret; 377 enum ucode_state ret;
379 378
380 /* free old equiv table */ 379 /* free old equiv table */
381 free_equiv_cpu_table(); 380 free_equiv_cpu_table();
382 381
383 ret = __load_microcode_amd(cpu, data, size); 382 ret = __load_microcode_amd(family, data, size);
384 383
385 if (ret != UCODE_OK) 384 if (ret != UCODE_OK)
386 cleanup(); 385 cleanup();
387 386
388#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32) 387#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
389 /* save BSP's matching patch for early load */ 388 /* save BSP's matching patch for early load */
390 if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) { 389 if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
391 struct ucode_patch *p = find_patch(cpu); 390 struct ucode_patch *p = find_patch(smp_processor_id());
392 if (p) { 391 if (p) {
393 memset(amd_bsp_mpb, 0, MPB_MAX_SIZE); 392 memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
394 memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data), 393 memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
441 goto fw_release; 440 goto fw_release;
442 } 441 }
443 442
444 ret = load_microcode_amd(cpu, fw->data, fw->size); 443 ret = load_microcode_amd(c->x86, fw->data, fw->size);
445 444
446 fw_release: 445 fw_release:
447 release_firmware(fw); 446 release_firmware(fw);
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 1d14ffee5749..6073104ccaa3 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
238 uci->cpu_sig.sig = cpuid_eax(0x00000001); 238 uci->cpu_sig.sig = cpuid_eax(0x00000001);
239} 239}
240#else 240#else
241static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c, 241void load_ucode_amd_ap(void)
242 struct ucode_cpu_info *uci)
243{ 242{
243 unsigned int cpu = smp_processor_id();
244 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
244 u32 rev, eax; 245 u32 rev, eax;
245 246
246 rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); 247 rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
247 eax = cpuid_eax(0x00000001); 248 eax = cpuid_eax(0x00000001);
248 249
249 uci->cpu_sig.sig = eax;
250 uci->cpu_sig.rev = rev; 250 uci->cpu_sig.rev = rev;
251 c->microcode = rev; 251 uci->cpu_sig.sig = eax;
252 c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
253}
254
255void load_ucode_amd_ap(void)
256{
257 unsigned int cpu = smp_processor_id();
258
259 collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
260 252
261 if (cpu && !ucode_loaded) { 253 if (cpu && !ucode_loaded) {
262 void *ucode; 254 void *ucode;
@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void)
265 return; 257 return;
266 258
267 ucode = (void *)(initrd_start + ucode_offset); 259 ucode = (void *)(initrd_start + ucode_offset);
268 if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK) 260 eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
261 if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
269 return; 262 return;
263
270 ucode_loaded = true; 264 ucode_loaded = true;
271 } 265 }
272 266
@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void)
278{ 272{
279 enum ucode_state ret; 273 enum ucode_state ret;
280 void *ucode; 274 void *ucode;
275 u32 eax;
276
281#ifdef CONFIG_X86_32 277#ifdef CONFIG_X86_32
282 unsigned int bsp = boot_cpu_data.cpu_index; 278 unsigned int bsp = boot_cpu_data.cpu_index;
283 struct ucode_cpu_info *uci = ucode_cpu_info + bsp; 279 struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void)
293 return 0; 289 return 0;
294 290
295 ucode = (void *)(initrd_start + ucode_offset); 291 ucode = (void *)(initrd_start + ucode_offset);
296 ret = load_microcode_amd(0, ucode, ucode_size); 292 eax = cpuid_eax(0x00000001);
293 eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
294
295 ret = load_microcode_amd(eax, ucode, ucode_size);
297 if (ret != UCODE_OK) 296 if (ret != UCODE_OK)
298 return -EINVAL; 297 return -EINVAL;
299 298