diff options
author | Dmitry Adamushko <dmitry.adamushko@gmail.com> | 2008-08-19 18:22:26 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-20 06:18:57 -0400 |
commit | d45de40934897c6ee5b05141f7895bbb28512395 (patch) | |
tree | 1b4c4a011071d188a08d0f5bce8caf6b2b0a93c2 /arch/x86/kernel/microcode_amd.c | |
parent | 8343ef2437c599d30568e6b5a257a40bf2f4902b (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>
Diffstat (limited to 'arch/x86/kernel/microcode_amd.c')
-rw-r--r-- | arch/x86/kernel/microcode_amd.c | 77 |
1 files changed, 12 insertions, 65 deletions
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 */ |
60 | static DEFINE_SPINLOCK(microcode_update_lock); | 60 | static DEFINE_SPINLOCK(microcode_update_lock); |
61 | 61 | ||
62 | /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ | ||
63 | extern struct mutex (microcode_mutex); | ||
64 | |||
65 | struct equiv_cpu_entry *equiv_cpu_table; | 62 | struct equiv_cpu_entry *equiv_cpu_table; |
66 | 63 | ||
67 | extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; | 64 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) |
68 | |||
69 | static 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 | ||
96 | static int get_matching_microcode_amd(void *mc, int cpu) | 86 | static 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 | ||
195 | out: | 185 | out: |
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 | ||
440 | static 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 | |||
479 | static void microcode_fini_cpu_amd(int cpu) | 430 | static 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(µcode_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(µcode_mutex); | ||
488 | } | 436 | } |
489 | 437 | ||
490 | static struct microcode_ops microcode_amd_ops = { | 438 | static 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, |