aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Shin <jacob.shin@amd.com>2013-06-05 16:13:55 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-06-05 16:56:47 -0400
commit275bbe2e299f1820ec8faa443d689469a9e6ecc5 (patch)
tree7e6a4faae73185e13ccf7c127f70c25a713026bf
parent6b3389ac21b5e557b957f1497d0ff22bf733e8c3 (diff)
x86, microcode, amd: Make find_ucode_in_initrd() __init
Change find_ucode_in_initrd() to __init and only let BSP call it during cold boot. This is the right thing to do because only BSP will see initrd loaded by the boot loader. APs will offset into initrd_start to find the microcode patch binary. Reported-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jacob Shin <jacob.shin@amd.com> Link: http://lkml.kernel.org/r/1370463236-2115-2-git-send-email-jacob.shin@amd.com Cc: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/kernel/microcode_amd_early.c98
1 files changed, 68 insertions, 30 deletions
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c
index 9618805ce6d7..7db1e16ca582 100644
--- a/arch/x86/kernel/microcode_amd_early.c
+++ b/arch/x86/kernel/microcode_amd_early.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/earlycpio.h> 11#include <linux/earlycpio.h>
12#include <linux/initrd.h>
12 13
13#include <asm/cpu.h> 14#include <asm/cpu.h>
14#include <asm/setup.h> 15#include <asm/setup.h>
@@ -16,40 +17,59 @@
16 17
17static bool ucode_loaded; 18static bool ucode_loaded;
18static u32 ucode_new_rev; 19static u32 ucode_new_rev;
20static unsigned long ucode_offset;
21static size_t ucode_size;
19 22
20/* 23/*
21 * Microcode patch container file is prepended to the initrd in cpio format. 24 * Microcode patch container file is prepended to the initrd in cpio format.
22 * See Documentation/x86/early-microcode.txt 25 * See Documentation/x86/early-microcode.txt
23 */ 26 */
24static __cpuinitdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin"; 27static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin";
25 28
26static struct cpio_data __cpuinit find_ucode_in_initrd(void) 29static struct cpio_data __init find_ucode_in_initrd(void)
27{ 30{
28 long offset = 0; 31 long offset = 0;
32 char *path;
33 void *start;
34 size_t size;
35 unsigned long *uoffset;
36 size_t *usize;
29 struct cpio_data cd; 37 struct cpio_data cd;
30 38
31#ifdef CONFIG_X86_32 39#ifdef CONFIG_X86_32
40 struct boot_params *p;
41
32 /* 42 /*
33 * On 32-bit, early load occurs before paging is turned on so we need 43 * On 32-bit, early load occurs before paging is turned on so we need
34 * to use physical addresses. 44 * to use physical addresses.
35 */ 45 */
36 if (!(read_cr0() & X86_CR0_PG)) { 46 p = (struct boot_params *)__pa_nodebug(&boot_params);
37 struct boot_params *p; 47 path = (char *)__pa_nodebug(ucode_path);
38 p = (struct boot_params *)__pa_nodebug(&boot_params); 48 start = (void *)p->hdr.ramdisk_image;
39 cd = find_cpio_data((char *)__pa_nodebug(ucode_path), 49 size = p->hdr.ramdisk_size;
40 (void *)p->hdr.ramdisk_image, p->hdr.ramdisk_size, 50 uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
41 &offset); 51 usize = (size_t *)__pa_nodebug(&ucode_size);
42 } else 52#else
53 path = ucode_path;
54 start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
55 size = boot_params.hdr.ramdisk_size;
56 uoffset = &ucode_offset;
57 usize = &ucode_size;
43#endif 58#endif
44 cd = find_cpio_data(ucode_path, 59
45 (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET), 60 cd = find_cpio_data(path, start, size, &offset);
46 boot_params.hdr.ramdisk_size, &offset); 61 if (!cd.data)
62 return cd;
47 63
48 if (*(u32 *)cd.data != UCODE_MAGIC) { 64 if (*(u32 *)cd.data != UCODE_MAGIC) {
49 cd.data = NULL; 65 cd.data = NULL;
50 cd.size = 0; 66 cd.size = 0;
67 return cd;
51 } 68 }
52 69
70 *uoffset = (u8 *)cd.data - (u8 *)start;
71 *usize = cd.size;
72
53 return cd; 73 return cd;
54} 74}
55 75
@@ -62,9 +82,8 @@ static struct cpio_data __cpuinit find_ucode_in_initrd(void)
62 * load_microcode_amd() to save equivalent cpu table and microcode patches in 82 * load_microcode_amd() to save equivalent cpu table and microcode patches in
63 * kernel heap memory. 83 * kernel heap memory.
64 */ 84 */
65static void __cpuinit apply_ucode_in_initrd(void) 85static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size)
66{ 86{
67 struct cpio_data cd;
68 struct equiv_cpu_entry *eq; 87 struct equiv_cpu_entry *eq;
69 u32 *header; 88 u32 *header;
70 u8 *data; 89 u8 *data;
@@ -78,12 +97,9 @@ static void __cpuinit apply_ucode_in_initrd(void)
78#else 97#else
79 new_rev = &ucode_new_rev; 98 new_rev = &ucode_new_rev;
80#endif 99#endif
81 cd = find_ucode_in_initrd();
82 if (!cd.data)
83 return;
84 100
85 data = cd.data; 101 data = ucode;
86 left = cd.size; 102 left = size;
87 header = (u32 *)data; 103 header = (u32 *)data;
88 104
89 /* find equiv cpu table */ 105 /* find equiv cpu table */
@@ -129,7 +145,11 @@ static void __cpuinit apply_ucode_in_initrd(void)
129 145
130void __init load_ucode_amd_bsp(void) 146void __init load_ucode_amd_bsp(void)
131{ 147{
132 apply_ucode_in_initrd(); 148 struct cpio_data cd = find_ucode_in_initrd();
149 if (!cd.data)
150 return;
151
152 apply_ucode_in_initrd(cd.data, cd.size);
133} 153}
134 154
135#ifdef CONFIG_X86_32 155#ifdef CONFIG_X86_32
@@ -145,12 +165,25 @@ u8 amd_bsp_mpb[MPB_MAX_SIZE];
145void __cpuinit load_ucode_amd_ap(void) 165void __cpuinit load_ucode_amd_ap(void)
146{ 166{
147 struct microcode_amd *mc; 167 struct microcode_amd *mc;
168 unsigned long *initrd;
169 unsigned long *uoffset;
170 size_t *usize;
171 void *ucode;
148 172
149 mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb); 173 mc = (struct microcode_amd *)__pa_nodebug(amd_bsp_mpb);
150 if (mc->hdr.patch_id && mc->hdr.processor_rev_id) 174 if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
151 __apply_microcode_amd(mc); 175 __apply_microcode_amd(mc);
152 else 176 return;
153 apply_ucode_in_initrd(); 177 }
178
179 initrd = (unsigned long *)__pa_nodebug(&initrd_start);
180 uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
181 usize = (size_t *)__pa_nodebug(&ucode_size);
182 if (!*usize)
183 return;
184
185 ucode = (void *)((unsigned long)__pa_nodebug(*initrd) + *uoffset);
186 apply_ucode_in_initrd(ucode, *usize);
154} 187}
155 188
156static void __init collect_cpu_sig_on_bsp(void *arg) 189static void __init collect_cpu_sig_on_bsp(void *arg)
@@ -181,8 +214,13 @@ void __cpuinit load_ucode_amd_ap(void)
181 collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu); 214 collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
182 215
183 if (cpu && !ucode_loaded) { 216 if (cpu && !ucode_loaded) {
184 struct cpio_data cd = find_ucode_in_initrd(); 217 void *ucode;
185 if (load_microcode_amd(0, cd.data, cd.size) != UCODE_OK) 218
219 if (!ucode_size)
220 return;
221
222 ucode = (void *)(initrd_start + ucode_offset);
223 if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
186 return; 224 return;
187 ucode_loaded = true; 225 ucode_loaded = true;
188 } 226 }
@@ -194,7 +232,7 @@ void __cpuinit load_ucode_amd_ap(void)
194int __init save_microcode_in_initrd_amd(void) 232int __init save_microcode_in_initrd_amd(void)
195{ 233{
196 enum ucode_state ret; 234 enum ucode_state ret;
197 struct cpio_data cd; 235 void *ucode;
198#ifdef CONFIG_X86_32 236#ifdef CONFIG_X86_32
199 unsigned int bsp = boot_cpu_data.cpu_index; 237 unsigned int bsp = boot_cpu_data.cpu_index;
200 struct ucode_cpu_info *uci = ucode_cpu_info + bsp; 238 struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
@@ -209,11 +247,11 @@ int __init save_microcode_in_initrd_amd(void)
209 if (ucode_loaded) 247 if (ucode_loaded)
210 return 0; 248 return 0;
211 249
212 cd = find_ucode_in_initrd(); 250 if (!ucode_size)
213 if (!cd.data) 251 return 0;
214 return -EINVAL;
215 252
216 ret = load_microcode_amd(0, cd.data, cd.size); 253 ucode = (void *)(initrd_start + ucode_offset);
254 ret = load_microcode_amd(0, ucode, ucode_size);
217 if (ret != UCODE_OK) 255 if (ret != UCODE_OK)
218 return -EINVAL; 256 return -EINVAL;
219 257