aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Adamushko <dmitry.adamushko@gmail.com>2008-08-19 18:22:26 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-20 06:18:57 -0400
commitd45de40934897c6ee5b05141f7895bbb28512395 (patch)
tree1b4c4a011071d188a08d0f5bce8caf6b2b0a93c2
parent8343ef2437c599d30568e6b5a257a40bf2f4902b (diff)
x86-microcode: generic interface refactoring
This is the 1st patch in the series. Here the aim was to avoid any significant changes, logically-wise. So it's mainly about generic interface refactoring: e.g. make microcode_{intel,amd}.c more about arch-specific details and less about policies like make-sure-we-run-on-a-target-cpu (no more set_cpus_allowed_ptr() here) and generic synchronization (no more microcode_mutex here). All in all, more line have been deleted than added. 4 files changed, 145 insertions(+), 198 deletions(-) Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/microcode.c155
-rw-r--r--arch/x86/kernel/microcode_amd.c77
-rw-r--r--arch/x86/kernel/microcode_intel.c91
-rw-r--r--include/asm-x86/microcode.h20
4 files changed, 145 insertions, 198 deletions
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index ad136ad99cb3..b2f84ce5eed3 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -71,7 +71,7 @@
71 * Thanks to Stuart Swales for pointing out this bug. 71 * Thanks to Stuart Swales for pointing out this bug.
72 */ 72 */
73 73
74/*#define DEBUG pr_debug */ 74/* #define DEBUG pr_debug */
75#include <linux/capability.h> 75#include <linux/capability.h>
76#include <linux/kernel.h> 76#include <linux/kernel.h>
77#include <linux/init.h> 77#include <linux/init.h>
@@ -104,8 +104,7 @@ MODULE_LICENSE("GPL");
104struct microcode_ops *microcode_ops; 104struct microcode_ops *microcode_ops;
105 105
106/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 106/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
107DEFINE_MUTEX(microcode_mutex); 107static DEFINE_MUTEX(microcode_mutex);
108EXPORT_SYMBOL_GPL(microcode_mutex);
109 108
110struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; 109struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
111EXPORT_SYMBOL_GPL(ucode_cpu_info); 110EXPORT_SYMBOL_GPL(ucode_cpu_info);
@@ -234,22 +233,6 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
234struct platform_device *microcode_pdev; 233struct platform_device *microcode_pdev;
235EXPORT_SYMBOL_GPL(microcode_pdev); 234EXPORT_SYMBOL_GPL(microcode_pdev);
236 235
237static void microcode_init_cpu(int cpu, int resume)
238{
239 cpumask_t old;
240 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
241
242 old = current->cpus_allowed;
243
244 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
245 mutex_lock(&microcode_mutex);
246 microcode_ops->collect_cpu_info(cpu);
247 if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
248 microcode_ops->cpu_request_microcode(cpu);
249 mutex_unlock(&microcode_mutex);
250 set_cpus_allowed_ptr(current, &old);
251}
252
253static ssize_t reload_store(struct sys_device *dev, 236static ssize_t reload_store(struct sys_device *dev,
254 struct sysdev_attribute *attr, 237 struct sysdev_attribute *attr,
255 const char *buf, size_t sz) 238 const char *buf, size_t sz)
@@ -266,14 +249,15 @@ static ssize_t reload_store(struct sys_device *dev,
266 cpumask_t old = current->cpus_allowed; 249 cpumask_t old = current->cpus_allowed;
267 250
268 get_online_cpus(); 251 get_online_cpus();
269 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); 252 if (cpu_online(cpu)) {
270 253 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
271 mutex_lock(&microcode_mutex); 254 mutex_lock(&microcode_mutex);
272 if (uci->valid) 255 if (uci->valid)
273 err = microcode_ops->cpu_request_microcode(cpu); 256 err = microcode_ops->cpu_request_microcode(cpu);
274 mutex_unlock(&microcode_mutex); 257 mutex_unlock(&microcode_mutex);
258 set_cpus_allowed_ptr(current, &old);
259 }
275 put_online_cpus(); 260 put_online_cpus();
276 set_cpus_allowed_ptr(current, &old);
277 } 261 }
278 if (err) 262 if (err)
279 return err; 263 return err;
@@ -285,7 +269,7 @@ static ssize_t version_show(struct sys_device *dev,
285{ 269{
286 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; 270 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
287 271
288 return sprintf(buf, "0x%x\n", uci->rev); 272 return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
289} 273}
290 274
291static ssize_t pf_show(struct sys_device *dev, 275static ssize_t pf_show(struct sys_device *dev,
@@ -293,7 +277,7 @@ static ssize_t pf_show(struct sys_device *dev,
293{ 277{
294 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; 278 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
295 279
296 return sprintf(buf, "0x%x\n", uci->pf); 280 return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
297} 281}
298 282
299static SYSDEV_ATTR(reload, 0200, NULL, reload_store); 283static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
@@ -312,7 +296,85 @@ static struct attribute_group mc_attr_group = {
312 .name = "microcode", 296 .name = "microcode",
313}; 297};
314 298
315static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) 299static void microcode_fini_cpu(int cpu)
300{
301 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
302
303 mutex_lock(&microcode_mutex);
304 microcode_ops->microcode_fini_cpu(cpu);
305 uci->valid = 0;
306 mutex_unlock(&microcode_mutex);
307}
308
309static void collect_cpu_info(int cpu)
310{
311 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
312
313 memset(uci, 0, sizeof(*uci));
314 if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig))
315 uci->valid = 1;
316}
317
318static void microcode_resume_cpu(int cpu)
319{
320 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
321 struct cpu_signature nsig;
322
323 pr_debug("microcode: CPU%d resumed\n", cpu);
324
325 if (!uci->mc.valid_mc)
326 return;
327
328 /*
329 * Let's verify that the 'cached' ucode does belong
330 * to this cpu (a bit of paranoia):
331 */
332 if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
333 microcode_fini_cpu(cpu);
334 return;
335 }
336
337 if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
338 microcode_fini_cpu(cpu);
339 /* Should we look for a new ucode here? */
340 return;
341 }
342
343 microcode_ops->apply_microcode(cpu);
344}
345
346void microcode_update_cpu(int cpu)
347{
348 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
349
350 /* We should bind the task to the CPU */
351 BUG_ON(raw_smp_processor_id() != cpu);
352
353 mutex_lock(&microcode_mutex);
354 /*
355 * Check if the system resume is in progress (uci->valid != NULL),
356 * otherwise just request a firmware:
357 */
358 if (uci->valid) {
359 microcode_resume_cpu(cpu);
360 } else {
361 collect_cpu_info(cpu);
362 if (uci->valid && system_state == SYSTEM_RUNNING)
363 microcode_ops->cpu_request_microcode(cpu);
364 }
365 mutex_unlock(&microcode_mutex);
366}
367
368static void microcode_init_cpu(int cpu)
369{
370 cpumask_t old = current->cpus_allowed;
371
372 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
373 microcode_update_cpu(cpu);
374 set_cpus_allowed_ptr(current, &old);
375}
376
377static int mc_sysdev_add(struct sys_device *sys_dev)
316{ 378{
317 int err, cpu = sys_dev->id; 379 int err, cpu = sys_dev->id;
318 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 380 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -327,16 +389,10 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
327 if (err) 389 if (err)
328 return err; 390 return err;
329 391
330 microcode_init_cpu(cpu, resume); 392 microcode_init_cpu(cpu);
331
332 return 0; 393 return 0;
333} 394}
334 395
335static int mc_sysdev_add(struct sys_device *sys_dev)
336{
337 return __mc_sysdev_add(sys_dev, 0);
338}
339
340static int mc_sysdev_remove(struct sys_device *sys_dev) 396static int mc_sysdev_remove(struct sys_device *sys_dev)
341{ 397{
342 int cpu = sys_dev->id; 398 int cpu = sys_dev->id;
@@ -345,7 +401,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
345 return 0; 401 return 0;
346 402
347 pr_debug("microcode: CPU%d removed\n", cpu); 403 pr_debug("microcode: CPU%d removed\n", cpu);
348 microcode_ops->microcode_fini_cpu(cpu); 404 microcode_fini_cpu(cpu);
349 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); 405 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
350 return 0; 406 return 0;
351} 407}
@@ -376,33 +432,26 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
376 432
377 sys_dev = get_cpu_sysdev(cpu); 433 sys_dev = get_cpu_sysdev(cpu);
378 switch (action) { 434 switch (action) {
379 case CPU_UP_CANCELED_FROZEN:
380 /* The CPU refused to come up during a system resume */
381 microcode_ops->microcode_fini_cpu(cpu);
382 break;
383 case CPU_ONLINE: 435 case CPU_ONLINE:
384 case CPU_DOWN_FAILED:
385 mc_sysdev_add(sys_dev);
386 break;
387 case CPU_ONLINE_FROZEN: 436 case CPU_ONLINE_FROZEN:
388 /* System-wide resume is in progress, try to apply microcode */ 437 microcode_init_cpu(cpu);
389 if (microcode_ops->apply_microcode_check_cpu(cpu)) { 438 case CPU_DOWN_FAILED:
390 /* The application of microcode failed */
391 microcode_ops->microcode_fini_cpu(cpu);
392 __mc_sysdev_add(sys_dev, 1);
393 break;
394 }
395 case CPU_DOWN_FAILED_FROZEN: 439 case CPU_DOWN_FAILED_FROZEN:
440 pr_debug("microcode: CPU%d added\n", cpu);
396 if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) 441 if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
397 printk(KERN_ERR "microcode: Failed to create the sysfs " 442 printk(KERN_ERR "microcode: Failed to create the sysfs "
398 "group for CPU%d\n", cpu); 443 "group for CPU%d\n", cpu);
399 break; 444 break;
400 case CPU_DOWN_PREPARE: 445 case CPU_DOWN_PREPARE:
401 mc_sysdev_remove(sys_dev);
402 break;
403 case CPU_DOWN_PREPARE_FROZEN: 446 case CPU_DOWN_PREPARE_FROZEN:
404 /* Suspend is in progress, only remove the interface */ 447 /* Suspend is in progress, only remove the interface */
405 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); 448 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
449 pr_debug("microcode: CPU%d removed\n", cpu);
450 break;
451 case CPU_DEAD:
452 case CPU_UP_CANCELED_FROZEN:
453 /* The CPU refused to come up during a system resume */
454 microcode_fini_cpu(cpu);
406 break; 455 break;
407 } 456 }
408 return NOTIFY_OK; 457 return NOTIFY_OK;
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index a6e76ccf8158..4006e5e3adf0 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -59,38 +59,28 @@ MODULE_LICENSE("GPL v2");
59/* serialize access to the physical write */ 59/* serialize access to the physical write */
60static DEFINE_SPINLOCK(microcode_update_lock); 60static DEFINE_SPINLOCK(microcode_update_lock);
61 61
62/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
63extern struct mutex (microcode_mutex);
64
65struct equiv_cpu_entry *equiv_cpu_table; 62struct equiv_cpu_entry *equiv_cpu_table;
66 63
67extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; 64static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
68
69static void collect_cpu_info_amd(int cpu)
70{ 65{
71 struct cpuinfo_x86 *c = &cpu_data(cpu); 66 struct cpuinfo_x86 *c = &cpu_data(cpu);
72 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
73 67
74 /* We should bind the task to the CPU */ 68 memset(csig, 0, sizeof(*csig));
75 BUG_ON(raw_smp_processor_id() != cpu);
76 uci->rev = 0;
77 uci->pf = 0;
78 uci->mc.mc_amd = NULL;
79 uci->valid = 1;
80 69
81 if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { 70 if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
82 printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", 71 printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
83 cpu); 72 cpu);
84 uci->valid = 0; 73 return -1;
85 return;
86 } 74 }
87 75
88 asm volatile("movl %1, %%ecx; rdmsr" 76 asm volatile("movl %1, %%ecx; rdmsr"
89 : "=a" (uci->rev) 77 : "=a" (csig->rev)
90 : "i" (0x0000008B) : "ecx"); 78 : "i" (0x0000008B) : "ecx");
91 79
92 printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n", 80 printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n",
93 uci->rev); 81 csig->rev);
82
83 return 0;
94} 84}
95 85
96static int get_matching_microcode_amd(void *mc, int cpu) 86static int get_matching_microcode_amd(void *mc, int cpu)
@@ -119,7 +109,7 @@ static int get_matching_microcode_amd(void *mc, int cpu)
119 if (equiv_cpu_table == NULL) { 109 if (equiv_cpu_table == NULL) {
120 printk(KERN_INFO "microcode: CPU%d microcode update with " 110 printk(KERN_INFO "microcode: CPU%d microcode update with "
121 "version 0x%x (current=0x%x)\n", 111 "version 0x%x (current=0x%x)\n",
122 cpu, mc_header->patch_id, uci->rev); 112 cpu, mc_header->patch_id, uci->cpu_sig.rev);
123 goto out; 113 goto out;
124 } 114 }
125 115
@@ -185,12 +175,12 @@ static int get_matching_microcode_amd(void *mc, int cpu)
185 pci_dev_put(sb_pci_dev); 175 pci_dev_put(sb_pci_dev);
186 } 176 }
187 177
188 if (mc_header->patch_id <= uci->rev) 178 if (mc_header->patch_id <= uci->cpu_sig.rev)
189 return 0; 179 return 0;
190 180
191 printk(KERN_INFO "microcode: CPU%d found a matching microcode " 181 printk(KERN_INFO "microcode: CPU%d found a matching microcode "
192 "update with version 0x%x (current=0x%x)\n", 182 "update with version 0x%x (current=0x%x)\n",
193 cpu, mc_header->patch_id, uci->rev); 183 cpu, mc_header->patch_id, uci->cpu_sig.rev);
194 184
195out: 185out:
196 new_mc = vmalloc(UCODE_MAX_SIZE); 186 new_mc = vmalloc(UCODE_MAX_SIZE);
@@ -250,9 +240,9 @@ static void apply_microcode_amd(int cpu)
250 240
251 printk(KERN_INFO "microcode: CPU%d updated from revision " 241 printk(KERN_INFO "microcode: CPU%d updated from revision "
252 "0x%x to 0x%x \n", 242 "0x%x to 0x%x \n",
253 cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id); 243 cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id);
254 244
255 uci->rev = rev; 245 uci->cpu_sig.rev = rev;
256} 246}
257 247
258#ifdef CONFIG_MICROCODE_OLD_INTERFACE 248#ifdef CONFIG_MICROCODE_OLD_INTERFACE
@@ -437,61 +427,18 @@ static int cpu_request_microcode_amd(int cpu)
437 return error; 427 return error;
438} 428}
439 429
440static int apply_microcode_check_cpu_amd(int cpu)
441{
442 struct cpuinfo_x86 *c = &cpu_data(cpu);
443 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
444 unsigned int rev;
445 cpumask_t old;
446 int err = 0;
447
448 /* Check if the microcode is available */
449 if (!uci->mc.mc_amd)
450 return 0;
451
452 old = current->cpus_allowed;
453 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
454
455 /* Check if the microcode we have in memory matches the CPU */
456 if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16)
457 err = -EINVAL;
458
459 if (!err) {
460 asm volatile("movl %1, %%ecx; rdmsr"
461 : "=a" (rev)
462 : "i" (0x0000008B) : "ecx");
463
464 if (uci->rev != rev)
465 err = -EINVAL;
466 }
467
468 if (!err)
469 apply_microcode_amd(cpu);
470 else
471 printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
472 " rev=0x%x\n",
473 cpu, uci->rev);
474
475 set_cpus_allowed(current, old);
476 return err;
477}
478
479static void microcode_fini_cpu_amd(int cpu) 430static void microcode_fini_cpu_amd(int cpu)
480{ 431{
481 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 432 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
482 433
483 mutex_lock(&microcode_mutex);
484 uci->valid = 0;
485 vfree(uci->mc.mc_amd); 434 vfree(uci->mc.mc_amd);
486 uci->mc.mc_amd = NULL; 435 uci->mc.mc_amd = NULL;
487 mutex_unlock(&microcode_mutex);
488} 436}
489 437
490static struct microcode_ops microcode_amd_ops = { 438static struct microcode_ops microcode_amd_ops = {
491 .get_next_ucode = get_next_ucode_amd, 439 .get_next_ucode = get_next_ucode_amd,
492 .get_matching_microcode = get_matching_microcode_amd, 440 .get_matching_microcode = get_matching_microcode_amd,
493 .microcode_sanity_check = NULL, 441 .microcode_sanity_check = NULL,
494 .apply_microcode_check_cpu = apply_microcode_check_cpu_amd,
495 .cpu_request_microcode = cpu_request_microcode_amd, 442 .cpu_request_microcode = cpu_request_microcode_amd,
496 .collect_cpu_info = collect_cpu_info_amd, 443 .collect_cpu_info = collect_cpu_info_amd,
497 .apply_microcode = apply_microcode_amd, 444 .apply_microcode = apply_microcode_amd,
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 6dd8907ff22e..c9b53202ba3d 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -122,46 +122,37 @@ MODULE_LICENSE("GPL");
122/* serialize access to the physical write to MSR 0x79 */ 122/* serialize access to the physical write to MSR 0x79 */
123static DEFINE_SPINLOCK(microcode_update_lock); 123static DEFINE_SPINLOCK(microcode_update_lock);
124 124
125/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 125static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
126extern struct mutex microcode_mutex;
127
128extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
129
130static void collect_cpu_info(int cpu_num)
131{ 126{
132 struct cpuinfo_x86 *c = &cpu_data(cpu_num); 127 struct cpuinfo_x86 *c = &cpu_data(cpu_num);
133 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
134 unsigned int val[2]; 128 unsigned int val[2];
135 129
136 /* We should bind the task to the CPU */ 130 memset(csig, 0, sizeof(*csig));
137 BUG_ON(raw_smp_processor_id() != cpu_num);
138 uci->pf = uci->rev = 0;
139 uci->mc.mc_intel = NULL;
140 uci->valid = 1;
141 131
142 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || 132 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
143 cpu_has(c, X86_FEATURE_IA64)) { 133 cpu_has(c, X86_FEATURE_IA64)) {
144 printk(KERN_ERR "microcode: CPU%d not a capable Intel " 134 printk(KERN_ERR "microcode: CPU%d not a capable Intel "
145 "processor\n", cpu_num); 135 "processor\n", cpu_num);
146 uci->valid = 0; 136 return -1;
147 return;
148 } 137 }
149 138
150 uci->sig = cpuid_eax(0x00000001); 139 csig->sig = cpuid_eax(0x00000001);
151 140
152 if ((c->x86_model >= 5) || (c->x86 > 6)) { 141 if ((c->x86_model >= 5) || (c->x86 > 6)) {
153 /* get processor flags from MSR 0x17 */ 142 /* get processor flags from MSR 0x17 */
154 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 143 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
155 uci->pf = 1 << ((val[1] >> 18) & 7); 144 csig->pf = 1 << ((val[1] >> 18) & 7);
156 } 145 }
157 146
158 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 147 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
159 /* see notes above for revision 1.07. Apparent chip bug */ 148 /* see notes above for revision 1.07. Apparent chip bug */
160 sync_core(); 149 sync_core();
161 /* get the current revision from MSR 0x8B */ 150 /* get the current revision from MSR 0x8B */
162 rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev); 151 rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev);
163 pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", 152 pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
164 uci->sig, uci->pf, uci->rev); 153 csig->sig, csig->pf, csig->rev);
154
155 return 0;
165} 156}
166 157
167static inline int microcode_update_match(int cpu_num, 158static inline int microcode_update_match(int cpu_num,
@@ -169,8 +160,8 @@ static inline int microcode_update_match(int cpu_num,
169{ 160{
170 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 161 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
171 162
172 if (!sigmatch(sig, uci->sig, pf, uci->pf) 163 if (!sigmatch(sig, uci->cpu_sig.sig, pf, uci->cpu_sig.pf)
173 || mc_header->rev <= uci->rev) 164 || mc_header->rev <= uci->cpu_sig.rev)
174 return 0; 165 return 0;
175 return 1; 166 return 1;
176} 167}
@@ -289,7 +280,7 @@ static int get_matching_microcode(void *mc, int cpu)
289find: 280find:
290 pr_debug("microcode: CPU%d found a matching microcode update with" 281 pr_debug("microcode: CPU%d found a matching microcode update with"
291 " version 0x%x (current=0x%x)\n", 282 " version 0x%x (current=0x%x)\n",
292 cpu, mc_header->rev, uci->rev); 283 cpu, mc_header->rev, uci->cpu_sig.rev);
293 new_mc = vmalloc(total_size); 284 new_mc = vmalloc(total_size);
294 if (!new_mc) { 285 if (!new_mc) {
295 printk(KERN_ERR "microcode: error! Can not allocate memory\n"); 286 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
@@ -335,16 +326,16 @@ static void apply_microcode(int cpu)
335 spin_unlock_irqrestore(&microcode_update_lock, flags); 326 spin_unlock_irqrestore(&microcode_update_lock, flags);
336 if (val[1] != uci->mc.mc_intel->hdr.rev) { 327 if (val[1] != uci->mc.mc_intel->hdr.rev) {
337 printk(KERN_ERR "microcode: CPU%d update from revision " 328 printk(KERN_ERR "microcode: CPU%d update from revision "
338 "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]); 329 "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]);
339 return; 330 return;
340 } 331 }
341 printk(KERN_INFO "microcode: CPU%d updated from revision " 332 printk(KERN_INFO "microcode: CPU%d updated from revision "
342 "0x%x to 0x%x, date = %04x-%02x-%02x \n", 333 "0x%x to 0x%x, date = %04x-%02x-%02x \n",
343 cpu_num, uci->rev, val[1], 334 cpu_num, uci->cpu_sig.rev, val[1],
344 uci->mc.mc_intel->hdr.date & 0xffff, 335 uci->mc.mc_intel->hdr.date & 0xffff,
345 uci->mc.mc_intel->hdr.date >> 24, 336 uci->mc.mc_intel->hdr.date >> 24,
346 (uci->mc.mc_intel->hdr.date >> 16) & 0xff); 337 (uci->mc.mc_intel->hdr.date >> 16) & 0xff);
347 uci->rev = val[1]; 338 uci->cpu_sig.rev = val[1];
348} 339}
349 340
350#ifdef CONFIG_MICROCODE_OLD_INTERFACE 341#ifdef CONFIG_MICROCODE_OLD_INTERFACE
@@ -459,70 +450,18 @@ static int cpu_request_microcode(int cpu)
459 return error; 450 return error;
460} 451}
461 452
462static int apply_microcode_check_cpu(int cpu)
463{
464 struct cpuinfo_x86 *c = &cpu_data(cpu);
465 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
466 cpumask_t old;
467 unsigned int val[2];
468 int err = 0;
469
470 /* Check if the microcode is available */
471 if (!uci->mc.mc_intel)
472 return 0;
473
474 old = current->cpus_allowed;
475 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
476
477 /* Check if the microcode we have in memory matches the CPU */
478 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
479 cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
480 err = -EINVAL;
481
482 if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
483 /* get processor flags from MSR 0x17 */
484 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
485 if (uci->pf != (1 << ((val[1] >> 18) & 7)))
486 err = -EINVAL;
487 }
488
489 if (!err) {
490 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
491 /* see notes above for revision 1.07. Apparent chip bug */
492 sync_core();
493 /* get the current revision from MSR 0x8B */
494 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
495 if (uci->rev != val[1])
496 err = -EINVAL;
497 }
498
499 if (!err)
500 apply_microcode(cpu);
501 else
502 printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
503 " sig=0x%x, pf=0x%x, rev=0x%x\n",
504 cpu, uci->sig, uci->pf, uci->rev);
505
506 set_cpus_allowed_ptr(current, &old);
507 return err;
508}
509
510static void microcode_fini_cpu(int cpu) 453static void microcode_fini_cpu(int cpu)
511{ 454{
512 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 455 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
513 456
514 mutex_lock(&microcode_mutex);
515 uci->valid = 0;
516 vfree(uci->mc.mc_intel); 457 vfree(uci->mc.mc_intel);
517 uci->mc.mc_intel = NULL; 458 uci->mc.mc_intel = NULL;
518 mutex_unlock(&microcode_mutex);
519} 459}
520 460
521static struct microcode_ops microcode_intel_ops = { 461static struct microcode_ops microcode_intel_ops = {
522 .get_next_ucode = get_next_ucode, 462 .get_next_ucode = get_next_ucode,
523 .get_matching_microcode = get_matching_microcode, 463 .get_matching_microcode = get_matching_microcode,
524 .microcode_sanity_check = microcode_sanity_check, 464 .microcode_sanity_check = microcode_sanity_check,
525 .apply_microcode_check_cpu = apply_microcode_check_cpu,
526 .cpu_request_microcode = cpu_request_microcode, 465 .cpu_request_microcode = cpu_request_microcode,
527 .collect_cpu_info = collect_cpu_info, 466 .collect_cpu_info = collect_cpu_info,
528 .apply_microcode = apply_microcode, 467 .apply_microcode = apply_microcode,
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index 18b2aeec2adf..7ceff48fa657 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -1,14 +1,18 @@
1#ifndef ASM_X86__MICROCODE_H
2#define ASM_X86__MICROCODE_H
3
1extern int microcode_init(void *opaque, struct module *module); 4extern int microcode_init(void *opaque, struct module *module);
2extern void microcode_exit(void); 5extern void microcode_exit(void);
3 6
7struct cpu_signature;
8
4struct microcode_ops { 9struct microcode_ops {
5 long (*get_next_ucode)(void **mc, long offset); 10 long (*get_next_ucode)(void **mc, long offset);
6 long (*microcode_get_next_ucode)(void **mc, long offset); 11 long (*microcode_get_next_ucode)(void **mc, long offset);
7 int (*get_matching_microcode)(void *mc, int cpu); 12 int (*get_matching_microcode)(void *mc, int cpu);
8 int (*apply_microcode_check_cpu)(int cpu);
9 int (*microcode_sanity_check)(void *mc); 13 int (*microcode_sanity_check)(void *mc);
10 int (*cpu_request_microcode)(int cpu); 14 int (*cpu_request_microcode)(int cpu);
11 void (*collect_cpu_info)(int cpu_num); 15 int (*collect_cpu_info)(int cpu_num, struct cpu_signature *csig);
12 void (*apply_microcode)(int cpu); 16 void (*apply_microcode)(int cpu);
13 void (*microcode_fini_cpu)(int cpu); 17 void (*microcode_fini_cpu)(int cpu);
14 void (*clear_patch)(void *data); 18 void (*clear_patch)(void *data);
@@ -75,13 +79,21 @@ struct microcode_amd {
75 unsigned int mpb[0]; 79 unsigned int mpb[0];
76}; 80};
77 81
78struct ucode_cpu_info { 82struct cpu_signature {
79 int valid;
80 unsigned int sig; 83 unsigned int sig;
81 unsigned int pf; 84 unsigned int pf;
82 unsigned int rev; 85 unsigned int rev;
86};
87
88struct ucode_cpu_info {
89 struct cpu_signature cpu_sig;
90 int valid;
83 union { 91 union {
84 struct microcode_intel *mc_intel; 92 struct microcode_intel *mc_intel;
85 struct microcode_amd *mc_amd; 93 struct microcode_amd *mc_amd;
94 void *valid_mc;
86 } mc; 95 } mc;
87}; 96};
97extern struct ucode_cpu_info ucode_cpu_info[];
98
99#endif /* ASM_X86__MICROCODE_H */