at v3.3 15 kB view raw
1/* 2 * Intel 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 * 7 * This driver allows to upgrade microcode on Intel processors 8 * belonging to IA-32 family - PentiumPro, Pentium II, 9 * Pentium III, Xeon, Pentium 4, etc. 10 * 11 * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture 12 * Software Developer's Manual 13 * Order Number 253668 or free download from: 14 * 15 * http://developer.intel.com/Assets/PDF/manual/253668.pdf 16 * 17 * For more information, go to http://www.urbanmyth.org/microcode 18 * 19 * This program is free software; you can redistribute it and/or 20 * modify it under the terms of the GNU General Public License 21 * as published by the Free Software Foundation; either version 22 * 2 of the License, or (at your option) any later version. 23 * 24 * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com> 25 * Initial release. 26 * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com> 27 * Added read() support + cleanups. 28 * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com> 29 * Added 'device trimming' support. open(O_WRONLY) zeroes 30 * and frees the saved copy of applied microcode. 31 * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com> 32 * Made to use devfs (/dev/cpu/microcode) + cleanups. 33 * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com> 34 * Added misc device support (now uses both devfs and misc). 35 * Added MICROCODE_IOCFREE ioctl to clear memory. 36 * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com> 37 * Messages for error cases (non Intel & no suitable microcode). 38 * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com> 39 * Removed ->release(). Removed exclusive open and status bitmap. 40 * Added microcode_rwsem to serialize read()/write()/ioctl(). 41 * Removed global kernel lock usage. 42 * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com> 43 * Write 0 to 0x8B msr and then cpuid before reading revision, 44 * so that it works even if there were no update done by the 45 * BIOS. Otherwise, reading from 0x8B gives junk (which happened 46 * to be 0 on my machine which is why it worked even when I 47 * disabled update by the BIOS) 48 * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix. 49 * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and 50 * Tigran Aivazian <tigran@veritas.com> 51 * Intel Pentium 4 processor support and bugfixes. 52 * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com> 53 * Bugfix for HT (Hyper-Threading) enabled processors 54 * whereby processor resources are shared by all logical processors 55 * in a single CPU package. 56 * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and 57 * Tigran Aivazian <tigran@veritas.com>, 58 * Serialize updates as required on HT processors due to 59 * speculative nature of implementation. 60 * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com> 61 * Fix the panic when writing zero-length microcode chunk. 62 * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, 63 * Jun Nakajima <jun.nakajima@intel.com> 64 * Support for the microcode updates in the new format. 65 * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com> 66 * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl 67 * because we no longer hold a copy of applied microcode 68 * in kernel memory. 69 * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com> 70 * Fix sigmatch() macro to handle old CPUs with pf == 0. 71 * Thanks to Stuart Swales for pointing out this bug. 72 */ 73 74#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 75 76#include <linux/platform_device.h> 77#include <linux/miscdevice.h> 78#include <linux/capability.h> 79#include <linux/kernel.h> 80#include <linux/module.h> 81#include <linux/mutex.h> 82#include <linux/cpu.h> 83#include <linux/fs.h> 84#include <linux/mm.h> 85#include <linux/syscore_ops.h> 86 87#include <asm/microcode.h> 88#include <asm/processor.h> 89 90MODULE_DESCRIPTION("Microcode Update Driver"); 91MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); 92MODULE_LICENSE("GPL"); 93 94#define MICROCODE_VERSION "2.00" 95 96static struct microcode_ops *microcode_ops; 97 98/* 99 * Synchronization. 100 * 101 * All non cpu-hotplug-callback call sites use: 102 * 103 * - microcode_mutex to synchronize with each other; 104 * - get/put_online_cpus() to synchronize with 105 * the cpu-hotplug-callback call sites. 106 * 107 * We guarantee that only a single cpu is being 108 * updated at any particular moment of time. 109 */ 110static DEFINE_MUTEX(microcode_mutex); 111 112struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; 113EXPORT_SYMBOL_GPL(ucode_cpu_info); 114 115/* 116 * Operations that are run on a target cpu: 117 */ 118 119struct cpu_info_ctx { 120 struct cpu_signature *cpu_sig; 121 int err; 122}; 123 124static void collect_cpu_info_local(void *arg) 125{ 126 struct cpu_info_ctx *ctx = arg; 127 128 ctx->err = microcode_ops->collect_cpu_info(smp_processor_id(), 129 ctx->cpu_sig); 130} 131 132static int collect_cpu_info_on_target(int cpu, struct cpu_signature *cpu_sig) 133{ 134 struct cpu_info_ctx ctx = { .cpu_sig = cpu_sig, .err = 0 }; 135 int ret; 136 137 ret = smp_call_function_single(cpu, collect_cpu_info_local, &ctx, 1); 138 if (!ret) 139 ret = ctx.err; 140 141 return ret; 142} 143 144static int collect_cpu_info(int cpu) 145{ 146 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 147 int ret; 148 149 memset(uci, 0, sizeof(*uci)); 150 151 ret = collect_cpu_info_on_target(cpu, &uci->cpu_sig); 152 if (!ret) 153 uci->valid = 1; 154 155 return ret; 156} 157 158struct apply_microcode_ctx { 159 int err; 160}; 161 162static void apply_microcode_local(void *arg) 163{ 164 struct apply_microcode_ctx *ctx = arg; 165 166 ctx->err = microcode_ops->apply_microcode(smp_processor_id()); 167} 168 169static int apply_microcode_on_target(int cpu) 170{ 171 struct apply_microcode_ctx ctx = { .err = 0 }; 172 int ret; 173 174 ret = smp_call_function_single(cpu, apply_microcode_local, &ctx, 1); 175 if (!ret) 176 ret = ctx.err; 177 178 return ret; 179} 180 181#ifdef CONFIG_MICROCODE_OLD_INTERFACE 182static int do_microcode_update(const void __user *buf, size_t size) 183{ 184 int error = 0; 185 int cpu; 186 187 for_each_online_cpu(cpu) { 188 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 189 enum ucode_state ustate; 190 191 if (!uci->valid) 192 continue; 193 194 ustate = microcode_ops->request_microcode_user(cpu, buf, size); 195 if (ustate == UCODE_ERROR) { 196 error = -1; 197 break; 198 } else if (ustate == UCODE_OK) 199 apply_microcode_on_target(cpu); 200 } 201 202 return error; 203} 204 205static int microcode_open(struct inode *inode, struct file *file) 206{ 207 return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM; 208} 209 210static ssize_t microcode_write(struct file *file, const char __user *buf, 211 size_t len, loff_t *ppos) 212{ 213 ssize_t ret = -EINVAL; 214 215 if ((len >> PAGE_SHIFT) > totalram_pages) { 216 pr_err("too much data (max %ld pages)\n", totalram_pages); 217 return ret; 218 } 219 220 get_online_cpus(); 221 mutex_lock(&microcode_mutex); 222 223 if (do_microcode_update(buf, len) == 0) 224 ret = (ssize_t)len; 225 226 mutex_unlock(&microcode_mutex); 227 put_online_cpus(); 228 229 return ret; 230} 231 232static const struct file_operations microcode_fops = { 233 .owner = THIS_MODULE, 234 .write = microcode_write, 235 .open = microcode_open, 236 .llseek = no_llseek, 237}; 238 239static struct miscdevice microcode_dev = { 240 .minor = MICROCODE_MINOR, 241 .name = "microcode", 242 .nodename = "cpu/microcode", 243 .fops = &microcode_fops, 244}; 245 246static int __init microcode_dev_init(void) 247{ 248 int error; 249 250 error = misc_register(&microcode_dev); 251 if (error) { 252 pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR); 253 return error; 254 } 255 256 return 0; 257} 258 259static void __exit microcode_dev_exit(void) 260{ 261 misc_deregister(&microcode_dev); 262} 263 264MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); 265MODULE_ALIAS("devname:cpu/microcode"); 266#else 267#define microcode_dev_init() 0 268#define microcode_dev_exit() do { } while (0) 269#endif 270 271/* fake device for request_firmware */ 272static struct platform_device *microcode_pdev; 273 274static int reload_for_cpu(int cpu) 275{ 276 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 277 int err = 0; 278 279 mutex_lock(&microcode_mutex); 280 if (uci->valid) { 281 enum ucode_state ustate; 282 283 ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev); 284 if (ustate == UCODE_OK) 285 apply_microcode_on_target(cpu); 286 else 287 if (ustate == UCODE_ERROR) 288 err = -EINVAL; 289 } 290 mutex_unlock(&microcode_mutex); 291 292 return err; 293} 294 295static ssize_t reload_store(struct device *dev, 296 struct device_attribute *attr, 297 const char *buf, size_t size) 298{ 299 unsigned long val; 300 int cpu = dev->id; 301 int ret = 0; 302 char *end; 303 304 val = simple_strtoul(buf, &end, 0); 305 if (end == buf) 306 return -EINVAL; 307 308 if (val == 1) { 309 get_online_cpus(); 310 if (cpu_online(cpu)) 311 ret = reload_for_cpu(cpu); 312 put_online_cpus(); 313 } 314 315 if (!ret) 316 ret = size; 317 318 return ret; 319} 320 321static ssize_t version_show(struct device *dev, 322 struct device_attribute *attr, char *buf) 323{ 324 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; 325 326 return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); 327} 328 329static ssize_t pf_show(struct device *dev, 330 struct device_attribute *attr, char *buf) 331{ 332 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; 333 334 return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); 335} 336 337static DEVICE_ATTR(reload, 0200, NULL, reload_store); 338static DEVICE_ATTR(version, 0400, version_show, NULL); 339static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL); 340 341static struct attribute *mc_default_attrs[] = { 342 &dev_attr_reload.attr, 343 &dev_attr_version.attr, 344 &dev_attr_processor_flags.attr, 345 NULL 346}; 347 348static struct attribute_group mc_attr_group = { 349 .attrs = mc_default_attrs, 350 .name = "microcode", 351}; 352 353static void microcode_fini_cpu(int cpu) 354{ 355 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 356 357 microcode_ops->microcode_fini_cpu(cpu); 358 uci->valid = 0; 359} 360 361static enum ucode_state microcode_resume_cpu(int cpu) 362{ 363 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 364 365 if (!uci->mc) 366 return UCODE_NFOUND; 367 368 pr_debug("CPU%d updated upon resume\n", cpu); 369 apply_microcode_on_target(cpu); 370 371 return UCODE_OK; 372} 373 374static enum ucode_state microcode_init_cpu(int cpu) 375{ 376 enum ucode_state ustate; 377 378 if (collect_cpu_info(cpu)) 379 return UCODE_ERROR; 380 381 /* --dimm. Trigger a delayed update? */ 382 if (system_state != SYSTEM_RUNNING) 383 return UCODE_NFOUND; 384 385 ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev); 386 387 if (ustate == UCODE_OK) { 388 pr_debug("CPU%d updated upon init\n", cpu); 389 apply_microcode_on_target(cpu); 390 } 391 392 return ustate; 393} 394 395static enum ucode_state microcode_update_cpu(int cpu) 396{ 397 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 398 enum ucode_state ustate; 399 400 if (uci->valid) 401 ustate = microcode_resume_cpu(cpu); 402 else 403 ustate = microcode_init_cpu(cpu); 404 405 return ustate; 406} 407 408static int mc_device_add(struct device *dev, struct subsys_interface *sif) 409{ 410 int err, cpu = dev->id; 411 412 if (!cpu_online(cpu)) 413 return 0; 414 415 pr_debug("CPU%d added\n", cpu); 416 417 err = sysfs_create_group(&dev->kobj, &mc_attr_group); 418 if (err) 419 return err; 420 421 if (microcode_init_cpu(cpu) == UCODE_ERROR) { 422 sysfs_remove_group(&dev->kobj, &mc_attr_group); 423 return -EINVAL; 424 } 425 426 return err; 427} 428 429static int mc_device_remove(struct device *dev, struct subsys_interface *sif) 430{ 431 int cpu = dev->id; 432 433 if (!cpu_online(cpu)) 434 return 0; 435 436 pr_debug("CPU%d removed\n", cpu); 437 microcode_fini_cpu(cpu); 438 sysfs_remove_group(&dev->kobj, &mc_attr_group); 439 return 0; 440} 441 442static struct subsys_interface mc_cpu_interface = { 443 .name = "microcode", 444 .subsys = &cpu_subsys, 445 .add_dev = mc_device_add, 446 .remove_dev = mc_device_remove, 447}; 448 449/** 450 * mc_bp_resume - Update boot CPU microcode during resume. 451 */ 452static void mc_bp_resume(void) 453{ 454 int cpu = smp_processor_id(); 455 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 456 457 if (uci->valid && uci->mc) 458 microcode_ops->apply_microcode(cpu); 459} 460 461static struct syscore_ops mc_syscore_ops = { 462 .resume = mc_bp_resume, 463}; 464 465static __cpuinit int 466mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) 467{ 468 unsigned int cpu = (unsigned long)hcpu; 469 struct device *dev; 470 471 dev = get_cpu_device(cpu); 472 switch (action) { 473 case CPU_ONLINE: 474 case CPU_ONLINE_FROZEN: 475 microcode_update_cpu(cpu); 476 case CPU_DOWN_FAILED: 477 case CPU_DOWN_FAILED_FROZEN: 478 pr_debug("CPU%d added\n", cpu); 479 if (sysfs_create_group(&dev->kobj, &mc_attr_group)) 480 pr_err("Failed to create group for CPU%d\n", cpu); 481 break; 482 case CPU_DOWN_PREPARE: 483 case CPU_DOWN_PREPARE_FROZEN: 484 /* Suspend is in progress, only remove the interface */ 485 sysfs_remove_group(&dev->kobj, &mc_attr_group); 486 pr_debug("CPU%d removed\n", cpu); 487 break; 488 489 /* 490 * When a CPU goes offline, don't free up or invalidate the copy of 491 * the microcode in kernel memory, so that we can reuse it when the 492 * CPU comes back online without unnecessarily requesting the userspace 493 * for it again. 494 */ 495 case CPU_UP_CANCELED_FROZEN: 496 /* The CPU refused to come up during a system resume */ 497 microcode_fini_cpu(cpu); 498 break; 499 } 500 return NOTIFY_OK; 501} 502 503static struct notifier_block __refdata mc_cpu_notifier = { 504 .notifier_call = mc_cpu_callback, 505}; 506 507static int __init microcode_init(void) 508{ 509 struct cpuinfo_x86 *c = &cpu_data(0); 510 int error; 511 512 if (c->x86_vendor == X86_VENDOR_INTEL) 513 microcode_ops = init_intel_microcode(); 514 else if (c->x86_vendor == X86_VENDOR_AMD) 515 microcode_ops = init_amd_microcode(); 516 517 if (!microcode_ops) { 518 pr_err("no support for this CPU vendor\n"); 519 return -ENODEV; 520 } 521 522 microcode_pdev = platform_device_register_simple("microcode", -1, 523 NULL, 0); 524 if (IS_ERR(microcode_pdev)) 525 return PTR_ERR(microcode_pdev); 526 527 get_online_cpus(); 528 mutex_lock(&microcode_mutex); 529 530 error = subsys_interface_register(&mc_cpu_interface); 531 532 mutex_unlock(&microcode_mutex); 533 put_online_cpus(); 534 535 if (error) 536 goto out_pdev; 537 538 error = microcode_dev_init(); 539 if (error) 540 goto out_driver; 541 542 register_syscore_ops(&mc_syscore_ops); 543 register_hotcpu_notifier(&mc_cpu_notifier); 544 545 pr_info("Microcode Update Driver: v" MICROCODE_VERSION 546 " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n"); 547 548 return 0; 549 550out_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 559out_pdev: 560 platform_device_unregister(microcode_pdev); 561 return error; 562 563} 564module_init(microcode_init); 565 566static 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 get_online_cpus(); 576 mutex_lock(&microcode_mutex); 577 578 subsys_interface_unregister(&mc_cpu_interface); 579 580 mutex_unlock(&microcode_mutex); 581 put_online_cpus(); 582 583 platform_device_unregister(microcode_pdev); 584 585 microcode_ops = NULL; 586 587 if (c->x86_vendor == X86_VENDOR_AMD) 588 exit_amd_microcode(); 589 590 pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); 591} 592module_exit(microcode_exit);