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