bus: subsys: update return type of ->remove_dev() to void
[deliverable/linux.git] / arch / x86 / kernel / cpu / microcode / core.c
CommitLineData
3e135d88 1/*
6b44e72a 2 * CPU Microcode Update Driver for Linux
3e135d88 3 *
6b44e72a
BP
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>
3e135d88 7 *
6b44e72a 8 * This driver allows to upgrade microcode on x86 processors.
3e135d88 9 *
6b44e72a
BP
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.
3e135d88 14 */
f58e1f53
JP
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
4bae1967 18#include <linux/platform_device.h>
4bae1967 19#include <linux/miscdevice.h>
871b72dd 20#include <linux/capability.h>
4bae1967
IM
21#include <linux/kernel.h>
22#include <linux/module.h>
3e135d88
PO
23#include <linux/mutex.h>
24#include <linux/cpu.h>
4bae1967
IM
25#include <linux/fs.h>
26#include <linux/mm.h>
f3c6ea1b 27#include <linux/syscore_ops.h>
3e135d88 28
3e135d88 29#include <asm/microcode.h>
4bae1967 30#include <asm/processor.h>
78ff123b 31#include <asm/cpu_device_id.h>
c93dc84c 32#include <asm/perf_event.h>
3e135d88
PO
33
34MODULE_DESCRIPTION("Microcode Update Driver");
35MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
36MODULE_LICENSE("GPL");
37
4bae1967 38#define MICROCODE_VERSION "2.00"
3e135d88 39
4bae1967 40static struct microcode_ops *microcode_ops;
3e135d88 41
65cef131
BP
42bool dis_ucode_ldr;
43module_param(dis_ucode_ldr, bool, 0);
44
871b72dd
DA
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 */
d45de409 57static DEFINE_MUTEX(microcode_mutex);
3e135d88 58
4bae1967 59struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
8d86f390 60EXPORT_SYMBOL_GPL(ucode_cpu_info);
3e135d88 61
871b72dd
DA
62/*
63 * Operations that are run on a target cpu:
64 */
65
66struct cpu_info_ctx {
67 struct cpu_signature *cpu_sig;
68 int err;
69};
70
71static 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
79static 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
91static 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
105struct apply_microcode_ctx {
106 int err;
107};
108
109static 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
116static 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
3e135d88 128#ifdef CONFIG_MICROCODE_OLD_INTERFACE
a0a29b62 129static int do_microcode_update(const void __user *buf, size_t size)
3e135d88 130{
3e135d88 131 int error = 0;
3e135d88 132 int cpu;
6f66cbc6 133
a0a29b62
DA
134 for_each_online_cpu(cpu) {
135 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
871b72dd 136 enum ucode_state ustate;
a0a29b62
DA
137
138 if (!uci->valid)
139 continue;
6f66cbc6 140
871b72dd
DA
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);
3e135d88 147 }
871b72dd 148
3e135d88
PO
149 return error;
150}
151
3f10940e 152static int microcode_open(struct inode *inode, struct file *file)
3e135d88 153{
3f10940e 154 return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM;
3e135d88
PO
155}
156
d33dcb9e
PO
157static ssize_t microcode_write(struct file *file, const char __user *buf,
158 size_t len, loff_t *ppos)
3e135d88 159{
871b72dd 160 ssize_t ret = -EINVAL;
3e135d88 161
4481374c 162 if ((len >> PAGE_SHIFT) > totalram_pages) {
f58e1f53 163 pr_err("too much data (max %ld pages)\n", totalram_pages);
871b72dd 164 return ret;
3e135d88
PO
165 }
166
167 get_online_cpus();
168 mutex_lock(&microcode_mutex);
169
871b72dd 170 if (do_microcode_update(buf, len) == 0)
3e135d88
PO
171 ret = (ssize_t)len;
172
e3e45c01
SE
173 if (ret > 0)
174 perf_check_microcode();
175
3e135d88
PO
176 mutex_unlock(&microcode_mutex);
177 put_online_cpus();
178
179 return ret;
180}
181
182static const struct file_operations microcode_fops = {
871b72dd
DA
183 .owner = THIS_MODULE,
184 .write = microcode_write,
185 .open = microcode_open,
6038f373 186 .llseek = no_llseek,
3e135d88
PO
187};
188
189static struct miscdevice microcode_dev = {
871b72dd
DA
190 .minor = MICROCODE_MINOR,
191 .name = "microcode",
e454cea2 192 .nodename = "cpu/microcode",
871b72dd 193 .fops = &microcode_fops,
3e135d88
PO
194};
195
d33dcb9e 196static int __init microcode_dev_init(void)
3e135d88
PO
197{
198 int error;
199
200 error = misc_register(&microcode_dev);
201 if (error) {
f58e1f53 202 pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR);
3e135d88
PO
203 return error;
204 }
205
206 return 0;
207}
208
bd399063 209static void __exit microcode_dev_exit(void)
3e135d88
PO
210{
211 misc_deregister(&microcode_dev);
212}
213
214MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
578454ff 215MODULE_ALIAS("devname:cpu/microcode");
3e135d88 216#else
4bae1967
IM
217#define microcode_dev_init() 0
218#define microcode_dev_exit() do { } while (0)
3e135d88
PO
219#endif
220
221/* fake device for request_firmware */
4bae1967 222static struct platform_device *microcode_pdev;
3e135d88 223
871b72dd 224static int reload_for_cpu(int cpu)
af5c820a 225{
871b72dd 226 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
4dbf32c3 227 enum ucode_state ustate;
af5c820a
RR
228 int err = 0;
229
4dbf32c3
BP
230 if (!uci->valid)
231 return err;
871b72dd 232
48e30685 233 ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
4dbf32c3
BP
234 if (ustate == UCODE_OK)
235 apply_microcode_on_target(cpu);
236 else
237 if (ustate == UCODE_ERROR)
238 err = -EINVAL;
af5c820a
RR
239 return err;
240}
241
8a25a2fd
KS
242static ssize_t reload_store(struct device *dev,
243 struct device_attribute *attr,
871b72dd 244 const char *buf, size_t size)
3e135d88 245{
871b72dd 246 unsigned long val;
c9fc3f77
BP
247 int cpu;
248 ssize_t ret = 0, tmp_ret;
249
e826abd5
SK
250 ret = kstrtoul(buf, 0, &val);
251 if (ret)
252 return ret;
871b72dd 253
c9fc3f77
BP
254 if (val != 1)
255 return size;
256
257 get_online_cpus();
c93dc84c 258 mutex_lock(&microcode_mutex);
c9fc3f77
BP
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;
3e135d88 267 }
c93dc84c
PZ
268 if (!ret)
269 perf_check_microcode();
270 mutex_unlock(&microcode_mutex);
c9fc3f77 271 put_online_cpus();
871b72dd
DA
272
273 if (!ret)
274 ret = size;
275
276 return ret;
3e135d88
PO
277}
278
8a25a2fd
KS
279static ssize_t version_show(struct device *dev,
280 struct device_attribute *attr, char *buf)
3e135d88
PO
281{
282 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
283
d45de409 284 return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
3e135d88
PO
285}
286
8a25a2fd
KS
287static ssize_t pf_show(struct device *dev,
288 struct device_attribute *attr, char *buf)
3e135d88
PO
289{
290 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
291
d45de409 292 return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
3e135d88
PO
293}
294
8a25a2fd
KS
295static DEVICE_ATTR(reload, 0200, NULL, reload_store);
296static DEVICE_ATTR(version, 0400, version_show, NULL);
297static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
3e135d88
PO
298
299static struct attribute *mc_default_attrs[] = {
8a25a2fd
KS
300 &dev_attr_version.attr,
301 &dev_attr_processor_flags.attr,
3e135d88
PO
302 NULL
303};
304
305static struct attribute_group mc_attr_group = {
871b72dd
DA
306 .attrs = mc_default_attrs,
307 .name = "microcode",
3e135d88
PO
308};
309
871b72dd 310static void microcode_fini_cpu(int cpu)
d45de409 311{
d45de409 312 microcode_ops->microcode_fini_cpu(cpu);
280a9ca5
DA
313}
314
871b72dd 315static enum ucode_state microcode_resume_cpu(int cpu)
d45de409 316{
f58e1f53 317 pr_debug("CPU%d updated upon resume\n", cpu);
bb9d3e47
BP
318
319 if (apply_microcode_on_target(cpu))
320 return UCODE_ERROR;
871b72dd
DA
321
322 return UCODE_OK;
d45de409
DA
323}
324
48e30685 325static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
d45de409 326{
871b72dd 327 enum ucode_state ustate;
9cd4d78e
FY
328 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
329
330 if (uci && uci->valid)
331 return UCODE_OK;
d45de409 332
871b72dd
DA
333 if (collect_cpu_info(cpu))
334 return UCODE_ERROR;
d45de409 335
871b72dd
DA
336 /* --dimm. Trigger a delayed update? */
337 if (system_state != SYSTEM_RUNNING)
338 return UCODE_NFOUND;
d45de409 339
48e30685
BP
340 ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev,
341 refresh_fw);
d45de409 342
871b72dd 343 if (ustate == UCODE_OK) {
f58e1f53 344 pr_debug("CPU%d updated upon init\n", cpu);
871b72dd 345 apply_microcode_on_target(cpu);
d45de409
DA
346 }
347
871b72dd 348 return ustate;
d45de409
DA
349}
350
871b72dd 351static enum ucode_state microcode_update_cpu(int cpu)
d45de409 352{
871b72dd 353 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
d45de409 354
2f99f5c8 355 if (uci->valid)
bb9d3e47 356 return microcode_resume_cpu(cpu);
d45de409 357
48e30685 358 return microcode_init_cpu(cpu, false);
d45de409
DA
359}
360
8a25a2fd 361static int mc_device_add(struct device *dev, struct subsys_interface *sif)
3e135d88 362{
8a25a2fd 363 int err, cpu = dev->id;
3e135d88
PO
364
365 if (!cpu_online(cpu))
366 return 0;
367
f58e1f53 368 pr_debug("CPU%d added\n", cpu);
3e135d88 369
8a25a2fd 370 err = sysfs_create_group(&dev->kobj, &mc_attr_group);
3e135d88
PO
371 if (err)
372 return err;
373
48e30685 374 if (microcode_init_cpu(cpu, true) == UCODE_ERROR)
6c53cbfc 375 return -EINVAL;
af5c820a
RR
376
377 return err;
3e135d88
PO
378}
379
71db87ba 380static void mc_device_remove(struct device *dev, struct subsys_interface *sif)
3e135d88 381{
8a25a2fd 382 int cpu = dev->id;
3e135d88
PO
383
384 if (!cpu_online(cpu))
71db87ba 385 return;
3e135d88 386
f58e1f53 387 pr_debug("CPU%d removed\n", cpu);
d45de409 388 microcode_fini_cpu(cpu);
8a25a2fd 389 sysfs_remove_group(&dev->kobj, &mc_attr_group);
3e135d88
PO
390}
391
8a25a2fd
KS
392static 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,
f3c6ea1b
RW
397};
398
399/**
400 * mc_bp_resume - Update boot CPU microcode during resume.
401 */
402static void mc_bp_resume(void)
3e135d88 403{
f3c6ea1b 404 int cpu = smp_processor_id();
871b72dd 405 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
3e135d88 406
871b72dd
DA
407 if (uci->valid && uci->mc)
408 microcode_ops->apply_microcode(cpu);
fb86b973 409 else if (!uci->mc)
fbae4ba8 410 reload_early_microcode();
3e135d88
PO
411}
412
f3c6ea1b
RW
413static struct syscore_ops mc_syscore_ops = {
414 .resume = mc_bp_resume,
3e135d88
PO
415};
416
148f9bb8 417static int
3e135d88
PO
418mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
419{
420 unsigned int cpu = (unsigned long)hcpu;
8a25a2fd 421 struct device *dev;
3e135d88 422
8a25a2fd 423 dev = get_cpu_device(cpu);
09c3f0d8
BP
424
425 switch (action & ~CPU_TASKS_FROZEN) {
3e135d88 426 case CPU_ONLINE:
871b72dd 427 microcode_update_cpu(cpu);
f58e1f53 428 pr_debug("CPU%d added\n", cpu);
09c3f0d8
BP
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:
8a25a2fd 435 if (sysfs_create_group(&dev->kobj, &mc_attr_group))
f58e1f53 436 pr_err("Failed to create group for CPU%d\n", cpu);
3e135d88 437 break;
09c3f0d8 438
3e135d88 439 case CPU_DOWN_PREPARE:
3e135d88 440 /* Suspend is in progress, only remove the interface */
8a25a2fd 441 sysfs_remove_group(&dev->kobj, &mc_attr_group);
f58e1f53 442 pr_debug("CPU%d removed\n", cpu);
d45de409 443 break;
70989449
SB
444
445 /*
09c3f0d8
BP
446 * case CPU_DEAD:
447 *
70989449
SB
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 */
3e135d88 453 }
09c3f0d8
BP
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
3e135d88
PO
459 return NOTIFY_OK;
460}
461
462static struct notifier_block __refdata mc_cpu_notifier = {
4bae1967 463 .notifier_call = mc_cpu_callback,
3e135d88
PO
464};
465
78ff123b
AK
466#ifdef MODULE
467/* Autoload on Intel and AMD systems */
e1b6fc55 468static const struct x86_cpu_id __initconst microcode_id[] = {
78ff123b
AK
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};
477MODULE_DEVICE_TABLE(x86cpu, microcode_id);
478#endif
479
3d8986bc
BP
480static struct attribute *cpu_root_microcode_attrs[] = {
481 &dev_attr_reload.attr,
482 NULL
483};
484
485static struct attribute_group cpu_root_microcode_group = {
486 .name = "microcode",
487 .attrs = cpu_root_microcode_attrs,
488};
489
18dbc916 490static int __init microcode_init(void)
3e135d88 491{
18dbc916 492 struct cpuinfo_x86 *c = &cpu_data(0);
3e135d88
PO
493 int error;
494
a18a0f68 495 if (paravirt_enabled() || dis_ucode_ldr)
da63865a 496 return -EINVAL;
65cef131 497
18dbc916
DA
498 if (c->x86_vendor == X86_VENDOR_INTEL)
499 microcode_ops = init_intel_microcode();
82b07865 500 else if (c->x86_vendor == X86_VENDOR_AMD)
18dbc916 501 microcode_ops = init_amd_microcode();
283c1f25 502 else
f58e1f53 503 pr_err("no support for this CPU vendor\n");
283c1f25
AH
504
505 if (!microcode_ops)
18dbc916 506 return -ENODEV;
3e135d88 507
3e135d88
PO
508 microcode_pdev = platform_device_register_simple("microcode", -1,
509 NULL, 0);
bd399063 510 if (IS_ERR(microcode_pdev))
3e135d88 511 return PTR_ERR(microcode_pdev);
3e135d88
PO
512
513 get_online_cpus();
871b72dd
DA
514 mutex_lock(&microcode_mutex);
515
8a25a2fd 516 error = subsys_interface_register(&mc_cpu_interface);
c93dc84c
PZ
517 if (!error)
518 perf_check_microcode();
871b72dd 519 mutex_unlock(&microcode_mutex);
3e135d88 520 put_online_cpus();
871b72dd 521
bd399063
SB
522 if (error)
523 goto out_pdev;
3e135d88 524
3d8986bc
BP
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
871b72dd
DA
533 error = microcode_dev_init();
534 if (error)
3d8986bc 535 goto out_ucode_group;
871b72dd 536
f3c6ea1b 537 register_syscore_ops(&mc_syscore_ops);
3e135d88 538 register_hotcpu_notifier(&mc_cpu_notifier);
8d86f390 539
871b72dd 540 pr_info("Microcode Update Driver: v" MICROCODE_VERSION
f58e1f53 541 " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
8d86f390 542
3e135d88 543 return 0;
bd399063 544
3d8986bc
BP
545 out_ucode_group:
546 sysfs_remove_group(&cpu_subsys.dev_root->kobj,
547 &cpu_root_microcode_group);
548
549 out_driver:
bd399063
SB
550 get_online_cpus();
551 mutex_lock(&microcode_mutex);
552
ff4b8a57 553 subsys_interface_unregister(&mc_cpu_interface);
bd399063
SB
554
555 mutex_unlock(&microcode_mutex);
556 put_online_cpus();
557
3d8986bc 558 out_pdev:
bd399063
SB
559 platform_device_unregister(microcode_pdev);
560 return error;
561
3e135d88 562}
871b72dd 563module_init(microcode_init);
3e135d88 564
18dbc916 565static void __exit microcode_exit(void)
3e135d88 566{
f72c1a57
BP
567 struct cpuinfo_x86 *c = &cpu_data(0);
568
3e135d88
PO
569 microcode_dev_exit();
570
571 unregister_hotcpu_notifier(&mc_cpu_notifier);
4ac5fc6a 572 unregister_syscore_ops(&mc_syscore_ops);
3e135d88 573
3d8986bc
BP
574 sysfs_remove_group(&cpu_subsys.dev_root->kobj,
575 &cpu_root_microcode_group);
576
3e135d88 577 get_online_cpus();
871b72dd
DA
578 mutex_lock(&microcode_mutex);
579
8a25a2fd 580 subsys_interface_unregister(&mc_cpu_interface);
871b72dd
DA
581
582 mutex_unlock(&microcode_mutex);
3e135d88
PO
583 put_online_cpus();
584
585 platform_device_unregister(microcode_pdev);
3e135d88 586
8d86f390
PO
587 microcode_ops = NULL;
588
f72c1a57
BP
589 if (c->x86_vendor == X86_VENDOR_AMD)
590 exit_amd_microcode();
591
871b72dd 592 pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
8d86f390 593}
18dbc916 594module_exit(microcode_exit);
This page took 0.675024 seconds and 5 git commands to generate.