]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/x86/kernel/microcode_amd.c
x86-microcode: fix unbalanced use of get_cpu()
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / microcode_amd.c
1 /*
2  *  AMD CPU Microcode Update Driver for Linux
3  *  Copyright (C) 2008 Advanced Micro Devices Inc.
4  *
5  *  Author: Peter Oruba <peter.oruba@amd.com>
6  *
7  *  Based on work by:
8  *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
9  *
10  *  This driver allows to upgrade microcode on AMD
11  *  family 0x10 and 0x11 processors.
12  *
13  *  Licensed unter the terms of the GNU General Public
14  *  License version 2. See file COPYING for details.
15 */
16
17 #include <linux/capability.h>
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/sched.h>
21 #include <linux/cpumask.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/vmalloc.h>
25 #include <linux/miscdevice.h>
26 #include <linux/spinlock.h>
27 #include <linux/mm.h>
28 #include <linux/fs.h>
29 #include <linux/mutex.h>
30 #include <linux/cpu.h>
31 #include <linux/firmware.h>
32 #include <linux/platform_device.h>
33 #include <linux/pci.h>
34 #include <linux/pci_ids.h>
35
36 #include <asm/msr.h>
37 #include <asm/uaccess.h>
38 #include <asm/processor.h>
39 #include <asm/microcode.h>
40
41 MODULE_DESCRIPTION("AMD Microcode Update Driver");
42 MODULE_AUTHOR("Peter Oruba <peter.oruba@amd.com>");
43 MODULE_LICENSE("GPL v2");
44
45 #define UCODE_MAGIC                0x00414d44
46 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
47 #define UCODE_UCODE_TYPE           0x00000001
48
49 #define UCODE_MAX_SIZE          (2048)
50 #define DEFAULT_UCODE_DATASIZE  (896)
51 #define MC_HEADER_SIZE          (sizeof(struct microcode_header_amd))
52 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
53 #define DWSIZE                  (sizeof(u32))
54 /* For now we support a fixed ucode total size only */
55 #define get_totalsize(mc) \
56         ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
57          + MC_HEADER_SIZE)
58
59 /* serialize access to the physical write */
60 static DEFINE_SPINLOCK(microcode_update_lock);
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;
66
67 extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
68
69 static void collect_cpu_info_amd(int cpu)
70 {
71         struct cpuinfo_x86 *c = &cpu_data(cpu);
72         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
73
74         /* We should bind the task to the CPU */
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
81         if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
82                 printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
83                        cpu);
84                 uci->valid = 0;
85                 return;
86         }
87
88         asm volatile("movl %1, %%ecx; rdmsr"
89                      : "=a" (uci->rev)
90                      : "i" (0x0000008B) : "ecx");
91
92         printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n",
93                uci->rev);
94 }
95
96 static int get_matching_microcode_amd(void *mc, int cpu)
97 {
98         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
99         struct microcode_header_amd *mc_header = mc;
100         unsigned long total_size = get_totalsize(mc_header);
101         void *new_mc;
102         struct pci_dev *nb_pci_dev, *sb_pci_dev;
103         unsigned int current_cpu_id;
104         unsigned int equiv_cpu_id = 0x00;
105         unsigned int i = 0;
106
107         /* We should bind the task to the CPU */
108         BUG_ON(cpu != raw_smp_processor_id());
109
110         /* This is a tricky part. We might be called from a write operation */
111         /* to the device file instead of the usual process of firmware */
112         /* loading. This routine needs to be able to distinguish both */
113 /* cases. This is done by checking if there alread is a equivalent */
114         /* CPU table installed. If not, we're written through */
115         /* /dev/cpu/microcode. */
116 /* Since we ignore all checks. The error case in which going through */
117 /* firmware loading and that table is not loaded has already been */
118         /* checked earlier. */
119         if (equiv_cpu_table == NULL) {
120                 printk(KERN_INFO "microcode: CPU%d microcode update with "
121                        "version 0x%x (current=0x%x)\n",
122                        cpu, mc_header->patch_id, uci->rev);
123                 goto out;
124         }
125
126         current_cpu_id = cpuid_eax(0x00000001);
127
128         while (equiv_cpu_table[i].installed_cpu != 0) {
129                 if (current_cpu_id == equiv_cpu_table[i].installed_cpu) {
130                         equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
131                         break;
132                 }
133                 i++;
134         }
135
136         if (!equiv_cpu_id) {
137                 printk(KERN_ERR "microcode: CPU%d cpu_id "
138                        "not found in equivalent cpu table \n", cpu);
139                 return 0;
140         }
141
142         if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) {
143                 printk(KERN_ERR
144                         "microcode: CPU%d patch does not match "
145                         "(patch is %x, cpu extended is %x) \n",
146                         cpu, mc_header->processor_rev_id[0],
147                         (equiv_cpu_id & 0xff));
148                 return 0;
149         }
150
151         if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) {
152                 printk(KERN_ERR "microcode: CPU%d patch does not match "
153                         "(patch is %x, cpu base id is %x) \n",
154                         cpu, mc_header->processor_rev_id[1],
155                         ((equiv_cpu_id >> 16) & 0xff));
156
157                 return 0;
158         }
159
160         /* ucode may be northbridge specific */
161         if (mc_header->nb_dev_id) {
162                 nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
163                                             (mc_header->nb_dev_id & 0xff),
164                                             NULL);
165                 if ((!nb_pci_dev) ||
166                     (mc_header->nb_rev_id != nb_pci_dev->revision)) {
167                         printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu);
168                         pci_dev_put(nb_pci_dev);
169                         return 0;
170                 }
171                 pci_dev_put(nb_pci_dev);
172         }
173
174         /* ucode may be southbridge specific */
175         if (mc_header->sb_dev_id) {
176                 sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
177                                             (mc_header->sb_dev_id & 0xff),
178                                             NULL);
179                 if ((!sb_pci_dev) ||
180                     (mc_header->sb_rev_id != sb_pci_dev->revision)) {
181                         printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu);
182                         pci_dev_put(sb_pci_dev);
183                         return 0;
184                 }
185                 pci_dev_put(sb_pci_dev);
186         }
187
188         if (mc_header->patch_id <= uci->rev)
189                 return 0;
190
191         printk(KERN_INFO "microcode: CPU%d found a matching microcode "
192                "update with version 0x%x (current=0x%x)\n",
193                cpu, mc_header->patch_id, uci->rev);
194
195 out:
196         new_mc = vmalloc(UCODE_MAX_SIZE);
197         if (!new_mc) {
198                 printk(KERN_ERR "microcode: error, can't allocate memory\n");
199                 return -ENOMEM;
200         }
201         memset(new_mc, 0, UCODE_MAX_SIZE);
202
203         /* free previous update file */
204         vfree(uci->mc.mc_amd);
205
206         memcpy(new_mc, mc, total_size);
207
208         uci->mc.mc_amd = new_mc;
209         return 1;
210 }
211
212 static void apply_microcode_amd(int cpu)
213 {
214         unsigned long flags;
215         unsigned int eax, edx;
216         unsigned int rev;
217         int cpu_num = raw_smp_processor_id();
218         struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
219
220         /* We should bind the task to the CPU */
221         BUG_ON(cpu_num != cpu);
222
223         if (uci->mc.mc_amd == NULL)
224                 return;
225
226         spin_lock_irqsave(&microcode_update_lock, flags);
227
228         edx = (unsigned int)(((unsigned long)
229                               &(uci->mc.mc_amd->hdr.data_code)) >> 32);
230         eax = (unsigned int)(((unsigned long)
231                               &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL);
232
233         asm volatile("movl %0, %%ecx; wrmsr" :
234                      : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx");
235
236         /* get patch id after patching */
237         asm volatile("movl %1, %%ecx; rdmsr"
238                      : "=a" (rev)
239                      : "i" (0x0000008B) : "ecx");
240
241         spin_unlock_irqrestore(&microcode_update_lock, flags);
242
243         /* check current patch id and patch's id for match */
244         if (rev != uci->mc.mc_amd->hdr.patch_id) {
245                 printk(KERN_ERR "microcode: CPU%d update from revision "
246                        "0x%x to 0x%x failed\n", cpu_num,
247                        uci->mc.mc_amd->hdr.patch_id, rev);
248                 return;
249         }
250
251         printk(KERN_INFO "microcode: CPU%d updated from revision "
252                "0x%x to 0x%x \n",
253                cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id);
254
255         uci->rev = rev;
256 }
257
258 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
259 extern void __user *user_buffer;        /* user area microcode data buffer */
260 extern unsigned int user_buffer_size;   /* it's size */
261
262 static long get_next_ucode_amd(void **mc, long offset)
263 {
264         struct microcode_header_amd mc_header;
265         unsigned long total_size;
266
267         /* No more data */
268         if (offset >= user_buffer_size)
269                 return 0;
270         if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
271                 printk(KERN_ERR "microcode: error! Can not read user data\n");
272                 return -EFAULT;
273         }
274         total_size = get_totalsize(&mc_header);
275         if (offset + total_size > user_buffer_size) {
276                 printk(KERN_ERR "microcode: error! Bad total size in microcode "
277                        "data file\n");
278                 return -EINVAL;
279         }
280         *mc = vmalloc(UCODE_MAX_SIZE);
281         if (!*mc)
282                 return -ENOMEM;
283         memset(*mc, 0, UCODE_MAX_SIZE);
284
285         if (copy_from_user(*mc, user_buffer + offset, total_size)) {
286                 printk(KERN_ERR "microcode: error! Can not read user data\n");
287                 vfree(*mc);
288                 return -EFAULT;
289         }
290         return offset + total_size;
291 }
292 #else
293 #define get_next_ucode_amd() NULL
294 #endif
295
296 static long get_next_ucode_from_buffer_amd(void **mc, void *buf,
297                                        unsigned long size, long offset)
298 {
299         struct microcode_header_amd *mc_header;
300         unsigned long total_size;
301         unsigned char *buf_pos = buf;
302
303         /* No more data */
304         if (offset >= size)
305                 return 0;
306
307         if (buf_pos[offset] != UCODE_UCODE_TYPE) {
308                 printk(KERN_ERR "microcode: error! "
309                        "Wrong microcode payload type field\n");
310                 return -EINVAL;
311         }
312
313         mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
314
315         total_size = (unsigned long) (buf_pos[offset+4] +
316                                       (buf_pos[offset+5] << 8));
317
318         printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
319                 size, total_size, offset);
320
321         if (offset + total_size > size) {
322                 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
323                 return -EINVAL;
324         }
325
326         *mc = vmalloc(UCODE_MAX_SIZE);
327         if (!*mc) {
328                 printk(KERN_ERR "microcode: error! "
329                        "Can not allocate memory for microcode patch\n");
330                 return -ENOMEM;
331         }
332
333         memset(*mc, 0, UCODE_MAX_SIZE);
334         memcpy(*mc, buf + offset + 8, total_size);
335
336         return offset + total_size + 8;
337 }
338
339 static long install_equiv_cpu_table(void *buf, unsigned long size, long offset)
340 {
341         unsigned int *buf_pos = buf;
342
343         /* No more data */
344         if (offset >= size)
345                 return 0;
346
347         if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) {
348                 printk(KERN_ERR "microcode: error! "
349                        "Wrong microcode equivalnet cpu table type field\n");
350                 return 0;
351         }
352
353         if (size == 0) {
354                 printk(KERN_ERR "microcode: error! "
355                        "Wrong microcode equivalnet cpu table length\n");
356                 return 0;
357         }
358
359         equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size);
360         if (!equiv_cpu_table) {
361                 printk(KERN_ERR "microcode: error, can't allocate memory for equiv CPU table\n");
362                 return 0;
363         }
364
365         memset(equiv_cpu_table, 0, size);
366         memcpy(equiv_cpu_table, &buf_pos[3], size);
367
368         return size + 12; /* add header length */
369 }
370
371 /* fake device for request_firmware */
372 extern struct platform_device *microcode_pdev;
373
374 static int cpu_request_microcode_amd(int cpu)
375 {
376         char name[30];
377         const struct firmware *firmware;
378         void *buf;
379         unsigned int *buf_pos;
380         unsigned long size;
381         long offset = 0;
382         int error;
383         void *mc;
384
385         /* We should bind the task to the CPU */
386         BUG_ON(cpu != raw_smp_processor_id());
387
388         sprintf(name, "amd-ucode/microcode_amd.bin");
389         error = request_firmware(&firmware, "amd-ucode/microcode_amd.bin",
390                                  &microcode_pdev->dev);
391         if (error) {
392                 printk(KERN_ERR "microcode: ucode data file %s load failed\n",
393                        name);
394                 return error;
395         }
396
397         buf_pos = (unsigned int *)firmware->data;
398         buf = (void *)firmware->data;
399         size = firmware->size;
400
401         if (buf_pos[0] != UCODE_MAGIC) {
402                 printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n");
403                 return -EINVAL;
404         }
405
406         offset = install_equiv_cpu_table(buf, buf_pos[2], offset);
407
408         if (!offset) {
409                 printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
410                 return -EINVAL;
411         }
412
413         while ((offset =
414                 get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) {
415                 error = get_matching_microcode_amd(mc, cpu);
416                 if (error < 0)
417                         break;
418                 /*
419                  * It's possible the data file has multiple matching ucode,
420                  * lets keep searching till the latest version
421                  */
422                 if (error == 1) {
423                         apply_microcode_amd(cpu);
424                         error = 0;
425                 }
426                 vfree(mc);
427         }
428         if (offset > 0) {
429                 vfree(mc);
430                 vfree(equiv_cpu_table);
431                 equiv_cpu_table = NULL;
432         }
433         if (offset < 0)
434                 error = offset;
435         release_firmware(firmware);
436
437         return error;
438 }
439
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)
480 {
481         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
482
483         mutex_lock(&microcode_mutex);
484         uci->valid = 0;
485         vfree(uci->mc.mc_amd);
486         uci->mc.mc_amd = NULL;
487         mutex_unlock(&microcode_mutex);
488 }
489
490 static struct microcode_ops microcode_amd_ops = {
491         .get_next_ucode                   = get_next_ucode_amd,
492         .get_matching_microcode           = get_matching_microcode_amd,
493         .microcode_sanity_check           = NULL,
494         .apply_microcode_check_cpu        = apply_microcode_check_cpu_amd,
495         .cpu_request_microcode            = cpu_request_microcode_amd,
496         .collect_cpu_info                 = collect_cpu_info_amd,
497         .apply_microcode                  = apply_microcode_amd,
498         .microcode_fini_cpu               = microcode_fini_cpu_amd,
499 };
500
501 static int __init microcode_amd_module_init(void)
502 {
503         struct cpuinfo_x86 *c = &cpu_data(0);
504
505         equiv_cpu_table = NULL;
506         if (c->x86_vendor != X86_VENDOR_AMD) {
507                 printk(KERN_ERR "microcode: CPU platform is not AMD-capable\n");
508                 return -ENODEV;
509         }
510
511         return microcode_init(&microcode_amd_ops, THIS_MODULE);
512 }
513
514 static void __exit microcode_amd_module_exit(void)
515 {
516         microcode_exit();
517 }
518
519 module_init(microcode_amd_module_init)
520 module_exit(microcode_amd_module_exit)