]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/x86/kernel/cpu/microcode/core.c
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[karo-tx-linux.git] / arch / x86 / kernel / cpu / microcode / core.c
1 /*
2  * CPU Microcode Update Driver for Linux
3  *
4  * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
5  *            2006      Shaohua Li <shaohua.li@intel.com>
6  *            2013-2015 Borislav Petkov <bp@alien8.de>
7  *
8  * This driver allows to upgrade microcode on x86 processors.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version
13  * 2 of the License, or (at your option) any later version.
14  */
15
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18 #include <linux/platform_device.h>
19 #include <linux/miscdevice.h>
20 #include <linux/capability.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/mutex.h>
24 #include <linux/cpu.h>
25 #include <linux/fs.h>
26 #include <linux/mm.h>
27 #include <linux/syscore_ops.h>
28
29 #include <asm/microcode.h>
30 #include <asm/processor.h>
31 #include <asm/cpu_device_id.h>
32 #include <asm/perf_event.h>
33
34 MODULE_DESCRIPTION("Microcode Update Driver");
35 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
36 MODULE_LICENSE("GPL");
37
38 #define MICROCODE_VERSION       "2.00"
39
40 static struct microcode_ops     *microcode_ops;
41
42 bool dis_ucode_ldr;
43 module_param(dis_ucode_ldr, bool, 0);
44
45 /*
46  * Synchronization.
47  *
48  * All non cpu-hotplug-callback call sites use:
49  *
50  * - microcode_mutex to synchronize with each other;
51  * - get/put_online_cpus() to synchronize with
52  *   the cpu-hotplug-callback call sites.
53  *
54  * We guarantee that only a single cpu is being
55  * updated at any particular moment of time.
56  */
57 static DEFINE_MUTEX(microcode_mutex);
58
59 struct ucode_cpu_info           ucode_cpu_info[NR_CPUS];
60 EXPORT_SYMBOL_GPL(ucode_cpu_info);
61
62 /*
63  * Operations that are run on a target cpu:
64  */
65
66 struct cpu_info_ctx {
67         struct cpu_signature    *cpu_sig;
68         int                     err;
69 };
70
71 static void collect_cpu_info_local(void *arg)
72 {
73         struct cpu_info_ctx *ctx = arg;
74
75         ctx->err = microcode_ops->collect_cpu_info(smp_processor_id(),
76                                                    ctx->cpu_sig);
77 }
78
79 static int collect_cpu_info_on_target(int cpu, struct cpu_signature *cpu_sig)
80 {
81         struct cpu_info_ctx ctx = { .cpu_sig = cpu_sig, .err = 0 };
82         int ret;
83
84         ret = smp_call_function_single(cpu, collect_cpu_info_local, &ctx, 1);
85         if (!ret)
86                 ret = ctx.err;
87
88         return ret;
89 }
90
91 static int collect_cpu_info(int cpu)
92 {
93         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
94         int ret;
95
96         memset(uci, 0, sizeof(*uci));
97
98         ret = collect_cpu_info_on_target(cpu, &uci->cpu_sig);
99         if (!ret)
100                 uci->valid = 1;
101
102         return ret;
103 }
104
105 struct apply_microcode_ctx {
106         int err;
107 };
108
109 static void apply_microcode_local(void *arg)
110 {
111         struct apply_microcode_ctx *ctx = arg;
112
113         ctx->err = microcode_ops->apply_microcode(smp_processor_id());
114 }
115
116 static int apply_microcode_on_target(int cpu)
117 {
118         struct apply_microcode_ctx ctx = { .err = 0 };
119         int ret;
120
121         ret = smp_call_function_single(cpu, apply_microcode_local, &ctx, 1);
122         if (!ret)
123                 ret = ctx.err;
124
125         return ret;
126 }
127
128 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
129 static int do_microcode_update(const void __user *buf, size_t size)
130 {
131         int error = 0;
132         int cpu;
133
134         for_each_online_cpu(cpu) {
135                 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
136                 enum ucode_state ustate;
137
138                 if (!uci->valid)
139                         continue;
140
141                 ustate = microcode_ops->request_microcode_user(cpu, buf, size);
142                 if (ustate == UCODE_ERROR) {
143                         error = -1;
144                         break;
145                 } else if (ustate == UCODE_OK)
146                         apply_microcode_on_target(cpu);
147         }
148
149         return error;
150 }
151
152 static int microcode_open(struct inode *inode, struct file *file)
153 {
154         return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM;
155 }
156
157 static ssize_t microcode_write(struct file *file, const char __user *buf,
158                                size_t len, loff_t *ppos)
159 {
160         ssize_t ret = -EINVAL;
161
162         if ((len >> PAGE_SHIFT) > totalram_pages) {
163                 pr_err("too much data (max %ld pages)\n", totalram_pages);
164                 return ret;
165         }
166
167         get_online_cpus();
168         mutex_lock(&microcode_mutex);
169
170         if (do_microcode_update(buf, len) == 0)
171                 ret = (ssize_t)len;
172
173         if (ret > 0)
174                 perf_check_microcode();
175
176         mutex_unlock(&microcode_mutex);
177         put_online_cpus();
178
179         return ret;
180 }
181
182 static const struct file_operations microcode_fops = {
183         .owner                  = THIS_MODULE,
184         .write                  = microcode_write,
185         .open                   = microcode_open,
186         .llseek         = no_llseek,
187 };
188
189 static struct miscdevice microcode_dev = {
190         .minor                  = MICROCODE_MINOR,
191         .name                   = "microcode",
192         .nodename               = "cpu/microcode",
193         .fops                   = &microcode_fops,
194 };
195
196 static int __init microcode_dev_init(void)
197 {
198         int error;
199
200         error = misc_register(&microcode_dev);
201         if (error) {
202                 pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR);
203                 return error;
204         }
205
206         return 0;
207 }
208
209 static void __exit microcode_dev_exit(void)
210 {
211         misc_deregister(&microcode_dev);
212 }
213
214 MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
215 MODULE_ALIAS("devname:cpu/microcode");
216 #else
217 #define microcode_dev_init()    0
218 #define microcode_dev_exit()    do { } while (0)
219 #endif
220
221 /* fake device for request_firmware */
222 static struct platform_device   *microcode_pdev;
223
224 static int reload_for_cpu(int cpu)
225 {
226         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
227         enum ucode_state ustate;
228         int err = 0;
229
230         if (!uci->valid)
231                 return err;
232
233         ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
234         if (ustate == UCODE_OK)
235                 apply_microcode_on_target(cpu);
236         else
237                 if (ustate == UCODE_ERROR)
238                         err = -EINVAL;
239         return err;
240 }
241
242 static ssize_t reload_store(struct device *dev,
243                             struct device_attribute *attr,
244                             const char *buf, size_t size)
245 {
246         unsigned long val;
247         int cpu;
248         ssize_t ret = 0, tmp_ret;
249
250         ret = kstrtoul(buf, 0, &val);
251         if (ret)
252                 return ret;
253
254         if (val != 1)
255                 return size;
256
257         get_online_cpus();
258         mutex_lock(&microcode_mutex);
259         for_each_online_cpu(cpu) {
260                 tmp_ret = reload_for_cpu(cpu);
261                 if (tmp_ret != 0)
262                         pr_warn("Error reloading microcode on CPU %d\n", cpu);
263
264                 /* save retval of the first encountered reload error */
265                 if (!ret)
266                         ret = tmp_ret;
267         }
268         if (!ret)
269                 perf_check_microcode();
270         mutex_unlock(&microcode_mutex);
271         put_online_cpus();
272
273         if (!ret)
274                 ret = size;
275
276         return ret;
277 }
278
279 static ssize_t version_show(struct device *dev,
280                         struct device_attribute *attr, char *buf)
281 {
282         struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
283
284         return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
285 }
286
287 static ssize_t pf_show(struct device *dev,
288                         struct device_attribute *attr, char *buf)
289 {
290         struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
291
292         return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
293 }
294
295 static DEVICE_ATTR(reload, 0200, NULL, reload_store);
296 static DEVICE_ATTR(version, 0400, version_show, NULL);
297 static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
298
299 static struct attribute *mc_default_attrs[] = {
300         &dev_attr_version.attr,
301         &dev_attr_processor_flags.attr,
302         NULL
303 };
304
305 static struct attribute_group mc_attr_group = {
306         .attrs                  = mc_default_attrs,
307         .name                   = "microcode",
308 };
309
310 static void microcode_fini_cpu(int cpu)
311 {
312         microcode_ops->microcode_fini_cpu(cpu);
313 }
314
315 static enum ucode_state microcode_resume_cpu(int cpu)
316 {
317         pr_debug("CPU%d updated upon resume\n", cpu);
318
319         if (apply_microcode_on_target(cpu))
320                 return UCODE_ERROR;
321
322         return UCODE_OK;
323 }
324
325 static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
326 {
327         enum ucode_state ustate;
328         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
329
330         if (uci && uci->valid)
331                 return UCODE_OK;
332
333         if (collect_cpu_info(cpu))
334                 return UCODE_ERROR;
335
336         /* --dimm. Trigger a delayed update? */
337         if (system_state != SYSTEM_RUNNING)
338                 return UCODE_NFOUND;
339
340         ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev,
341                                                      refresh_fw);
342
343         if (ustate == UCODE_OK) {
344                 pr_debug("CPU%d updated upon init\n", cpu);
345                 apply_microcode_on_target(cpu);
346         }
347
348         return ustate;
349 }
350
351 static enum ucode_state microcode_update_cpu(int cpu)
352 {
353         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
354
355         if (uci->valid)
356                 return microcode_resume_cpu(cpu);
357
358         return microcode_init_cpu(cpu, false);
359 }
360
361 static int mc_device_add(struct device *dev, struct subsys_interface *sif)
362 {
363         int err, cpu = dev->id;
364
365         if (!cpu_online(cpu))
366                 return 0;
367
368         pr_debug("CPU%d added\n", cpu);
369
370         err = sysfs_create_group(&dev->kobj, &mc_attr_group);
371         if (err)
372                 return err;
373
374         if (microcode_init_cpu(cpu, true) == UCODE_ERROR)
375                 return -EINVAL;
376
377         return err;
378 }
379
380 static void mc_device_remove(struct device *dev, struct subsys_interface *sif)
381 {
382         int cpu = dev->id;
383
384         if (!cpu_online(cpu))
385                 return;
386
387         pr_debug("CPU%d removed\n", cpu);
388         microcode_fini_cpu(cpu);
389         sysfs_remove_group(&dev->kobj, &mc_attr_group);
390 }
391
392 static struct subsys_interface mc_cpu_interface = {
393         .name                   = "microcode",
394         .subsys                 = &cpu_subsys,
395         .add_dev                = mc_device_add,
396         .remove_dev             = mc_device_remove,
397 };
398
399 /**
400  * mc_bp_resume - Update boot CPU microcode during resume.
401  */
402 static void mc_bp_resume(void)
403 {
404         int cpu = smp_processor_id();
405         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
406
407         if (uci->valid && uci->mc)
408                 microcode_ops->apply_microcode(cpu);
409         else if (!uci->mc)
410                 reload_early_microcode();
411 }
412
413 static struct syscore_ops mc_syscore_ops = {
414         .resume                 = mc_bp_resume,
415 };
416
417 static int
418 mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
419 {
420         unsigned int cpu = (unsigned long)hcpu;
421         struct device *dev;
422
423         dev = get_cpu_device(cpu);
424
425         switch (action & ~CPU_TASKS_FROZEN) {
426         case CPU_ONLINE:
427                 microcode_update_cpu(cpu);
428                 pr_debug("CPU%d added\n", cpu);
429                 /*
430                  * "break" is missing on purpose here because we want to fall
431                  * through in order to create the sysfs group.
432                  */
433
434         case CPU_DOWN_FAILED:
435                 if (sysfs_create_group(&dev->kobj, &mc_attr_group))
436                         pr_err("Failed to create group for CPU%d\n", cpu);
437                 break;
438
439         case CPU_DOWN_PREPARE:
440                 /* Suspend is in progress, only remove the interface */
441                 sysfs_remove_group(&dev->kobj, &mc_attr_group);
442                 pr_debug("CPU%d removed\n", cpu);
443                 break;
444
445         /*
446          * case CPU_DEAD:
447          *
448          * When a CPU goes offline, don't free up or invalidate the copy of
449          * the microcode in kernel memory, so that we can reuse it when the
450          * CPU comes back online without unnecessarily requesting the userspace
451          * for it again.
452          */
453         }
454
455         /* The CPU refused to come up during a system resume */
456         if (action == CPU_UP_CANCELED_FROZEN)
457                 microcode_fini_cpu(cpu);
458
459         return NOTIFY_OK;
460 }
461
462 static struct notifier_block mc_cpu_notifier = {
463         .notifier_call  = mc_cpu_callback,
464 };
465
466 #ifdef MODULE
467 /* Autoload on Intel and AMD systems */
468 static const struct x86_cpu_id __initconst microcode_id[] = {
469 #ifdef CONFIG_MICROCODE_INTEL
470         { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, },
471 #endif
472 #ifdef CONFIG_MICROCODE_AMD
473         { X86_VENDOR_AMD, X86_FAMILY_ANY, X86_MODEL_ANY, },
474 #endif
475         {}
476 };
477 MODULE_DEVICE_TABLE(x86cpu, microcode_id);
478 #endif
479
480 static struct attribute *cpu_root_microcode_attrs[] = {
481         &dev_attr_reload.attr,
482         NULL
483 };
484
485 static struct attribute_group cpu_root_microcode_group = {
486         .name  = "microcode",
487         .attrs = cpu_root_microcode_attrs,
488 };
489
490 static int __init microcode_init(void)
491 {
492         struct cpuinfo_x86 *c = &cpu_data(0);
493         int error;
494
495         if (paravirt_enabled() || dis_ucode_ldr)
496                 return -EINVAL;
497
498         if (c->x86_vendor == X86_VENDOR_INTEL)
499                 microcode_ops = init_intel_microcode();
500         else if (c->x86_vendor == X86_VENDOR_AMD)
501                 microcode_ops = init_amd_microcode();
502         else
503                 pr_err("no support for this CPU vendor\n");
504
505         if (!microcode_ops)
506                 return -ENODEV;
507
508         microcode_pdev = platform_device_register_simple("microcode", -1,
509                                                          NULL, 0);
510         if (IS_ERR(microcode_pdev))
511                 return PTR_ERR(microcode_pdev);
512
513         get_online_cpus();
514         mutex_lock(&microcode_mutex);
515
516         error = subsys_interface_register(&mc_cpu_interface);
517         if (!error)
518                 perf_check_microcode();
519         mutex_unlock(&microcode_mutex);
520         put_online_cpus();
521
522         if (error)
523                 goto out_pdev;
524
525         error = sysfs_create_group(&cpu_subsys.dev_root->kobj,
526                                    &cpu_root_microcode_group);
527
528         if (error) {
529                 pr_err("Error creating microcode group!\n");
530                 goto out_driver;
531         }
532
533         error = microcode_dev_init();
534         if (error)
535                 goto out_ucode_group;
536
537         register_syscore_ops(&mc_syscore_ops);
538         register_hotcpu_notifier(&mc_cpu_notifier);
539
540         pr_info("Microcode Update Driver: v" MICROCODE_VERSION
541                 " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
542
543         return 0;
544
545  out_ucode_group:
546         sysfs_remove_group(&cpu_subsys.dev_root->kobj,
547                            &cpu_root_microcode_group);
548
549  out_driver:
550         get_online_cpus();
551         mutex_lock(&microcode_mutex);
552
553         subsys_interface_unregister(&mc_cpu_interface);
554
555         mutex_unlock(&microcode_mutex);
556         put_online_cpus();
557
558  out_pdev:
559         platform_device_unregister(microcode_pdev);
560         return error;
561
562 }
563 module_init(microcode_init);
564
565 static void __exit microcode_exit(void)
566 {
567         struct cpuinfo_x86 *c = &cpu_data(0);
568
569         microcode_dev_exit();
570
571         unregister_hotcpu_notifier(&mc_cpu_notifier);
572         unregister_syscore_ops(&mc_syscore_ops);
573
574         sysfs_remove_group(&cpu_subsys.dev_root->kobj,
575                            &cpu_root_microcode_group);
576
577         get_online_cpus();
578         mutex_lock(&microcode_mutex);
579
580         subsys_interface_unregister(&mc_cpu_interface);
581
582         mutex_unlock(&microcode_mutex);
583         put_online_cpus();
584
585         platform_device_unregister(microcode_pdev);
586
587         microcode_ops = NULL;
588
589         if (c->x86_vendor == X86_VENDOR_AMD)
590                 exit_amd_microcode();
591
592         pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
593 }
594 module_exit(microcode_exit);