]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/x86/kernel/cpu/microcode/core.c
Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[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 int mc_device_remove(struct device *dev, struct subsys_interface *sif)
381 {
382         int cpu = dev->id;
383
384         if (!cpu_online(cpu))
385                 return 0;
386
387         pr_debug("CPU%d removed\n", cpu);
388         microcode_fini_cpu(cpu);
389         sysfs_remove_group(&dev->kobj, &mc_attr_group);
390         return 0;
391 }
392
393 static struct subsys_interface mc_cpu_interface = {
394         .name                   = "microcode",
395         .subsys                 = &cpu_subsys,
396         .add_dev                = mc_device_add,
397         .remove_dev             = mc_device_remove,
398 };
399
400 /**
401  * mc_bp_resume - Update boot CPU microcode during resume.
402  */
403 static void mc_bp_resume(void)
404 {
405         int cpu = smp_processor_id();
406         struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
407
408         if (uci->valid && uci->mc)
409                 microcode_ops->apply_microcode(cpu);
410         else if (!uci->mc)
411                 reload_early_microcode();
412 }
413
414 static struct syscore_ops mc_syscore_ops = {
415         .resume                 = mc_bp_resume,
416 };
417
418 static int
419 mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
420 {
421         unsigned int cpu = (unsigned long)hcpu;
422         struct device *dev;
423
424         dev = get_cpu_device(cpu);
425
426         switch (action & ~CPU_TASKS_FROZEN) {
427         case CPU_ONLINE:
428                 microcode_update_cpu(cpu);
429                 pr_debug("CPU%d added\n", cpu);
430                 /*
431                  * "break" is missing on purpose here because we want to fall
432                  * through in order to create the sysfs group.
433                  */
434
435         case CPU_DOWN_FAILED:
436                 if (sysfs_create_group(&dev->kobj, &mc_attr_group))
437                         pr_err("Failed to create group for CPU%d\n", cpu);
438                 break;
439
440         case CPU_DOWN_PREPARE:
441                 /* Suspend is in progress, only remove the interface */
442                 sysfs_remove_group(&dev->kobj, &mc_attr_group);
443                 pr_debug("CPU%d removed\n", cpu);
444                 break;
445
446         /*
447          * case CPU_DEAD:
448          *
449          * When a CPU goes offline, don't free up or invalidate the copy of
450          * the microcode in kernel memory, so that we can reuse it when the
451          * CPU comes back online without unnecessarily requesting the userspace
452          * for it again.
453          */
454         }
455
456         /* The CPU refused to come up during a system resume */
457         if (action == CPU_UP_CANCELED_FROZEN)
458                 microcode_fini_cpu(cpu);
459
460         return NOTIFY_OK;
461 }
462
463 static struct notifier_block __refdata mc_cpu_notifier = {
464         .notifier_call  = mc_cpu_callback,
465 };
466
467 #ifdef MODULE
468 /* Autoload on Intel and AMD systems */
469 static const struct x86_cpu_id __initconst microcode_id[] = {
470 #ifdef CONFIG_MICROCODE_INTEL
471         { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, },
472 #endif
473 #ifdef CONFIG_MICROCODE_AMD
474         { X86_VENDOR_AMD, X86_FAMILY_ANY, X86_MODEL_ANY, },
475 #endif
476         {}
477 };
478 MODULE_DEVICE_TABLE(x86cpu, microcode_id);
479 #endif
480
481 static struct attribute *cpu_root_microcode_attrs[] = {
482         &dev_attr_reload.attr,
483         NULL
484 };
485
486 static struct attribute_group cpu_root_microcode_group = {
487         .name  = "microcode",
488         .attrs = cpu_root_microcode_attrs,
489 };
490
491 static int __init microcode_init(void)
492 {
493         struct cpuinfo_x86 *c = &cpu_data(0);
494         int error;
495
496         if (paravirt_enabled() || dis_ucode_ldr)
497                 return -EINVAL;
498
499         if (c->x86_vendor == X86_VENDOR_INTEL)
500                 microcode_ops = init_intel_microcode();
501         else if (c->x86_vendor == X86_VENDOR_AMD)
502                 microcode_ops = init_amd_microcode();
503         else
504                 pr_err("no support for this CPU vendor\n");
505
506         if (!microcode_ops)
507                 return -ENODEV;
508
509         microcode_pdev = platform_device_register_simple("microcode", -1,
510                                                          NULL, 0);
511         if (IS_ERR(microcode_pdev))
512                 return PTR_ERR(microcode_pdev);
513
514         get_online_cpus();
515         mutex_lock(&microcode_mutex);
516
517         error = subsys_interface_register(&mc_cpu_interface);
518         if (!error)
519                 perf_check_microcode();
520         mutex_unlock(&microcode_mutex);
521         put_online_cpus();
522
523         if (error)
524                 goto out_pdev;
525
526         error = sysfs_create_group(&cpu_subsys.dev_root->kobj,
527                                    &cpu_root_microcode_group);
528
529         if (error) {
530                 pr_err("Error creating microcode group!\n");
531                 goto out_driver;
532         }
533
534         error = microcode_dev_init();
535         if (error)
536                 goto out_ucode_group;
537
538         register_syscore_ops(&mc_syscore_ops);
539         register_hotcpu_notifier(&mc_cpu_notifier);
540
541         pr_info("Microcode Update Driver: v" MICROCODE_VERSION
542                 " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
543
544         return 0;
545
546  out_ucode_group:
547         sysfs_remove_group(&cpu_subsys.dev_root->kobj,
548                            &cpu_root_microcode_group);
549
550  out_driver:
551         get_online_cpus();
552         mutex_lock(&microcode_mutex);
553
554         subsys_interface_unregister(&mc_cpu_interface);
555
556         mutex_unlock(&microcode_mutex);
557         put_online_cpus();
558
559  out_pdev:
560         platform_device_unregister(microcode_pdev);
561         return error;
562
563 }
564 module_init(microcode_init);
565
566 static void __exit microcode_exit(void)
567 {
568         struct cpuinfo_x86 *c = &cpu_data(0);
569
570         microcode_dev_exit();
571
572         unregister_hotcpu_notifier(&mc_cpu_notifier);
573         unregister_syscore_ops(&mc_syscore_ops);
574
575         sysfs_remove_group(&cpu_subsys.dev_root->kobj,
576                            &cpu_root_microcode_group);
577
578         get_online_cpus();
579         mutex_lock(&microcode_mutex);
580
581         subsys_interface_unregister(&mc_cpu_interface);
582
583         mutex_unlock(&microcode_mutex);
584         put_online_cpus();
585
586         platform_device_unregister(microcode_pdev);
587
588         microcode_ops = NULL;
589
590         if (c->x86_vendor == X86_VENDOR_AMD)
591                 exit_amd_microcode();
592
593         pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
594 }
595 module_exit(microcode_exit);