diff options
| author | Borislav Petkov <bp@suse.de> | 2013-12-01 12:09:58 -0500 |
|---|---|---|
| committer | Borislav Petkov <bp@suse.de> | 2014-01-13 14:00:12 -0500 |
| commit | bad5fa631fca5466401cd4a48e30cc1f1cb6101e (patch) | |
| tree | 6049920eea5810bbd38f417f1313fa35f5a0679d /arch/x86/kernel/cpu/microcode | |
| parent | 5335ba5cf475369f88db8e6835764efdcad8ab96 (diff) | |
x86, microcode: Move to a proper location
We've grown a bunch of microcode loader files all prefixed with
"microcode_". They should be under cpu/ because this is strictly
CPU-related functionality so do that and drop the prefix since they're
in their own directory now which gives that prefix. :)
While at it, drop MICROCODE_INTEL_LIB config item and stash the
functionality under CONFIG_MICROCODE_INTEL as it was its only user.
Signed-off-by: Borislav Petkov <bp@suse.de>
Tested-by: Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>
Diffstat (limited to 'arch/x86/kernel/cpu/microcode')
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/Makefile | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 492 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 380 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 645 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core_early.c | 141 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 333 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_early.c | 787 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_lib.c | 174 |
8 files changed, 2959 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/microcode/Makefile b/arch/x86/kernel/cpu/microcode/Makefile new file mode 100644 index 000000000000..285c85427c32 --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | microcode-y := core.o | ||
| 2 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
| 3 | microcode-$(CONFIG_MICROCODE_INTEL) += intel.o intel_lib.o | ||
| 4 | microcode-$(CONFIG_MICROCODE_AMD) += amd.o | ||
| 5 | obj-$(CONFIG_MICROCODE_EARLY) += core_early.o | ||
| 6 | obj-$(CONFIG_MICROCODE_INTEL_EARLY) += intel_early.o | ||
| 7 | obj-$(CONFIG_MICROCODE_AMD_EARLY) += amd_early.o | ||
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c new file mode 100644 index 000000000000..4a6ff747aaad --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
| @@ -0,0 +1,492 @@ | |||
| 1 | /* | ||
| 2 | * AMD CPU Microcode Update Driver for Linux | ||
| 3 | * Copyright (C) 2008-2011 Advanced Micro Devices Inc. | ||
| 4 | * | ||
| 5 | * Author: Peter Oruba <peter.oruba@amd.com> | ||
| 6 | * | ||
| 7 | * Based on work by: | ||
| 8 | * Tigran Aivazian <tigran@aivazian.fsnet.co.uk> | ||
| 9 | * | ||
| 10 | * Maintainers: | ||
| 11 | * Andreas Herrmann <herrmann.der.user@googlemail.com> | ||
| 12 | * Borislav Petkov <bp@alien8.de> | ||
| 13 | * | ||
| 14 | * This driver allows to upgrade microcode on F10h AMD | ||
| 15 | * CPUs and later. | ||
| 16 | * | ||
| 17 | * Licensed under the terms of the GNU General Public | ||
| 18 | * License version 2. See file COPYING for details. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 22 | |||
| 23 | #include <linux/firmware.h> | ||
| 24 | #include <linux/pci_ids.h> | ||
| 25 | #include <linux/uaccess.h> | ||
| 26 | #include <linux/vmalloc.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/pci.h> | ||
| 30 | |||
| 31 | #include <asm/microcode.h> | ||
| 32 | #include <asm/processor.h> | ||
| 33 | #include <asm/msr.h> | ||
| 34 | #include <asm/microcode_amd.h> | ||
| 35 | |||
| 36 | MODULE_DESCRIPTION("AMD Microcode Update Driver"); | ||
| 37 | MODULE_AUTHOR("Peter Oruba"); | ||
| 38 | MODULE_LICENSE("GPL v2"); | ||
| 39 | |||
| 40 | static struct equiv_cpu_entry *equiv_cpu_table; | ||
| 41 | |||
| 42 | struct ucode_patch { | ||
| 43 | struct list_head plist; | ||
| 44 | void *data; | ||
| 45 | u32 patch_id; | ||
| 46 | u16 equiv_cpu; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static LIST_HEAD(pcache); | ||
| 50 | |||
| 51 | static u16 __find_equiv_id(unsigned int cpu) | ||
| 52 | { | ||
| 53 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 54 | return find_equiv_id(equiv_cpu_table, uci->cpu_sig.sig); | ||
| 55 | } | ||
| 56 | |||
| 57 | static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu) | ||
| 58 | { | ||
| 59 | int i = 0; | ||
| 60 | |||
| 61 | BUG_ON(!equiv_cpu_table); | ||
| 62 | |||
| 63 | while (equiv_cpu_table[i].equiv_cpu != 0) { | ||
| 64 | if (equiv_cpu == equiv_cpu_table[i].equiv_cpu) | ||
| 65 | return equiv_cpu_table[i].installed_cpu; | ||
| 66 | i++; | ||
| 67 | } | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* | ||
| 72 | * a small, trivial cache of per-family ucode patches | ||
| 73 | */ | ||
| 74 | static struct ucode_patch *cache_find_patch(u16 equiv_cpu) | ||
| 75 | { | ||
| 76 | struct ucode_patch *p; | ||
| 77 | |||
| 78 | list_for_each_entry(p, &pcache, plist) | ||
| 79 | if (p->equiv_cpu == equiv_cpu) | ||
| 80 | return p; | ||
| 81 | return NULL; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void update_cache(struct ucode_patch *new_patch) | ||
| 85 | { | ||
| 86 | struct ucode_patch *p; | ||
| 87 | |||
| 88 | list_for_each_entry(p, &pcache, plist) { | ||
| 89 | if (p->equiv_cpu == new_patch->equiv_cpu) { | ||
| 90 | if (p->patch_id >= new_patch->patch_id) | ||
| 91 | /* we already have the latest patch */ | ||
| 92 | return; | ||
| 93 | |||
| 94 | list_replace(&p->plist, &new_patch->plist); | ||
| 95 | kfree(p->data); | ||
| 96 | kfree(p); | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | /* no patch found, add it */ | ||
| 101 | list_add_tail(&new_patch->plist, &pcache); | ||
| 102 | } | ||
| 103 | |||
| 104 | static void free_cache(void) | ||
| 105 | { | ||
| 106 | struct ucode_patch *p, *tmp; | ||
| 107 | |||
| 108 | list_for_each_entry_safe(p, tmp, &pcache, plist) { | ||
| 109 | __list_del(p->plist.prev, p->plist.next); | ||
| 110 | kfree(p->data); | ||
| 111 | kfree(p); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | static struct ucode_patch *find_patch(unsigned int cpu) | ||
| 116 | { | ||
| 117 | u16 equiv_id; | ||
| 118 | |||
| 119 | equiv_id = __find_equiv_id(cpu); | ||
| 120 | if (!equiv_id) | ||
| 121 | return NULL; | ||
| 122 | |||
| 123 | return cache_find_patch(equiv_id); | ||
| 124 | } | ||
| 125 | |||
| 126 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | ||
| 127 | { | ||
| 128 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 129 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 130 | struct ucode_patch *p; | ||
| 131 | |||
| 132 | csig->sig = cpuid_eax(0x00000001); | ||
| 133 | csig->rev = c->microcode; | ||
| 134 | |||
| 135 | /* | ||
| 136 | * a patch could have been loaded early, set uci->mc so that | ||
| 137 | * mc_bp_resume() can call apply_microcode() | ||
| 138 | */ | ||
| 139 | p = find_patch(cpu); | ||
| 140 | if (p && (p->patch_id == csig->rev)) | ||
| 141 | uci->mc = p->data; | ||
| 142 | |||
| 143 | pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static unsigned int verify_patch_size(u8 family, u32 patch_size, | ||
| 149 | unsigned int size) | ||
| 150 | { | ||
| 151 | u32 max_size; | ||
| 152 | |||
| 153 | #define F1XH_MPB_MAX_SIZE 2048 | ||
| 154 | #define F14H_MPB_MAX_SIZE 1824 | ||
| 155 | #define F15H_MPB_MAX_SIZE 4096 | ||
| 156 | #define F16H_MPB_MAX_SIZE 3458 | ||
| 157 | |||
| 158 | switch (family) { | ||
| 159 | case 0x14: | ||
| 160 | max_size = F14H_MPB_MAX_SIZE; | ||
| 161 | break; | ||
| 162 | case 0x15: | ||
| 163 | max_size = F15H_MPB_MAX_SIZE; | ||
| 164 | break; | ||
| 165 | case 0x16: | ||
| 166 | max_size = F16H_MPB_MAX_SIZE; | ||
| 167 | break; | ||
| 168 | default: | ||
| 169 | max_size = F1XH_MPB_MAX_SIZE; | ||
| 170 | break; | ||
| 171 | } | ||
| 172 | |||
| 173 | if (patch_size > min_t(u32, size, max_size)) { | ||
| 174 | pr_err("patch size mismatch\n"); | ||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | return patch_size; | ||
| 179 | } | ||
| 180 | |||
| 181 | int __apply_microcode_amd(struct microcode_amd *mc_amd) | ||
| 182 | { | ||
| 183 | u32 rev, dummy; | ||
| 184 | |||
| 185 | native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); | ||
| 186 | |||
| 187 | /* verify patch application was successful */ | ||
| 188 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | ||
| 189 | if (rev != mc_amd->hdr.patch_id) | ||
| 190 | return -1; | ||
| 191 | |||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | int apply_microcode_amd(int cpu) | ||
| 196 | { | ||
| 197 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 198 | struct microcode_amd *mc_amd; | ||
| 199 | struct ucode_cpu_info *uci; | ||
| 200 | struct ucode_patch *p; | ||
| 201 | u32 rev, dummy; | ||
| 202 | |||
| 203 | BUG_ON(raw_smp_processor_id() != cpu); | ||
| 204 | |||
| 205 | uci = ucode_cpu_info + cpu; | ||
| 206 | |||
| 207 | p = find_patch(cpu); | ||
| 208 | if (!p) | ||
| 209 | return 0; | ||
| 210 | |||
| 211 | mc_amd = p->data; | ||
| 212 | uci->mc = p->data; | ||
| 213 | |||
| 214 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | ||
| 215 | |||
| 216 | /* need to apply patch? */ | ||
| 217 | if (rev >= mc_amd->hdr.patch_id) { | ||
| 218 | c->microcode = rev; | ||
| 219 | uci->cpu_sig.rev = rev; | ||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | if (__apply_microcode_amd(mc_amd)) { | ||
| 224 | pr_err("CPU%d: update failed for patch_level=0x%08x\n", | ||
| 225 | cpu, mc_amd->hdr.patch_id); | ||
| 226 | return -1; | ||
| 227 | } | ||
| 228 | pr_info("CPU%d: new patch_level=0x%08x\n", cpu, | ||
| 229 | mc_amd->hdr.patch_id); | ||
| 230 | |||
| 231 | uci->cpu_sig.rev = mc_amd->hdr.patch_id; | ||
| 232 | c->microcode = mc_amd->hdr.patch_id; | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int install_equiv_cpu_table(const u8 *buf) | ||
| 238 | { | ||
| 239 | unsigned int *ibuf = (unsigned int *)buf; | ||
| 240 | unsigned int type = ibuf[1]; | ||
| 241 | unsigned int size = ibuf[2]; | ||
| 242 | |||
| 243 | if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { | ||
| 244 | pr_err("empty section/" | ||
| 245 | "invalid type field in container file section header\n"); | ||
| 246 | return -EINVAL; | ||
| 247 | } | ||
| 248 | |||
| 249 | equiv_cpu_table = vmalloc(size); | ||
| 250 | if (!equiv_cpu_table) { | ||
| 251 | pr_err("failed to allocate equivalent CPU table\n"); | ||
| 252 | return -ENOMEM; | ||
| 253 | } | ||
| 254 | |||
| 255 | memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size); | ||
| 256 | |||
| 257 | /* add header length */ | ||
| 258 | return size + CONTAINER_HDR_SZ; | ||
| 259 | } | ||
| 260 | |||
| 261 | static void free_equiv_cpu_table(void) | ||
| 262 | { | ||
| 263 | vfree(equiv_cpu_table); | ||
| 264 | equiv_cpu_table = NULL; | ||
| 265 | } | ||
| 266 | |||
| 267 | static void cleanup(void) | ||
| 268 | { | ||
| 269 | free_equiv_cpu_table(); | ||
| 270 | free_cache(); | ||
| 271 | } | ||
| 272 | |||
| 273 | /* | ||
| 274 | * We return the current size even if some of the checks failed so that | ||
| 275 | * we can skip over the next patch. If we return a negative value, we | ||
| 276 | * signal a grave error like a memory allocation has failed and the | ||
| 277 | * driver cannot continue functioning normally. In such cases, we tear | ||
| 278 | * down everything we've used up so far and exit. | ||
| 279 | */ | ||
| 280 | static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover) | ||
| 281 | { | ||
| 282 | struct microcode_header_amd *mc_hdr; | ||
| 283 | struct ucode_patch *patch; | ||
| 284 | unsigned int patch_size, crnt_size, ret; | ||
| 285 | u32 proc_fam; | ||
| 286 | u16 proc_id; | ||
| 287 | |||
| 288 | patch_size = *(u32 *)(fw + 4); | ||
| 289 | crnt_size = patch_size + SECTION_HDR_SIZE; | ||
| 290 | mc_hdr = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE); | ||
| 291 | proc_id = mc_hdr->processor_rev_id; | ||
| 292 | |||
| 293 | proc_fam = find_cpu_family_by_equiv_cpu(proc_id); | ||
| 294 | if (!proc_fam) { | ||
| 295 | pr_err("No patch family for equiv ID: 0x%04x\n", proc_id); | ||
| 296 | return crnt_size; | ||
| 297 | } | ||
| 298 | |||
| 299 | /* check if patch is for the current family */ | ||
| 300 | proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); | ||
| 301 | if (proc_fam != family) | ||
| 302 | return crnt_size; | ||
| 303 | |||
| 304 | if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { | ||
| 305 | pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", | ||
| 306 | mc_hdr->patch_id); | ||
| 307 | return crnt_size; | ||
| 308 | } | ||
| 309 | |||
| 310 | ret = verify_patch_size(family, patch_size, leftover); | ||
| 311 | if (!ret) { | ||
| 312 | pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); | ||
| 313 | return crnt_size; | ||
| 314 | } | ||
| 315 | |||
| 316 | patch = kzalloc(sizeof(*patch), GFP_KERNEL); | ||
| 317 | if (!patch) { | ||
| 318 | pr_err("Patch allocation failure.\n"); | ||
| 319 | return -EINVAL; | ||
| 320 | } | ||
| 321 | |||
| 322 | patch->data = kzalloc(patch_size, GFP_KERNEL); | ||
| 323 | if (!patch->data) { | ||
| 324 | pr_err("Patch data allocation failure.\n"); | ||
| 325 | kfree(patch); | ||
| 326 | return -EINVAL; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* All looks ok, copy patch... */ | ||
| 330 | memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size); | ||
| 331 | INIT_LIST_HEAD(&patch->plist); | ||
| 332 | patch->patch_id = mc_hdr->patch_id; | ||
| 333 | patch->equiv_cpu = proc_id; | ||
| 334 | |||
| 335 | pr_debug("%s: Added patch_id: 0x%08x, proc_id: 0x%04x\n", | ||
| 336 | __func__, patch->patch_id, proc_id); | ||
| 337 | |||
| 338 | /* ... and add to cache. */ | ||
| 339 | update_cache(patch); | ||
| 340 | |||
| 341 | return crnt_size; | ||
| 342 | } | ||
| 343 | |||
| 344 | static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, | ||
| 345 | size_t size) | ||
| 346 | { | ||
| 347 | enum ucode_state ret = UCODE_ERROR; | ||
| 348 | unsigned int leftover; | ||
| 349 | u8 *fw = (u8 *)data; | ||
| 350 | int crnt_size = 0; | ||
| 351 | int offset; | ||
| 352 | |||
| 353 | offset = install_equiv_cpu_table(data); | ||
| 354 | if (offset < 0) { | ||
| 355 | pr_err("failed to create equivalent cpu table\n"); | ||
| 356 | return ret; | ||
| 357 | } | ||
| 358 | fw += offset; | ||
| 359 | leftover = size - offset; | ||
| 360 | |||
| 361 | if (*(u32 *)fw != UCODE_UCODE_TYPE) { | ||
| 362 | pr_err("invalid type field in container file section header\n"); | ||
| 363 | free_equiv_cpu_table(); | ||
| 364 | return ret; | ||
| 365 | } | ||
| 366 | |||
| 367 | while (leftover) { | ||
| 368 | crnt_size = verify_and_add_patch(family, fw, leftover); | ||
| 369 | if (crnt_size < 0) | ||
| 370 | return ret; | ||
| 371 | |||
| 372 | fw += crnt_size; | ||
| 373 | leftover -= crnt_size; | ||
| 374 | } | ||
| 375 | |||
| 376 | return UCODE_OK; | ||
| 377 | } | ||
| 378 | |||
| 379 | enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) | ||
| 380 | { | ||
| 381 | enum ucode_state ret; | ||
| 382 | |||
| 383 | /* free old equiv table */ | ||
| 384 | free_equiv_cpu_table(); | ||
| 385 | |||
| 386 | ret = __load_microcode_amd(family, data, size); | ||
| 387 | |||
| 388 | if (ret != UCODE_OK) | ||
| 389 | cleanup(); | ||
| 390 | |||
| 391 | #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32) | ||
| 392 | /* save BSP's matching patch for early load */ | ||
| 393 | if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) { | ||
| 394 | struct ucode_patch *p = find_patch(smp_processor_id()); | ||
| 395 | if (p) { | ||
| 396 | memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); | ||
| 397 | memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), | ||
| 398 | PATCH_MAX_SIZE)); | ||
| 399 | } | ||
| 400 | } | ||
| 401 | #endif | ||
| 402 | return ret; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* | ||
| 406 | * AMD microcode firmware naming convention, up to family 15h they are in | ||
| 407 | * the legacy file: | ||
| 408 | * | ||
| 409 | * amd-ucode/microcode_amd.bin | ||
| 410 | * | ||
| 411 | * This legacy file is always smaller than 2K in size. | ||
| 412 | * | ||
| 413 | * Beginning with family 15h, they are in family-specific firmware files: | ||
| 414 | * | ||
| 415 | * amd-ucode/microcode_amd_fam15h.bin | ||
| 416 | * amd-ucode/microcode_amd_fam16h.bin | ||
| 417 | * ... | ||
| 418 | * | ||
| 419 | * These might be larger than 2K. | ||
| 420 | */ | ||
| 421 | static enum ucode_state request_microcode_amd(int cpu, struct device *device, | ||
| 422 | bool refresh_fw) | ||
| 423 | { | ||
| 424 | char fw_name[36] = "amd-ucode/microcode_amd.bin"; | ||
| 425 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 426 | enum ucode_state ret = UCODE_NFOUND; | ||
| 427 | const struct firmware *fw; | ||
| 428 | |||
| 429 | /* reload ucode container only on the boot cpu */ | ||
| 430 | if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index) | ||
| 431 | return UCODE_OK; | ||
| 432 | |||
| 433 | if (c->x86 >= 0x15) | ||
| 434 | snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); | ||
| 435 | |||
| 436 | if (request_firmware(&fw, (const char *)fw_name, device)) { | ||
| 437 | pr_debug("failed to load file %s\n", fw_name); | ||
| 438 | goto out; | ||
| 439 | } | ||
| 440 | |||
| 441 | ret = UCODE_ERROR; | ||
| 442 | if (*(u32 *)fw->data != UCODE_MAGIC) { | ||
| 443 | pr_err("invalid magic value (0x%08x)\n", *(u32 *)fw->data); | ||
| 444 | goto fw_release; | ||
| 445 | } | ||
| 446 | |||
| 447 | ret = load_microcode_amd(c->x86, fw->data, fw->size); | ||
| 448 | |||
| 449 | fw_release: | ||
| 450 | release_firmware(fw); | ||
| 451 | |||
| 452 | out: | ||
| 453 | return ret; | ||
| 454 | } | ||
| 455 | |||
| 456 | static enum ucode_state | ||
| 457 | request_microcode_user(int cpu, const void __user *buf, size_t size) | ||
| 458 | { | ||
| 459 | return UCODE_ERROR; | ||
| 460 | } | ||
| 461 | |||
| 462 | static void microcode_fini_cpu_amd(int cpu) | ||
| 463 | { | ||
| 464 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 465 | |||
| 466 | uci->mc = NULL; | ||
| 467 | } | ||
| 468 | |||
| 469 | static struct microcode_ops microcode_amd_ops = { | ||
| 470 | .request_microcode_user = request_microcode_user, | ||
| 471 | .request_microcode_fw = request_microcode_amd, | ||
| 472 | .collect_cpu_info = collect_cpu_info_amd, | ||
| 473 | .apply_microcode = apply_microcode_amd, | ||
| 474 | .microcode_fini_cpu = microcode_fini_cpu_amd, | ||
| 475 | }; | ||
| 476 | |||
| 477 | struct microcode_ops * __init init_amd_microcode(void) | ||
| 478 | { | ||
| 479 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
| 480 | |||
| 481 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { | ||
| 482 | pr_warning("AMD CPU family 0x%x not supported\n", c->x86); | ||
| 483 | return NULL; | ||
| 484 | } | ||
| 485 | |||
| 486 | return µcode_amd_ops; | ||
| 487 | } | ||
| 488 | |||
| 489 | void __exit exit_amd_microcode(void) | ||
| 490 | { | ||
| 491 | cleanup(); | ||
| 492 | } | ||
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c new file mode 100644 index 000000000000..8384c0fa206f --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/amd_early.c | |||
| @@ -0,0 +1,380 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Author: Jacob Shin <jacob.shin@amd.com> | ||
| 5 | * Fixes: Borislav Petkov <bp@suse.de> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/earlycpio.h> | ||
| 13 | #include <linux/initrd.h> | ||
| 14 | |||
| 15 | #include <asm/cpu.h> | ||
| 16 | #include <asm/setup.h> | ||
| 17 | #include <asm/microcode_amd.h> | ||
| 18 | |||
| 19 | /* | ||
| 20 | * This points to the current valid container of microcode patches which we will | ||
| 21 | * save from the initrd before jettisoning its contents. | ||
| 22 | */ | ||
| 23 | static u8 *container; | ||
| 24 | static size_t container_size; | ||
| 25 | |||
| 26 | static u32 ucode_new_rev; | ||
| 27 | u8 amd_ucode_patch[PATCH_MAX_SIZE]; | ||
| 28 | static u16 this_equiv_id; | ||
| 29 | |||
| 30 | struct cpio_data ucode_cpio; | ||
| 31 | |||
| 32 | /* | ||
| 33 | * Microcode patch container file is prepended to the initrd in cpio format. | ||
| 34 | * See Documentation/x86/early-microcode.txt | ||
| 35 | */ | ||
| 36 | static __initdata char ucode_path[] = "kernel/x86/microcode/AuthenticAMD.bin"; | ||
| 37 | |||
| 38 | static struct cpio_data __init find_ucode_in_initrd(void) | ||
| 39 | { | ||
| 40 | long offset = 0; | ||
| 41 | char *path; | ||
| 42 | void *start; | ||
| 43 | size_t size; | ||
| 44 | |||
| 45 | #ifdef CONFIG_X86_32 | ||
| 46 | struct boot_params *p; | ||
| 47 | |||
| 48 | /* | ||
| 49 | * On 32-bit, early load occurs before paging is turned on so we need | ||
| 50 | * to use physical addresses. | ||
| 51 | */ | ||
| 52 | p = (struct boot_params *)__pa_nodebug(&boot_params); | ||
| 53 | path = (char *)__pa_nodebug(ucode_path); | ||
| 54 | start = (void *)p->hdr.ramdisk_image; | ||
| 55 | size = p->hdr.ramdisk_size; | ||
| 56 | #else | ||
| 57 | path = ucode_path; | ||
| 58 | start = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET); | ||
| 59 | size = boot_params.hdr.ramdisk_size; | ||
| 60 | #endif | ||
| 61 | |||
| 62 | return find_cpio_data(path, start, size, &offset); | ||
| 63 | } | ||
| 64 | |||
| 65 | static size_t compute_container_size(u8 *data, u32 total_size) | ||
| 66 | { | ||
| 67 | size_t size = 0; | ||
| 68 | u32 *header = (u32 *)data; | ||
| 69 | |||
| 70 | if (header[0] != UCODE_MAGIC || | ||
| 71 | header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */ | ||
| 72 | header[2] == 0) /* size */ | ||
| 73 | return size; | ||
| 74 | |||
| 75 | size = header[2] + CONTAINER_HDR_SZ; | ||
| 76 | total_size -= size; | ||
| 77 | data += size; | ||
| 78 | |||
| 79 | while (total_size) { | ||
| 80 | u16 patch_size; | ||
| 81 | |||
| 82 | header = (u32 *)data; | ||
| 83 | |||
| 84 | if (header[0] != UCODE_UCODE_TYPE) | ||
| 85 | break; | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Sanity-check patch size. | ||
| 89 | */ | ||
| 90 | patch_size = header[1]; | ||
| 91 | if (patch_size > PATCH_MAX_SIZE) | ||
| 92 | break; | ||
| 93 | |||
| 94 | size += patch_size + SECTION_HDR_SIZE; | ||
| 95 | data += patch_size + SECTION_HDR_SIZE; | ||
| 96 | total_size -= patch_size + SECTION_HDR_SIZE; | ||
| 97 | } | ||
| 98 | |||
| 99 | return size; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Early load occurs before we can vmalloc(). So we look for the microcode | ||
| 104 | * patch container file in initrd, traverse equivalent cpu table, look for a | ||
| 105 | * matching microcode patch, and update, all in initrd memory in place. | ||
| 106 | * When vmalloc() is available for use later -- on 64-bit during first AP load, | ||
| 107 | * and on 32-bit during save_microcode_in_initrd_amd() -- we can call | ||
| 108 | * load_microcode_amd() to save equivalent cpu table and microcode patches in | ||
| 109 | * kernel heap memory. | ||
| 110 | */ | ||
| 111 | static void apply_ucode_in_initrd(void *ucode, size_t size) | ||
| 112 | { | ||
| 113 | struct equiv_cpu_entry *eq; | ||
| 114 | size_t *cont_sz; | ||
| 115 | u32 *header; | ||
| 116 | u8 *data, **cont; | ||
| 117 | u16 eq_id = 0; | ||
| 118 | int offset, left; | ||
| 119 | u32 rev, eax, ebx, ecx, edx; | ||
| 120 | u32 *new_rev; | ||
| 121 | |||
| 122 | #ifdef CONFIG_X86_32 | ||
| 123 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); | ||
| 124 | cont_sz = (size_t *)__pa_nodebug(&container_size); | ||
| 125 | cont = (u8 **)__pa_nodebug(&container); | ||
| 126 | #else | ||
| 127 | new_rev = &ucode_new_rev; | ||
| 128 | cont_sz = &container_size; | ||
| 129 | cont = &container; | ||
| 130 | #endif | ||
| 131 | |||
| 132 | data = ucode; | ||
| 133 | left = size; | ||
| 134 | header = (u32 *)data; | ||
| 135 | |||
| 136 | /* find equiv cpu table */ | ||
| 137 | if (header[0] != UCODE_MAGIC || | ||
| 138 | header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */ | ||
| 139 | header[2] == 0) /* size */ | ||
| 140 | return; | ||
| 141 | |||
| 142 | eax = 0x00000001; | ||
| 143 | ecx = 0; | ||
| 144 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
| 145 | |||
| 146 | while (left > 0) { | ||
| 147 | eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ); | ||
| 148 | |||
| 149 | *cont = data; | ||
| 150 | |||
| 151 | /* Advance past the container header */ | ||
| 152 | offset = header[2] + CONTAINER_HDR_SZ; | ||
| 153 | data += offset; | ||
| 154 | left -= offset; | ||
| 155 | |||
| 156 | eq_id = find_equiv_id(eq, eax); | ||
| 157 | if (eq_id) { | ||
| 158 | this_equiv_id = eq_id; | ||
| 159 | *cont_sz = compute_container_size(*cont, left + offset); | ||
| 160 | |||
| 161 | /* | ||
| 162 | * truncate how much we need to iterate over in the | ||
| 163 | * ucode update loop below | ||
| 164 | */ | ||
| 165 | left = *cont_sz - offset; | ||
| 166 | break; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * support multiple container files appended together. if this | ||
| 171 | * one does not have a matching equivalent cpu entry, we fast | ||
| 172 | * forward to the next container file. | ||
| 173 | */ | ||
| 174 | while (left > 0) { | ||
| 175 | header = (u32 *)data; | ||
| 176 | if (header[0] == UCODE_MAGIC && | ||
| 177 | header[1] == UCODE_EQUIV_CPU_TABLE_TYPE) | ||
| 178 | break; | ||
| 179 | |||
| 180 | offset = header[1] + SECTION_HDR_SIZE; | ||
| 181 | data += offset; | ||
| 182 | left -= offset; | ||
| 183 | } | ||
| 184 | |||
| 185 | /* mark where the next microcode container file starts */ | ||
| 186 | offset = data - (u8 *)ucode; | ||
| 187 | ucode = data; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (!eq_id) { | ||
| 191 | *cont = NULL; | ||
| 192 | *cont_sz = 0; | ||
| 193 | return; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* find ucode and update if needed */ | ||
| 197 | |||
| 198 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | ||
| 199 | |||
| 200 | while (left > 0) { | ||
| 201 | struct microcode_amd *mc; | ||
| 202 | |||
| 203 | header = (u32 *)data; | ||
| 204 | if (header[0] != UCODE_UCODE_TYPE || /* type */ | ||
| 205 | header[1] == 0) /* size */ | ||
| 206 | break; | ||
| 207 | |||
| 208 | mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE); | ||
| 209 | |||
| 210 | if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id) { | ||
| 211 | |||
| 212 | if (!__apply_microcode_amd(mc)) { | ||
| 213 | rev = mc->hdr.patch_id; | ||
| 214 | *new_rev = rev; | ||
| 215 | |||
| 216 | /* save ucode patch */ | ||
| 217 | memcpy(amd_ucode_patch, mc, | ||
| 218 | min_t(u32, header[1], PATCH_MAX_SIZE)); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | offset = header[1] + SECTION_HDR_SIZE; | ||
| 223 | data += offset; | ||
| 224 | left -= offset; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | void __init load_ucode_amd_bsp(void) | ||
| 229 | { | ||
| 230 | struct cpio_data cp; | ||
| 231 | void **data; | ||
| 232 | size_t *size; | ||
| 233 | |||
| 234 | #ifdef CONFIG_X86_32 | ||
| 235 | data = (void **)__pa_nodebug(&ucode_cpio.data); | ||
| 236 | size = (size_t *)__pa_nodebug(&ucode_cpio.size); | ||
| 237 | #else | ||
| 238 | data = &ucode_cpio.data; | ||
| 239 | size = &ucode_cpio.size; | ||
| 240 | #endif | ||
| 241 | |||
| 242 | cp = find_ucode_in_initrd(); | ||
| 243 | if (!cp.data) | ||
| 244 | return; | ||
| 245 | |||
| 246 | *data = cp.data; | ||
| 247 | *size = cp.size; | ||
| 248 | |||
| 249 | apply_ucode_in_initrd(cp.data, cp.size); | ||
| 250 | } | ||
| 251 | |||
| 252 | #ifdef CONFIG_X86_32 | ||
| 253 | /* | ||
| 254 | * On 32-bit, since AP's early load occurs before paging is turned on, we | ||
| 255 | * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during | ||
| 256 | * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During | ||
| 257 | * save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch, | ||
| 258 | * which is used upon resume from suspend. | ||
| 259 | */ | ||
| 260 | void load_ucode_amd_ap(void) | ||
| 261 | { | ||
| 262 | struct microcode_amd *mc; | ||
| 263 | size_t *usize; | ||
| 264 | void **ucode; | ||
| 265 | |||
| 266 | mc = (struct microcode_amd *)__pa(amd_ucode_patch); | ||
| 267 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { | ||
| 268 | __apply_microcode_amd(mc); | ||
| 269 | return; | ||
| 270 | } | ||
| 271 | |||
| 272 | ucode = (void *)__pa_nodebug(&container); | ||
| 273 | usize = (size_t *)__pa_nodebug(&container_size); | ||
| 274 | |||
| 275 | if (!*ucode || !*usize) | ||
| 276 | return; | ||
| 277 | |||
| 278 | apply_ucode_in_initrd(*ucode, *usize); | ||
| 279 | } | ||
| 280 | |||
| 281 | static void __init collect_cpu_sig_on_bsp(void *arg) | ||
| 282 | { | ||
| 283 | unsigned int cpu = smp_processor_id(); | ||
| 284 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 285 | |||
| 286 | uci->cpu_sig.sig = cpuid_eax(0x00000001); | ||
| 287 | } | ||
| 288 | #else | ||
| 289 | void load_ucode_amd_ap(void) | ||
| 290 | { | ||
| 291 | unsigned int cpu = smp_processor_id(); | ||
| 292 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 293 | struct equiv_cpu_entry *eq; | ||
| 294 | struct microcode_amd *mc; | ||
| 295 | u32 rev, eax; | ||
| 296 | u16 eq_id; | ||
| 297 | |||
| 298 | /* Exit if called on the BSP. */ | ||
| 299 | if (!cpu) | ||
| 300 | return; | ||
| 301 | |||
| 302 | if (!container) | ||
| 303 | return; | ||
| 304 | |||
| 305 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | ||
| 306 | |||
| 307 | uci->cpu_sig.rev = rev; | ||
| 308 | uci->cpu_sig.sig = eax; | ||
| 309 | |||
| 310 | eax = cpuid_eax(0x00000001); | ||
| 311 | eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ); | ||
| 312 | |||
| 313 | eq_id = find_equiv_id(eq, eax); | ||
| 314 | if (!eq_id) | ||
| 315 | return; | ||
| 316 | |||
| 317 | if (eq_id == this_equiv_id) { | ||
| 318 | mc = (struct microcode_amd *)amd_ucode_patch; | ||
| 319 | |||
| 320 | if (mc && rev < mc->hdr.patch_id) { | ||
| 321 | if (!__apply_microcode_amd(mc)) | ||
| 322 | ucode_new_rev = mc->hdr.patch_id; | ||
| 323 | } | ||
| 324 | |||
| 325 | } else { | ||
| 326 | if (!ucode_cpio.data) | ||
| 327 | return; | ||
| 328 | |||
| 329 | /* | ||
| 330 | * AP has a different equivalence ID than BSP, looks like | ||
| 331 | * mixed-steppings silicon so go through the ucode blob anew. | ||
| 332 | */ | ||
| 333 | apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | #endif | ||
| 337 | |||
| 338 | int __init save_microcode_in_initrd_amd(void) | ||
| 339 | { | ||
| 340 | enum ucode_state ret; | ||
| 341 | u32 eax; | ||
| 342 | |||
| 343 | #ifdef CONFIG_X86_32 | ||
| 344 | unsigned int bsp = boot_cpu_data.cpu_index; | ||
| 345 | struct ucode_cpu_info *uci = ucode_cpu_info + bsp; | ||
| 346 | |||
| 347 | if (!uci->cpu_sig.sig) | ||
| 348 | smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1); | ||
| 349 | |||
| 350 | /* | ||
| 351 | * Take into account the fact that the ramdisk might get relocated | ||
| 352 | * and therefore we need to recompute the container's position in | ||
| 353 | * virtual memory space. | ||
| 354 | */ | ||
| 355 | container = (u8 *)(__va((u32)relocated_ramdisk) + | ||
| 356 | ((u32)container - boot_params.hdr.ramdisk_image)); | ||
| 357 | #endif | ||
| 358 | if (ucode_new_rev) | ||
| 359 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | ||
| 360 | ucode_new_rev); | ||
| 361 | |||
| 362 | if (!container) | ||
| 363 | return -EINVAL; | ||
| 364 | |||
| 365 | eax = cpuid_eax(0x00000001); | ||
| 366 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | ||
| 367 | |||
| 368 | ret = load_microcode_amd(eax, container, container_size); | ||
| 369 | if (ret != UCODE_OK) | ||
| 370 | return -EINVAL; | ||
| 371 | |||
| 372 | /* | ||
| 373 | * This will be freed any msec now, stash patches for the current | ||
| 374 | * family and switch to patch cache for cpu hotplug, etc later. | ||
| 375 | */ | ||
| 376 | container = NULL; | ||
| 377 | container_size = 0; | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | } | ||
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c new file mode 100644 index 000000000000..15c987698b0f --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
| @@ -0,0 +1,645 @@ | |||
| 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 | #include <asm/cpu_device_id.h> | ||
| 90 | #include <asm/perf_event.h> | ||
| 91 | |||
| 92 | MODULE_DESCRIPTION("Microcode Update Driver"); | ||
| 93 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | ||
| 94 | MODULE_LICENSE("GPL"); | ||
| 95 | |||
| 96 | #define MICROCODE_VERSION "2.00" | ||
| 97 | |||
| 98 | static struct microcode_ops *microcode_ops; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Synchronization. | ||
| 102 | * | ||
| 103 | * All non cpu-hotplug-callback call sites use: | ||
| 104 | * | ||
| 105 | * - microcode_mutex to synchronize with each other; | ||
| 106 | * - get/put_online_cpus() to synchronize with | ||
| 107 | * the cpu-hotplug-callback call sites. | ||
| 108 | * | ||
| 109 | * We guarantee that only a single cpu is being | ||
| 110 | * updated at any particular moment of time. | ||
| 111 | */ | ||
| 112 | static DEFINE_MUTEX(microcode_mutex); | ||
| 113 | |||
| 114 | struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; | ||
| 115 | EXPORT_SYMBOL_GPL(ucode_cpu_info); | ||
| 116 | |||
| 117 | /* | ||
| 118 | * Operations that are run on a target cpu: | ||
| 119 | */ | ||
| 120 | |||
| 121 | struct cpu_info_ctx { | ||
| 122 | struct cpu_signature *cpu_sig; | ||
| 123 | int err; | ||
| 124 | }; | ||
| 125 | |||
| 126 | static void collect_cpu_info_local(void *arg) | ||
| 127 | { | ||
| 128 | struct cpu_info_ctx *ctx = arg; | ||
| 129 | |||
| 130 | ctx->err = microcode_ops->collect_cpu_info(smp_processor_id(), | ||
| 131 | ctx->cpu_sig); | ||
| 132 | } | ||
| 133 | |||
| 134 | static int collect_cpu_info_on_target(int cpu, struct cpu_signature *cpu_sig) | ||
| 135 | { | ||
| 136 | struct cpu_info_ctx ctx = { .cpu_sig = cpu_sig, .err = 0 }; | ||
| 137 | int ret; | ||
| 138 | |||
| 139 | ret = smp_call_function_single(cpu, collect_cpu_info_local, &ctx, 1); | ||
| 140 | if (!ret) | ||
| 141 | ret = ctx.err; | ||
| 142 | |||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | static int collect_cpu_info(int cpu) | ||
| 147 | { | ||
| 148 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 149 | int ret; | ||
| 150 | |||
| 151 | memset(uci, 0, sizeof(*uci)); | ||
| 152 | |||
| 153 | ret = collect_cpu_info_on_target(cpu, &uci->cpu_sig); | ||
| 154 | if (!ret) | ||
| 155 | uci->valid = 1; | ||
| 156 | |||
| 157 | return ret; | ||
| 158 | } | ||
| 159 | |||
| 160 | struct apply_microcode_ctx { | ||
| 161 | int err; | ||
| 162 | }; | ||
| 163 | |||
| 164 | static void apply_microcode_local(void *arg) | ||
| 165 | { | ||
| 166 | struct apply_microcode_ctx *ctx = arg; | ||
| 167 | |||
| 168 | ctx->err = microcode_ops->apply_microcode(smp_processor_id()); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int apply_microcode_on_target(int cpu) | ||
| 172 | { | ||
| 173 | struct apply_microcode_ctx ctx = { .err = 0 }; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | ret = smp_call_function_single(cpu, apply_microcode_local, &ctx, 1); | ||
| 177 | if (!ret) | ||
| 178 | ret = ctx.err; | ||
| 179 | |||
| 180 | return ret; | ||
| 181 | } | ||
| 182 | |||
| 183 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE | ||
| 184 | static int do_microcode_update(const void __user *buf, size_t size) | ||
| 185 | { | ||
| 186 | int error = 0; | ||
| 187 | int cpu; | ||
| 188 | |||
| 189 | for_each_online_cpu(cpu) { | ||
| 190 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 191 | enum ucode_state ustate; | ||
| 192 | |||
| 193 | if (!uci->valid) | ||
| 194 | continue; | ||
| 195 | |||
| 196 | ustate = microcode_ops->request_microcode_user(cpu, buf, size); | ||
| 197 | if (ustate == UCODE_ERROR) { | ||
| 198 | error = -1; | ||
| 199 | break; | ||
| 200 | } else if (ustate == UCODE_OK) | ||
| 201 | apply_microcode_on_target(cpu); | ||
| 202 | } | ||
| 203 | |||
| 204 | return error; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int microcode_open(struct inode *inode, struct file *file) | ||
| 208 | { | ||
| 209 | return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM; | ||
| 210 | } | ||
| 211 | |||
| 212 | static ssize_t microcode_write(struct file *file, const char __user *buf, | ||
| 213 | size_t len, loff_t *ppos) | ||
| 214 | { | ||
| 215 | ssize_t ret = -EINVAL; | ||
| 216 | |||
| 217 | if ((len >> PAGE_SHIFT) > totalram_pages) { | ||
| 218 | pr_err("too much data (max %ld pages)\n", totalram_pages); | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | get_online_cpus(); | ||
| 223 | mutex_lock(µcode_mutex); | ||
| 224 | |||
| 225 | if (do_microcode_update(buf, len) == 0) | ||
| 226 | ret = (ssize_t)len; | ||
| 227 | |||
| 228 | if (ret > 0) | ||
| 229 | perf_check_microcode(); | ||
| 230 | |||
| 231 | mutex_unlock(µcode_mutex); | ||
| 232 | put_online_cpus(); | ||
| 233 | |||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | |||
| 237 | static const struct file_operations microcode_fops = { | ||
| 238 | .owner = THIS_MODULE, | ||
| 239 | .write = microcode_write, | ||
| 240 | .open = microcode_open, | ||
| 241 | .llseek = no_llseek, | ||
| 242 | }; | ||
| 243 | |||
| 244 | static struct miscdevice microcode_dev = { | ||
| 245 | .minor = MICROCODE_MINOR, | ||
| 246 | .name = "microcode", | ||
| 247 | .nodename = "cpu/microcode", | ||
| 248 | .fops = µcode_fops, | ||
| 249 | }; | ||
| 250 | |||
| 251 | static int __init microcode_dev_init(void) | ||
| 252 | { | ||
| 253 | int error; | ||
| 254 | |||
| 255 | error = misc_register(µcode_dev); | ||
| 256 | if (error) { | ||
| 257 | pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR); | ||
| 258 | return error; | ||
| 259 | } | ||
| 260 | |||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static void __exit microcode_dev_exit(void) | ||
| 265 | { | ||
| 266 | misc_deregister(µcode_dev); | ||
| 267 | } | ||
| 268 | |||
| 269 | MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); | ||
| 270 | MODULE_ALIAS("devname:cpu/microcode"); | ||
| 271 | #else | ||
| 272 | #define microcode_dev_init() 0 | ||
| 273 | #define microcode_dev_exit() do { } while (0) | ||
| 274 | #endif | ||
| 275 | |||
| 276 | /* fake device for request_firmware */ | ||
| 277 | static struct platform_device *microcode_pdev; | ||
| 278 | |||
| 279 | static int reload_for_cpu(int cpu) | ||
| 280 | { | ||
| 281 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 282 | enum ucode_state ustate; | ||
| 283 | int err = 0; | ||
| 284 | |||
| 285 | if (!uci->valid) | ||
| 286 | return err; | ||
| 287 | |||
| 288 | ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, true); | ||
| 289 | if (ustate == UCODE_OK) | ||
| 290 | apply_microcode_on_target(cpu); | ||
| 291 | else | ||
| 292 | if (ustate == UCODE_ERROR) | ||
| 293 | err = -EINVAL; | ||
| 294 | return err; | ||
| 295 | } | ||
| 296 | |||
| 297 | static ssize_t reload_store(struct device *dev, | ||
| 298 | struct device_attribute *attr, | ||
| 299 | const char *buf, size_t size) | ||
| 300 | { | ||
| 301 | unsigned long val; | ||
| 302 | int cpu; | ||
| 303 | ssize_t ret = 0, tmp_ret; | ||
| 304 | |||
| 305 | ret = kstrtoul(buf, 0, &val); | ||
| 306 | if (ret) | ||
| 307 | return ret; | ||
| 308 | |||
| 309 | if (val != 1) | ||
| 310 | return size; | ||
| 311 | |||
| 312 | get_online_cpus(); | ||
| 313 | mutex_lock(µcode_mutex); | ||
| 314 | for_each_online_cpu(cpu) { | ||
| 315 | tmp_ret = reload_for_cpu(cpu); | ||
| 316 | if (tmp_ret != 0) | ||
| 317 | pr_warn("Error reloading microcode on CPU %d\n", cpu); | ||
| 318 | |||
| 319 | /* save retval of the first encountered reload error */ | ||
| 320 | if (!ret) | ||
| 321 | ret = tmp_ret; | ||
| 322 | } | ||
| 323 | if (!ret) | ||
| 324 | perf_check_microcode(); | ||
| 325 | mutex_unlock(µcode_mutex); | ||
| 326 | put_online_cpus(); | ||
| 327 | |||
| 328 | if (!ret) | ||
| 329 | ret = size; | ||
| 330 | |||
| 331 | return ret; | ||
| 332 | } | ||
| 333 | |||
| 334 | static ssize_t version_show(struct device *dev, | ||
| 335 | struct device_attribute *attr, char *buf) | ||
| 336 | { | ||
| 337 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 338 | |||
| 339 | return sprintf(buf, "0x%x\n", uci->cpu_sig.rev); | ||
| 340 | } | ||
| 341 | |||
| 342 | static ssize_t pf_show(struct device *dev, | ||
| 343 | struct device_attribute *attr, char *buf) | ||
| 344 | { | ||
| 345 | struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; | ||
| 346 | |||
| 347 | return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); | ||
| 348 | } | ||
| 349 | |||
| 350 | static DEVICE_ATTR(reload, 0200, NULL, reload_store); | ||
| 351 | static DEVICE_ATTR(version, 0400, version_show, NULL); | ||
| 352 | static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL); | ||
| 353 | |||
| 354 | static struct attribute *mc_default_attrs[] = { | ||
| 355 | &dev_attr_version.attr, | ||
| 356 | &dev_attr_processor_flags.attr, | ||
| 357 | NULL | ||
| 358 | }; | ||
| 359 | |||
| 360 | static struct attribute_group mc_attr_group = { | ||
| 361 | .attrs = mc_default_attrs, | ||
| 362 | .name = "microcode", | ||
| 363 | }; | ||
| 364 | |||
| 365 | static void microcode_fini_cpu(int cpu) | ||
| 366 | { | ||
| 367 | microcode_ops->microcode_fini_cpu(cpu); | ||
| 368 | } | ||
| 369 | |||
| 370 | static enum ucode_state microcode_resume_cpu(int cpu) | ||
| 371 | { | ||
| 372 | pr_debug("CPU%d updated upon resume\n", cpu); | ||
| 373 | |||
| 374 | if (apply_microcode_on_target(cpu)) | ||
| 375 | return UCODE_ERROR; | ||
| 376 | |||
| 377 | return UCODE_OK; | ||
| 378 | } | ||
| 379 | |||
| 380 | static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) | ||
| 381 | { | ||
| 382 | enum ucode_state ustate; | ||
| 383 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 384 | |||
| 385 | if (uci && uci->valid) | ||
| 386 | return UCODE_OK; | ||
| 387 | |||
| 388 | if (collect_cpu_info(cpu)) | ||
| 389 | return UCODE_ERROR; | ||
| 390 | |||
| 391 | /* --dimm. Trigger a delayed update? */ | ||
| 392 | if (system_state != SYSTEM_RUNNING) | ||
| 393 | return UCODE_NFOUND; | ||
| 394 | |||
| 395 | ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, | ||
| 396 | refresh_fw); | ||
| 397 | |||
| 398 | if (ustate == UCODE_OK) { | ||
| 399 | pr_debug("CPU%d updated upon init\n", cpu); | ||
| 400 | apply_microcode_on_target(cpu); | ||
| 401 | } | ||
| 402 | |||
| 403 | return ustate; | ||
| 404 | } | ||
| 405 | |||
| 406 | static enum ucode_state microcode_update_cpu(int cpu) | ||
| 407 | { | ||
| 408 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 409 | |||
| 410 | if (uci->valid) | ||
| 411 | return microcode_resume_cpu(cpu); | ||
| 412 | |||
| 413 | return microcode_init_cpu(cpu, false); | ||
| 414 | } | ||
| 415 | |||
| 416 | static int mc_device_add(struct device *dev, struct subsys_interface *sif) | ||
| 417 | { | ||
| 418 | int err, cpu = dev->id; | ||
| 419 | |||
| 420 | if (!cpu_online(cpu)) | ||
| 421 | return 0; | ||
| 422 | |||
| 423 | pr_debug("CPU%d added\n", cpu); | ||
| 424 | |||
| 425 | err = sysfs_create_group(&dev->kobj, &mc_attr_group); | ||
| 426 | if (err) | ||
| 427 | return err; | ||
| 428 | |||
| 429 | if (microcode_init_cpu(cpu, true) == UCODE_ERROR) | ||
| 430 | return -EINVAL; | ||
| 431 | |||
| 432 | return err; | ||
| 433 | } | ||
| 434 | |||
| 435 | static int mc_device_remove(struct device *dev, struct subsys_interface *sif) | ||
| 436 | { | ||
| 437 | int cpu = dev->id; | ||
| 438 | |||
| 439 | if (!cpu_online(cpu)) | ||
| 440 | return 0; | ||
| 441 | |||
| 442 | pr_debug("CPU%d removed\n", cpu); | ||
| 443 | microcode_fini_cpu(cpu); | ||
| 444 | sysfs_remove_group(&dev->kobj, &mc_attr_group); | ||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | |||
| 448 | static struct subsys_interface mc_cpu_interface = { | ||
| 449 | .name = "microcode", | ||
| 450 | .subsys = &cpu_subsys, | ||
| 451 | .add_dev = mc_device_add, | ||
| 452 | .remove_dev = mc_device_remove, | ||
| 453 | }; | ||
| 454 | |||
| 455 | /** | ||
| 456 | * mc_bp_resume - Update boot CPU microcode during resume. | ||
| 457 | */ | ||
| 458 | static void mc_bp_resume(void) | ||
| 459 | { | ||
| 460 | int cpu = smp_processor_id(); | ||
| 461 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 462 | |||
| 463 | if (uci->valid && uci->mc) | ||
| 464 | microcode_ops->apply_microcode(cpu); | ||
| 465 | } | ||
| 466 | |||
| 467 | static struct syscore_ops mc_syscore_ops = { | ||
| 468 | .resume = mc_bp_resume, | ||
| 469 | }; | ||
| 470 | |||
| 471 | static int | ||
| 472 | mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | ||
| 473 | { | ||
| 474 | unsigned int cpu = (unsigned long)hcpu; | ||
| 475 | struct device *dev; | ||
| 476 | |||
| 477 | dev = get_cpu_device(cpu); | ||
| 478 | |||
| 479 | switch (action & ~CPU_TASKS_FROZEN) { | ||
| 480 | case CPU_ONLINE: | ||
| 481 | microcode_update_cpu(cpu); | ||
| 482 | pr_debug("CPU%d added\n", cpu); | ||
| 483 | /* | ||
| 484 | * "break" is missing on purpose here because we want to fall | ||
| 485 | * through in order to create the sysfs group. | ||
| 486 | */ | ||
| 487 | |||
| 488 | case CPU_DOWN_FAILED: | ||
| 489 | if (sysfs_create_group(&dev->kobj, &mc_attr_group)) | ||
| 490 | pr_err("Failed to create group for CPU%d\n", cpu); | ||
| 491 | break; | ||
| 492 | |||
| 493 | case CPU_DOWN_PREPARE: | ||
| 494 | /* Suspend is in progress, only remove the interface */ | ||
| 495 | sysfs_remove_group(&dev->kobj, &mc_attr_group); | ||
| 496 | pr_debug("CPU%d removed\n", cpu); | ||
| 497 | break; | ||
| 498 | |||
| 499 | /* | ||
| 500 | * case CPU_DEAD: | ||
| 501 | * | ||
| 502 | * When a CPU goes offline, don't free up or invalidate the copy of | ||
| 503 | * the microcode in kernel memory, so that we can reuse it when the | ||
| 504 | * CPU comes back online without unnecessarily requesting the userspace | ||
| 505 | * for it again. | ||
| 506 | */ | ||
| 507 | } | ||
| 508 | |||
| 509 | /* The CPU refused to come up during a system resume */ | ||
| 510 | if (action == CPU_UP_CANCELED_FROZEN) | ||
| 511 | microcode_fini_cpu(cpu); | ||
| 512 | |||
| 513 | return NOTIFY_OK; | ||
| 514 | } | ||
| 515 | |||
| 516 | static struct notifier_block __refdata mc_cpu_notifier = { | ||
| 517 | .notifier_call = mc_cpu_callback, | ||
| 518 | }; | ||
| 519 | |||
| 520 | #ifdef MODULE | ||
| 521 | /* Autoload on Intel and AMD systems */ | ||
| 522 | static const struct x86_cpu_id __initconst microcode_id[] = { | ||
| 523 | #ifdef CONFIG_MICROCODE_INTEL | ||
| 524 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, }, | ||
| 525 | #endif | ||
| 526 | #ifdef CONFIG_MICROCODE_AMD | ||
| 527 | { X86_VENDOR_AMD, X86_FAMILY_ANY, X86_MODEL_ANY, }, | ||
| 528 | #endif | ||
| 529 | {} | ||
| 530 | }; | ||
| 531 | MODULE_DEVICE_TABLE(x86cpu, microcode_id); | ||
| 532 | #endif | ||
| 533 | |||
| 534 | static struct attribute *cpu_root_microcode_attrs[] = { | ||
| 535 | &dev_attr_reload.attr, | ||
| 536 | NULL | ||
| 537 | }; | ||
| 538 | |||
| 539 | static struct attribute_group cpu_root_microcode_group = { | ||
| 540 | .name = "microcode", | ||
| 541 | .attrs = cpu_root_microcode_attrs, | ||
| 542 | }; | ||
| 543 | |||
| 544 | static int __init microcode_init(void) | ||
| 545 | { | ||
| 546 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
| 547 | int error; | ||
| 548 | |||
| 549 | if (c->x86_vendor == X86_VENDOR_INTEL) | ||
| 550 | microcode_ops = init_intel_microcode(); | ||
| 551 | else if (c->x86_vendor == X86_VENDOR_AMD) | ||
| 552 | microcode_ops = init_amd_microcode(); | ||
| 553 | else | ||
| 554 | pr_err("no support for this CPU vendor\n"); | ||
| 555 | |||
| 556 | if (!microcode_ops) | ||
| 557 | return -ENODEV; | ||
| 558 | |||
| 559 | microcode_pdev = platform_device_register_simple("microcode", -1, | ||
| 560 | NULL, 0); | ||
| 561 | if (IS_ERR(microcode_pdev)) | ||
| 562 | return PTR_ERR(microcode_pdev); | ||
| 563 | |||
| 564 | get_online_cpus(); | ||
| 565 | mutex_lock(µcode_mutex); | ||
| 566 | |||
| 567 | error = subsys_interface_register(&mc_cpu_interface); | ||
| 568 | if (!error) | ||
| 569 | perf_check_microcode(); | ||
| 570 | mutex_unlock(µcode_mutex); | ||
| 571 | put_online_cpus(); | ||
| 572 | |||
| 573 | if (error) | ||
| 574 | goto out_pdev; | ||
| 575 | |||
| 576 | error = sysfs_create_group(&cpu_subsys.dev_root->kobj, | ||
| 577 | &cpu_root_microcode_group); | ||
| 578 | |||
| 579 | if (error) { | ||
| 580 | pr_err("Error creating microcode group!\n"); | ||
| 581 | goto out_driver; | ||
| 582 | } | ||
| 583 | |||
| 584 | error = microcode_dev_init(); | ||
| 585 | if (error) | ||
| 586 | goto out_ucode_group; | ||
| 587 | |||
| 588 | register_syscore_ops(&mc_syscore_ops); | ||
| 589 | register_hotcpu_notifier(&mc_cpu_notifier); | ||
| 590 | |||
| 591 | pr_info("Microcode Update Driver: v" MICROCODE_VERSION | ||
| 592 | " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n"); | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | |||
| 596 | out_ucode_group: | ||
| 597 | sysfs_remove_group(&cpu_subsys.dev_root->kobj, | ||
| 598 | &cpu_root_microcode_group); | ||
| 599 | |||
| 600 | out_driver: | ||
| 601 | get_online_cpus(); | ||
| 602 | mutex_lock(µcode_mutex); | ||
| 603 | |||
| 604 | subsys_interface_unregister(&mc_cpu_interface); | ||
| 605 | |||
| 606 | mutex_unlock(µcode_mutex); | ||
| 607 | put_online_cpus(); | ||
| 608 | |||
| 609 | out_pdev: | ||
| 610 | platform_device_unregister(microcode_pdev); | ||
| 611 | return error; | ||
| 612 | |||
| 613 | } | ||
| 614 | module_init(microcode_init); | ||
| 615 | |||
| 616 | static void __exit microcode_exit(void) | ||
| 617 | { | ||
| 618 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
| 619 | |||
| 620 | microcode_dev_exit(); | ||
| 621 | |||
| 622 | unregister_hotcpu_notifier(&mc_cpu_notifier); | ||
| 623 | unregister_syscore_ops(&mc_syscore_ops); | ||
| 624 | |||
| 625 | sysfs_remove_group(&cpu_subsys.dev_root->kobj, | ||
| 626 | &cpu_root_microcode_group); | ||
| 627 | |||
| 628 | get_online_cpus(); | ||
| 629 | mutex_lock(µcode_mutex); | ||
| 630 | |||
| 631 | subsys_interface_unregister(&mc_cpu_interface); | ||
| 632 | |||
| 633 | mutex_unlock(µcode_mutex); | ||
| 634 | put_online_cpus(); | ||
| 635 | |||
| 636 | platform_device_unregister(microcode_pdev); | ||
| 637 | |||
| 638 | microcode_ops = NULL; | ||
| 639 | |||
| 640 | if (c->x86_vendor == X86_VENDOR_AMD) | ||
| 641 | exit_amd_microcode(); | ||
| 642 | |||
| 643 | pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); | ||
| 644 | } | ||
| 645 | module_exit(microcode_exit); | ||
diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c new file mode 100644 index 000000000000..be7f8514f577 --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/core_early.c | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | /* | ||
| 2 | * X86 CPU microcode early update for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com> | ||
| 5 | * H Peter Anvin" <hpa@zytor.com> | ||
| 6 | * | ||
| 7 | * This driver allows to early 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 9.11 of Volume 3, IA-32 Intel Architecture | ||
| 12 | * Software Developer's Manual. | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or | ||
| 15 | * modify it under the terms of the GNU General Public License | ||
| 16 | * as published by the Free Software Foundation; either version | ||
| 17 | * 2 of the License, or (at your option) any later version. | ||
| 18 | */ | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <asm/microcode_intel.h> | ||
| 21 | #include <asm/microcode_amd.h> | ||
| 22 | #include <asm/processor.h> | ||
| 23 | |||
| 24 | #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) | ||
| 25 | #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') | ||
| 26 | #define CPUID_INTEL2 QCHAR('i', 'n', 'e', 'I') | ||
| 27 | #define CPUID_INTEL3 QCHAR('n', 't', 'e', 'l') | ||
| 28 | #define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') | ||
| 29 | #define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') | ||
| 30 | #define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') | ||
| 31 | |||
| 32 | #define CPUID_IS(a, b, c, ebx, ecx, edx) \ | ||
| 33 | (!((ebx ^ (a))|(edx ^ (b))|(ecx ^ (c)))) | ||
| 34 | |||
| 35 | /* | ||
| 36 | * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. | ||
| 37 | * x86_vendor() gets vendor id for BSP. | ||
| 38 | * | ||
| 39 | * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify | ||
| 40 | * coding, we still use x86_vendor() to get vendor id for AP. | ||
| 41 | * | ||
| 42 | * x86_vendor() gets vendor information directly through cpuid. | ||
| 43 | */ | ||
| 44 | static int x86_vendor(void) | ||
| 45 | { | ||
| 46 | u32 eax = 0x00000000; | ||
| 47 | u32 ebx, ecx = 0, edx; | ||
| 48 | |||
| 49 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
| 50 | |||
| 51 | if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx)) | ||
| 52 | return X86_VENDOR_INTEL; | ||
| 53 | |||
| 54 | if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) | ||
| 55 | return X86_VENDOR_AMD; | ||
| 56 | |||
| 57 | return X86_VENDOR_UNKNOWN; | ||
| 58 | } | ||
| 59 | |||
| 60 | static int x86_family(void) | ||
| 61 | { | ||
| 62 | u32 eax = 0x00000001; | ||
| 63 | u32 ebx, ecx = 0, edx; | ||
| 64 | int x86; | ||
| 65 | |||
| 66 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
| 67 | |||
| 68 | x86 = (eax >> 8) & 0xf; | ||
| 69 | if (x86 == 15) | ||
| 70 | x86 += (eax >> 20) & 0xff; | ||
| 71 | |||
| 72 | return x86; | ||
| 73 | } | ||
| 74 | |||
| 75 | void __init load_ucode_bsp(void) | ||
| 76 | { | ||
| 77 | int vendor, x86; | ||
| 78 | |||
| 79 | if (!have_cpuid_p()) | ||
| 80 | return; | ||
| 81 | |||
| 82 | vendor = x86_vendor(); | ||
| 83 | x86 = x86_family(); | ||
| 84 | |||
| 85 | switch (vendor) { | ||
| 86 | case X86_VENDOR_INTEL: | ||
| 87 | if (x86 >= 6) | ||
| 88 | load_ucode_intel_bsp(); | ||
| 89 | break; | ||
| 90 | case X86_VENDOR_AMD: | ||
| 91 | if (x86 >= 0x10) | ||
| 92 | load_ucode_amd_bsp(); | ||
| 93 | break; | ||
| 94 | default: | ||
| 95 | break; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | void load_ucode_ap(void) | ||
| 100 | { | ||
| 101 | int vendor, x86; | ||
| 102 | |||
| 103 | if (!have_cpuid_p()) | ||
| 104 | return; | ||
| 105 | |||
| 106 | vendor = x86_vendor(); | ||
| 107 | x86 = x86_family(); | ||
| 108 | |||
| 109 | switch (vendor) { | ||
| 110 | case X86_VENDOR_INTEL: | ||
| 111 | if (x86 >= 6) | ||
| 112 | load_ucode_intel_ap(); | ||
| 113 | break; | ||
| 114 | case X86_VENDOR_AMD: | ||
| 115 | if (x86 >= 0x10) | ||
| 116 | load_ucode_amd_ap(); | ||
| 117 | break; | ||
| 118 | default: | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | int __init save_microcode_in_initrd(void) | ||
| 124 | { | ||
| 125 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
| 126 | |||
| 127 | switch (c->x86_vendor) { | ||
| 128 | case X86_VENDOR_INTEL: | ||
| 129 | if (c->x86 >= 6) | ||
| 130 | save_microcode_in_initrd_intel(); | ||
| 131 | break; | ||
| 132 | case X86_VENDOR_AMD: | ||
| 133 | if (c->x86 >= 0x10) | ||
| 134 | save_microcode_in_initrd_amd(); | ||
| 135 | break; | ||
| 136 | default: | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c new file mode 100644 index 000000000000..5fb2cebf556b --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/intel.c | |||
| @@ -0,0 +1,333 @@ | |||
| 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/firmware.h> | ||
| 77 | #include <linux/uaccess.h> | ||
| 78 | #include <linux/kernel.h> | ||
| 79 | #include <linux/module.h> | ||
| 80 | #include <linux/vmalloc.h> | ||
| 81 | |||
| 82 | #include <asm/microcode_intel.h> | ||
| 83 | #include <asm/processor.h> | ||
| 84 | #include <asm/msr.h> | ||
| 85 | |||
| 86 | MODULE_DESCRIPTION("Microcode Update Driver"); | ||
| 87 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | ||
| 88 | MODULE_LICENSE("GPL"); | ||
| 89 | |||
| 90 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | ||
| 91 | { | ||
| 92 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
| 93 | unsigned int val[2]; | ||
| 94 | |||
| 95 | memset(csig, 0, sizeof(*csig)); | ||
| 96 | |||
| 97 | csig->sig = cpuid_eax(0x00000001); | ||
| 98 | |||
| 99 | if ((c->x86_model >= 5) || (c->x86 > 6)) { | ||
| 100 | /* get processor flags from MSR 0x17 */ | ||
| 101 | rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | ||
| 102 | csig->pf = 1 << ((val[1] >> 18) & 7); | ||
| 103 | } | ||
| 104 | |||
| 105 | csig->rev = c->microcode; | ||
| 106 | pr_info("CPU%d sig=0x%x, pf=0x%x, revision=0x%x\n", | ||
| 107 | cpu_num, csig->sig, csig->pf, csig->rev); | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* | ||
| 113 | * return 0 - no update found | ||
| 114 | * return 1 - found update | ||
| 115 | */ | ||
| 116 | static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) | ||
| 117 | { | ||
| 118 | struct cpu_signature cpu_sig; | ||
| 119 | unsigned int csig, cpf, crev; | ||
| 120 | |||
| 121 | collect_cpu_info(cpu, &cpu_sig); | ||
| 122 | |||
| 123 | csig = cpu_sig.sig; | ||
| 124 | cpf = cpu_sig.pf; | ||
| 125 | crev = cpu_sig.rev; | ||
| 126 | |||
| 127 | return get_matching_microcode(csig, cpf, mc_intel, crev); | ||
| 128 | } | ||
| 129 | |||
| 130 | int apply_microcode(int cpu) | ||
| 131 | { | ||
| 132 | struct microcode_intel *mc_intel; | ||
| 133 | struct ucode_cpu_info *uci; | ||
| 134 | unsigned int val[2]; | ||
| 135 | int cpu_num = raw_smp_processor_id(); | ||
| 136 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
| 137 | |||
| 138 | uci = ucode_cpu_info + cpu; | ||
| 139 | mc_intel = uci->mc; | ||
| 140 | |||
| 141 | /* We should bind the task to the CPU */ | ||
| 142 | BUG_ON(cpu_num != cpu); | ||
| 143 | |||
| 144 | if (mc_intel == NULL) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Microcode on this CPU could be updated earlier. Only apply the | ||
| 149 | * microcode patch in mc_intel when it is newer than the one on this | ||
| 150 | * CPU. | ||
| 151 | */ | ||
| 152 | if (get_matching_mc(mc_intel, cpu) == 0) | ||
| 153 | return 0; | ||
| 154 | |||
| 155 | /* write microcode via MSR 0x79 */ | ||
| 156 | wrmsr(MSR_IA32_UCODE_WRITE, | ||
| 157 | (unsigned long) mc_intel->bits, | ||
| 158 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
| 159 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 160 | |||
| 161 | /* As documented in the SDM: Do a CPUID 1 here */ | ||
| 162 | sync_core(); | ||
| 163 | |||
| 164 | /* get the current revision from MSR 0x8B */ | ||
| 165 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
| 166 | |||
| 167 | if (val[1] != mc_intel->hdr.rev) { | ||
| 168 | pr_err("CPU%d update to revision 0x%x failed\n", | ||
| 169 | cpu_num, mc_intel->hdr.rev); | ||
| 170 | return -1; | ||
| 171 | } | ||
| 172 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", | ||
| 173 | cpu_num, val[1], | ||
| 174 | mc_intel->hdr.date & 0xffff, | ||
| 175 | mc_intel->hdr.date >> 24, | ||
| 176 | (mc_intel->hdr.date >> 16) & 0xff); | ||
| 177 | |||
| 178 | uci->cpu_sig.rev = val[1]; | ||
| 179 | c->microcode = val[1]; | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | ||
| 185 | int (*get_ucode_data)(void *, const void *, size_t)) | ||
| 186 | { | ||
| 187 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 188 | u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL; | ||
| 189 | int new_rev = uci->cpu_sig.rev; | ||
| 190 | unsigned int leftover = size; | ||
| 191 | enum ucode_state state = UCODE_OK; | ||
| 192 | unsigned int curr_mc_size = 0; | ||
| 193 | unsigned int csig, cpf; | ||
| 194 | |||
| 195 | while (leftover) { | ||
| 196 | struct microcode_header_intel mc_header; | ||
| 197 | unsigned int mc_size; | ||
| 198 | |||
| 199 | if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header))) | ||
| 200 | break; | ||
| 201 | |||
| 202 | mc_size = get_totalsize(&mc_header); | ||
| 203 | if (!mc_size || mc_size > leftover) { | ||
| 204 | pr_err("error! Bad data in microcode data file\n"); | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* For performance reasons, reuse mc area when possible */ | ||
| 209 | if (!mc || mc_size > curr_mc_size) { | ||
| 210 | vfree(mc); | ||
| 211 | mc = vmalloc(mc_size); | ||
| 212 | if (!mc) | ||
| 213 | break; | ||
| 214 | curr_mc_size = mc_size; | ||
| 215 | } | ||
| 216 | |||
| 217 | if (get_ucode_data(mc, ucode_ptr, mc_size) || | ||
| 218 | microcode_sanity_check(mc, 1) < 0) { | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | |||
| 222 | csig = uci->cpu_sig.sig; | ||
| 223 | cpf = uci->cpu_sig.pf; | ||
| 224 | if (get_matching_microcode(csig, cpf, mc, new_rev)) { | ||
| 225 | vfree(new_mc); | ||
| 226 | new_rev = mc_header.rev; | ||
| 227 | new_mc = mc; | ||
| 228 | mc = NULL; /* trigger new vmalloc */ | ||
| 229 | } | ||
| 230 | |||
| 231 | ucode_ptr += mc_size; | ||
| 232 | leftover -= mc_size; | ||
| 233 | } | ||
| 234 | |||
| 235 | vfree(mc); | ||
| 236 | |||
| 237 | if (leftover) { | ||
| 238 | vfree(new_mc); | ||
| 239 | state = UCODE_ERROR; | ||
| 240 | goto out; | ||
| 241 | } | ||
| 242 | |||
| 243 | if (!new_mc) { | ||
| 244 | state = UCODE_NFOUND; | ||
| 245 | goto out; | ||
| 246 | } | ||
| 247 | |||
| 248 | vfree(uci->mc); | ||
| 249 | uci->mc = (struct microcode_intel *)new_mc; | ||
| 250 | |||
| 251 | /* | ||
| 252 | * If early loading microcode is supported, save this mc into | ||
| 253 | * permanent memory. So it will be loaded early when a CPU is hot added | ||
| 254 | * or resumes. | ||
| 255 | */ | ||
| 256 | save_mc_for_early(new_mc); | ||
| 257 | |||
| 258 | pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", | ||
| 259 | cpu, new_rev, uci->cpu_sig.rev); | ||
| 260 | out: | ||
| 261 | return state; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int get_ucode_fw(void *to, const void *from, size_t n) | ||
| 265 | { | ||
| 266 | memcpy(to, from, n); | ||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static enum ucode_state request_microcode_fw(int cpu, struct device *device, | ||
| 271 | bool refresh_fw) | ||
| 272 | { | ||
| 273 | char name[30]; | ||
| 274 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 275 | const struct firmware *firmware; | ||
| 276 | enum ucode_state ret; | ||
| 277 | |||
| 278 | sprintf(name, "intel-ucode/%02x-%02x-%02x", | ||
| 279 | c->x86, c->x86_model, c->x86_mask); | ||
| 280 | |||
| 281 | if (request_firmware(&firmware, name, device)) { | ||
| 282 | pr_debug("data file %s load failed\n", name); | ||
| 283 | return UCODE_NFOUND; | ||
| 284 | } | ||
| 285 | |||
| 286 | ret = generic_load_microcode(cpu, (void *)firmware->data, | ||
| 287 | firmware->size, &get_ucode_fw); | ||
| 288 | |||
| 289 | release_firmware(firmware); | ||
| 290 | |||
| 291 | return ret; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int get_ucode_user(void *to, const void *from, size_t n) | ||
| 295 | { | ||
| 296 | return copy_from_user(to, from, n); | ||
| 297 | } | ||
| 298 | |||
| 299 | static enum ucode_state | ||
| 300 | request_microcode_user(int cpu, const void __user *buf, size_t size) | ||
| 301 | { | ||
| 302 | return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user); | ||
| 303 | } | ||
| 304 | |||
| 305 | static void microcode_fini_cpu(int cpu) | ||
| 306 | { | ||
| 307 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 308 | |||
| 309 | vfree(uci->mc); | ||
| 310 | uci->mc = NULL; | ||
| 311 | } | ||
| 312 | |||
| 313 | static struct microcode_ops microcode_intel_ops = { | ||
| 314 | .request_microcode_user = request_microcode_user, | ||
| 315 | .request_microcode_fw = request_microcode_fw, | ||
| 316 | .collect_cpu_info = collect_cpu_info, | ||
| 317 | .apply_microcode = apply_microcode, | ||
| 318 | .microcode_fini_cpu = microcode_fini_cpu, | ||
| 319 | }; | ||
| 320 | |||
| 321 | struct microcode_ops * __init init_intel_microcode(void) | ||
| 322 | { | ||
| 323 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
| 324 | |||
| 325 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
| 326 | cpu_has(c, X86_FEATURE_IA64)) { | ||
| 327 | pr_err("Intel CPU family 0x%x not supported\n", c->x86); | ||
| 328 | return NULL; | ||
| 329 | } | ||
| 330 | |||
| 331 | return µcode_intel_ops; | ||
| 332 | } | ||
| 333 | |||
diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c new file mode 100644 index 000000000000..18f739129e72 --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/intel_early.c | |||
| @@ -0,0 +1,787 @@ | |||
| 1 | /* | ||
| 2 | * Intel CPU microcode early update for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com> | ||
| 5 | * H Peter Anvin" <hpa@zytor.com> | ||
| 6 | * | ||
| 7 | * This allows to early 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 9.11 of Volume 3, IA-32 Intel Architecture | ||
| 12 | * Software Developer's Manual. | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or | ||
| 15 | * modify it under the terms of the GNU General Public License | ||
| 16 | * as published by the Free Software Foundation; either version | ||
| 17 | * 2 of the License, or (at your option) any later version. | ||
| 18 | */ | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/mm.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/earlycpio.h> | ||
| 23 | #include <linux/initrd.h> | ||
| 24 | #include <linux/cpu.h> | ||
| 25 | #include <asm/msr.h> | ||
| 26 | #include <asm/microcode_intel.h> | ||
| 27 | #include <asm/processor.h> | ||
| 28 | #include <asm/tlbflush.h> | ||
| 29 | #include <asm/setup.h> | ||
| 30 | |||
| 31 | unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; | ||
| 32 | struct mc_saved_data { | ||
| 33 | unsigned int mc_saved_count; | ||
| 34 | struct microcode_intel **mc_saved; | ||
| 35 | } mc_saved_data; | ||
| 36 | |||
| 37 | static enum ucode_state | ||
| 38 | generic_load_microcode_early(struct microcode_intel **mc_saved_p, | ||
| 39 | unsigned int mc_saved_count, | ||
| 40 | struct ucode_cpu_info *uci) | ||
| 41 | { | ||
| 42 | struct microcode_intel *ucode_ptr, *new_mc = NULL; | ||
| 43 | int new_rev = uci->cpu_sig.rev; | ||
| 44 | enum ucode_state state = UCODE_OK; | ||
| 45 | unsigned int mc_size; | ||
| 46 | struct microcode_header_intel *mc_header; | ||
| 47 | unsigned int csig = uci->cpu_sig.sig; | ||
| 48 | unsigned int cpf = uci->cpu_sig.pf; | ||
| 49 | int i; | ||
| 50 | |||
| 51 | for (i = 0; i < mc_saved_count; i++) { | ||
| 52 | ucode_ptr = mc_saved_p[i]; | ||
| 53 | |||
| 54 | mc_header = (struct microcode_header_intel *)ucode_ptr; | ||
| 55 | mc_size = get_totalsize(mc_header); | ||
| 56 | if (get_matching_microcode(csig, cpf, ucode_ptr, new_rev)) { | ||
| 57 | new_rev = mc_header->rev; | ||
| 58 | new_mc = ucode_ptr; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | if (!new_mc) { | ||
| 63 | state = UCODE_NFOUND; | ||
| 64 | goto out; | ||
| 65 | } | ||
| 66 | |||
| 67 | uci->mc = (struct microcode_intel *)new_mc; | ||
| 68 | out: | ||
| 69 | return state; | ||
| 70 | } | ||
| 71 | |||
| 72 | static void | ||
| 73 | microcode_pointer(struct microcode_intel **mc_saved, | ||
| 74 | unsigned long *mc_saved_in_initrd, | ||
| 75 | unsigned long initrd_start, int mc_saved_count) | ||
| 76 | { | ||
| 77 | int i; | ||
| 78 | |||
| 79 | for (i = 0; i < mc_saved_count; i++) | ||
| 80 | mc_saved[i] = (struct microcode_intel *) | ||
| 81 | (mc_saved_in_initrd[i] + initrd_start); | ||
| 82 | } | ||
| 83 | |||
| 84 | #ifdef CONFIG_X86_32 | ||
| 85 | static void | ||
| 86 | microcode_phys(struct microcode_intel **mc_saved_tmp, | ||
| 87 | struct mc_saved_data *mc_saved_data) | ||
| 88 | { | ||
| 89 | int i; | ||
| 90 | struct microcode_intel ***mc_saved; | ||
| 91 | |||
| 92 | mc_saved = (struct microcode_intel ***) | ||
| 93 | __pa_nodebug(&mc_saved_data->mc_saved); | ||
| 94 | for (i = 0; i < mc_saved_data->mc_saved_count; i++) { | ||
| 95 | struct microcode_intel *p; | ||
| 96 | |||
| 97 | p = *(struct microcode_intel **) | ||
| 98 | __pa_nodebug(mc_saved_data->mc_saved + i); | ||
| 99 | mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | #endif | ||
| 103 | |||
| 104 | static enum ucode_state | ||
| 105 | load_microcode(struct mc_saved_data *mc_saved_data, | ||
| 106 | unsigned long *mc_saved_in_initrd, | ||
| 107 | unsigned long initrd_start, | ||
| 108 | struct ucode_cpu_info *uci) | ||
| 109 | { | ||
| 110 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | ||
| 111 | unsigned int count = mc_saved_data->mc_saved_count; | ||
| 112 | |||
| 113 | if (!mc_saved_data->mc_saved) { | ||
| 114 | microcode_pointer(mc_saved_tmp, mc_saved_in_initrd, | ||
| 115 | initrd_start, count); | ||
| 116 | |||
| 117 | return generic_load_microcode_early(mc_saved_tmp, count, uci); | ||
| 118 | } else { | ||
| 119 | #ifdef CONFIG_X86_32 | ||
| 120 | microcode_phys(mc_saved_tmp, mc_saved_data); | ||
| 121 | return generic_load_microcode_early(mc_saved_tmp, count, uci); | ||
| 122 | #else | ||
| 123 | return generic_load_microcode_early(mc_saved_data->mc_saved, | ||
| 124 | count, uci); | ||
| 125 | #endif | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | static u8 get_x86_family(unsigned long sig) | ||
| 130 | { | ||
| 131 | u8 x86; | ||
| 132 | |||
| 133 | x86 = (sig >> 8) & 0xf; | ||
| 134 | |||
| 135 | if (x86 == 0xf) | ||
| 136 | x86 += (sig >> 20) & 0xff; | ||
| 137 | |||
| 138 | return x86; | ||
| 139 | } | ||
| 140 | |||
| 141 | static u8 get_x86_model(unsigned long sig) | ||
| 142 | { | ||
| 143 | u8 x86, x86_model; | ||
| 144 | |||
| 145 | x86 = get_x86_family(sig); | ||
| 146 | x86_model = (sig >> 4) & 0xf; | ||
| 147 | |||
| 148 | if (x86 == 0x6 || x86 == 0xf) | ||
| 149 | x86_model += ((sig >> 16) & 0xf) << 4; | ||
| 150 | |||
| 151 | return x86_model; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | * Given CPU signature and a microcode patch, this function finds if the | ||
| 156 | * microcode patch has matching family and model with the CPU. | ||
| 157 | */ | ||
| 158 | static enum ucode_state | ||
| 159 | matching_model_microcode(struct microcode_header_intel *mc_header, | ||
| 160 | unsigned long sig) | ||
| 161 | { | ||
| 162 | u8 x86, x86_model; | ||
| 163 | u8 x86_ucode, x86_model_ucode; | ||
| 164 | struct extended_sigtable *ext_header; | ||
| 165 | unsigned long total_size = get_totalsize(mc_header); | ||
| 166 | unsigned long data_size = get_datasize(mc_header); | ||
| 167 | int ext_sigcount, i; | ||
| 168 | struct extended_signature *ext_sig; | ||
| 169 | |||
| 170 | x86 = get_x86_family(sig); | ||
| 171 | x86_model = get_x86_model(sig); | ||
| 172 | |||
| 173 | x86_ucode = get_x86_family(mc_header->sig); | ||
| 174 | x86_model_ucode = get_x86_model(mc_header->sig); | ||
| 175 | |||
| 176 | if (x86 == x86_ucode && x86_model == x86_model_ucode) | ||
| 177 | return UCODE_OK; | ||
| 178 | |||
| 179 | /* Look for ext. headers: */ | ||
| 180 | if (total_size <= data_size + MC_HEADER_SIZE) | ||
| 181 | return UCODE_NFOUND; | ||
| 182 | |||
| 183 | ext_header = (struct extended_sigtable *) | ||
| 184 | mc_header + data_size + MC_HEADER_SIZE; | ||
| 185 | ext_sigcount = ext_header->count; | ||
| 186 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | ||
| 187 | |||
| 188 | for (i = 0; i < ext_sigcount; i++) { | ||
| 189 | x86_ucode = get_x86_family(ext_sig->sig); | ||
| 190 | x86_model_ucode = get_x86_model(ext_sig->sig); | ||
| 191 | |||
| 192 | if (x86 == x86_ucode && x86_model == x86_model_ucode) | ||
| 193 | return UCODE_OK; | ||
| 194 | |||
| 195 | ext_sig++; | ||
| 196 | } | ||
| 197 | |||
| 198 | return UCODE_NFOUND; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int | ||
| 202 | save_microcode(struct mc_saved_data *mc_saved_data, | ||
| 203 | struct microcode_intel **mc_saved_src, | ||
| 204 | unsigned int mc_saved_count) | ||
| 205 | { | ||
| 206 | int i, j; | ||
| 207 | struct microcode_intel **mc_saved_p; | ||
| 208 | int ret; | ||
| 209 | |||
| 210 | if (!mc_saved_count) | ||
| 211 | return -EINVAL; | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Copy new microcode data. | ||
| 215 | */ | ||
| 216 | mc_saved_p = kmalloc(mc_saved_count*sizeof(struct microcode_intel *), | ||
| 217 | GFP_KERNEL); | ||
| 218 | if (!mc_saved_p) | ||
| 219 | return -ENOMEM; | ||
| 220 | |||
| 221 | for (i = 0; i < mc_saved_count; i++) { | ||
| 222 | struct microcode_intel *mc = mc_saved_src[i]; | ||
| 223 | struct microcode_header_intel *mc_header = &mc->hdr; | ||
| 224 | unsigned long mc_size = get_totalsize(mc_header); | ||
| 225 | mc_saved_p[i] = kmalloc(mc_size, GFP_KERNEL); | ||
| 226 | if (!mc_saved_p[i]) { | ||
| 227 | ret = -ENOMEM; | ||
| 228 | goto err; | ||
| 229 | } | ||
| 230 | if (!mc_saved_src[i]) { | ||
| 231 | ret = -EINVAL; | ||
| 232 | goto err; | ||
| 233 | } | ||
| 234 | memcpy(mc_saved_p[i], mc, mc_size); | ||
| 235 | } | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Point to newly saved microcode. | ||
| 239 | */ | ||
| 240 | mc_saved_data->mc_saved = mc_saved_p; | ||
| 241 | mc_saved_data->mc_saved_count = mc_saved_count; | ||
| 242 | |||
| 243 | return 0; | ||
| 244 | |||
| 245 | err: | ||
| 246 | for (j = 0; j <= i; j++) | ||
| 247 | kfree(mc_saved_p[j]); | ||
| 248 | kfree(mc_saved_p); | ||
| 249 | |||
| 250 | return ret; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * A microcode patch in ucode_ptr is saved into mc_saved | ||
| 255 | * - if it has matching signature and newer revision compared to an existing | ||
| 256 | * patch mc_saved. | ||
| 257 | * - or if it is a newly discovered microcode patch. | ||
| 258 | * | ||
| 259 | * The microcode patch should have matching model with CPU. | ||
| 260 | */ | ||
| 261 | static void _save_mc(struct microcode_intel **mc_saved, u8 *ucode_ptr, | ||
| 262 | unsigned int *mc_saved_count_p) | ||
| 263 | { | ||
| 264 | int i; | ||
| 265 | int found = 0; | ||
| 266 | unsigned int mc_saved_count = *mc_saved_count_p; | ||
| 267 | struct microcode_header_intel *mc_header; | ||
| 268 | |||
| 269 | mc_header = (struct microcode_header_intel *)ucode_ptr; | ||
| 270 | for (i = 0; i < mc_saved_count; i++) { | ||
| 271 | unsigned int sig, pf; | ||
| 272 | unsigned int new_rev; | ||
| 273 | struct microcode_header_intel *mc_saved_header = | ||
| 274 | (struct microcode_header_intel *)mc_saved[i]; | ||
| 275 | sig = mc_saved_header->sig; | ||
| 276 | pf = mc_saved_header->pf; | ||
| 277 | new_rev = mc_header->rev; | ||
| 278 | |||
| 279 | if (get_matching_sig(sig, pf, ucode_ptr, new_rev)) { | ||
| 280 | found = 1; | ||
| 281 | if (update_match_revision(mc_header, new_rev)) { | ||
| 282 | /* | ||
| 283 | * Found an older ucode saved before. | ||
| 284 | * Replace the older one with this newer | ||
| 285 | * one. | ||
| 286 | */ | ||
| 287 | mc_saved[i] = | ||
| 288 | (struct microcode_intel *)ucode_ptr; | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | } | ||
| 293 | if (i >= mc_saved_count && !found) | ||
| 294 | /* | ||
| 295 | * This ucode is first time discovered in ucode file. | ||
| 296 | * Save it to memory. | ||
| 297 | */ | ||
| 298 | mc_saved[mc_saved_count++] = | ||
| 299 | (struct microcode_intel *)ucode_ptr; | ||
| 300 | |||
| 301 | *mc_saved_count_p = mc_saved_count; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Get microcode matching with BSP's model. Only CPUs with the same model as | ||
| 306 | * BSP can stay in the platform. | ||
| 307 | */ | ||
| 308 | static enum ucode_state __init | ||
| 309 | get_matching_model_microcode(int cpu, unsigned long start, | ||
| 310 | void *data, size_t size, | ||
| 311 | struct mc_saved_data *mc_saved_data, | ||
| 312 | unsigned long *mc_saved_in_initrd, | ||
| 313 | struct ucode_cpu_info *uci) | ||
| 314 | { | ||
| 315 | u8 *ucode_ptr = data; | ||
| 316 | unsigned int leftover = size; | ||
| 317 | enum ucode_state state = UCODE_OK; | ||
| 318 | unsigned int mc_size; | ||
| 319 | struct microcode_header_intel *mc_header; | ||
| 320 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | ||
| 321 | unsigned int mc_saved_count = mc_saved_data->mc_saved_count; | ||
| 322 | int i; | ||
| 323 | |||
| 324 | while (leftover) { | ||
| 325 | mc_header = (struct microcode_header_intel *)ucode_ptr; | ||
| 326 | |||
| 327 | mc_size = get_totalsize(mc_header); | ||
| 328 | if (!mc_size || mc_size > leftover || | ||
| 329 | microcode_sanity_check(ucode_ptr, 0) < 0) | ||
| 330 | break; | ||
| 331 | |||
| 332 | leftover -= mc_size; | ||
| 333 | |||
| 334 | /* | ||
| 335 | * Since APs with same family and model as the BSP may boot in | ||
| 336 | * the platform, we need to find and save microcode patches | ||
| 337 | * with the same family and model as the BSP. | ||
| 338 | */ | ||
| 339 | if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != | ||
| 340 | UCODE_OK) { | ||
| 341 | ucode_ptr += mc_size; | ||
| 342 | continue; | ||
| 343 | } | ||
| 344 | |||
| 345 | _save_mc(mc_saved_tmp, ucode_ptr, &mc_saved_count); | ||
| 346 | |||
| 347 | ucode_ptr += mc_size; | ||
| 348 | } | ||
| 349 | |||
| 350 | if (leftover) { | ||
| 351 | state = UCODE_ERROR; | ||
| 352 | goto out; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (mc_saved_count == 0) { | ||
| 356 | state = UCODE_NFOUND; | ||
| 357 | goto out; | ||
| 358 | } | ||
| 359 | |||
| 360 | for (i = 0; i < mc_saved_count; i++) | ||
| 361 | mc_saved_in_initrd[i] = (unsigned long)mc_saved_tmp[i] - start; | ||
| 362 | |||
| 363 | mc_saved_data->mc_saved_count = mc_saved_count; | ||
| 364 | out: | ||
| 365 | return state; | ||
| 366 | } | ||
| 367 | |||
| 368 | static int collect_cpu_info_early(struct ucode_cpu_info *uci) | ||
| 369 | { | ||
| 370 | unsigned int val[2]; | ||
| 371 | u8 x86, x86_model; | ||
| 372 | struct cpu_signature csig; | ||
| 373 | unsigned int eax, ebx, ecx, edx; | ||
| 374 | |||
| 375 | csig.sig = 0; | ||
| 376 | csig.pf = 0; | ||
| 377 | csig.rev = 0; | ||
| 378 | |||
| 379 | memset(uci, 0, sizeof(*uci)); | ||
| 380 | |||
| 381 | eax = 0x00000001; | ||
| 382 | ecx = 0; | ||
| 383 | native_cpuid(&eax, &ebx, &ecx, &edx); | ||
| 384 | csig.sig = eax; | ||
| 385 | |||
| 386 | x86 = get_x86_family(csig.sig); | ||
| 387 | x86_model = get_x86_model(csig.sig); | ||
| 388 | |||
| 389 | if ((x86_model >= 5) || (x86 > 6)) { | ||
| 390 | /* get processor flags from MSR 0x17 */ | ||
| 391 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | ||
| 392 | csig.pf = 1 << ((val[1] >> 18) & 7); | ||
| 393 | } | ||
| 394 | native_wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 395 | |||
| 396 | /* As documented in the SDM: Do a CPUID 1 here */ | ||
| 397 | sync_core(); | ||
| 398 | |||
| 399 | /* get the current revision from MSR 0x8B */ | ||
| 400 | native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
| 401 | |||
| 402 | csig.rev = val[1]; | ||
| 403 | |||
| 404 | uci->cpu_sig = csig; | ||
| 405 | uci->valid = 1; | ||
| 406 | |||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | #ifdef DEBUG | ||
| 411 | static void __ref show_saved_mc(void) | ||
| 412 | { | ||
| 413 | int i, j; | ||
| 414 | unsigned int sig, pf, rev, total_size, data_size, date; | ||
| 415 | struct ucode_cpu_info uci; | ||
| 416 | |||
| 417 | if (mc_saved_data.mc_saved_count == 0) { | ||
| 418 | pr_debug("no micorcode data saved.\n"); | ||
| 419 | return; | ||
| 420 | } | ||
| 421 | pr_debug("Total microcode saved: %d\n", mc_saved_data.mc_saved_count); | ||
| 422 | |||
| 423 | collect_cpu_info_early(&uci); | ||
| 424 | |||
| 425 | sig = uci.cpu_sig.sig; | ||
| 426 | pf = uci.cpu_sig.pf; | ||
| 427 | rev = uci.cpu_sig.rev; | ||
| 428 | pr_debug("CPU%d: sig=0x%x, pf=0x%x, rev=0x%x\n", | ||
| 429 | smp_processor_id(), sig, pf, rev); | ||
| 430 | |||
| 431 | for (i = 0; i < mc_saved_data.mc_saved_count; i++) { | ||
| 432 | struct microcode_header_intel *mc_saved_header; | ||
| 433 | struct extended_sigtable *ext_header; | ||
| 434 | int ext_sigcount; | ||
| 435 | struct extended_signature *ext_sig; | ||
| 436 | |||
| 437 | mc_saved_header = (struct microcode_header_intel *) | ||
| 438 | mc_saved_data.mc_saved[i]; | ||
| 439 | sig = mc_saved_header->sig; | ||
| 440 | pf = mc_saved_header->pf; | ||
| 441 | rev = mc_saved_header->rev; | ||
| 442 | total_size = get_totalsize(mc_saved_header); | ||
| 443 | data_size = get_datasize(mc_saved_header); | ||
| 444 | date = mc_saved_header->date; | ||
| 445 | |||
| 446 | pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, toal size=0x%x, date = %04x-%02x-%02x\n", | ||
| 447 | i, sig, pf, rev, total_size, | ||
| 448 | date & 0xffff, | ||
| 449 | date >> 24, | ||
| 450 | (date >> 16) & 0xff); | ||
| 451 | |||
| 452 | /* Look for ext. headers: */ | ||
| 453 | if (total_size <= data_size + MC_HEADER_SIZE) | ||
| 454 | continue; | ||
| 455 | |||
| 456 | ext_header = (struct extended_sigtable *) | ||
| 457 | mc_saved_header + data_size + MC_HEADER_SIZE; | ||
| 458 | ext_sigcount = ext_header->count; | ||
| 459 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | ||
| 460 | |||
| 461 | for (j = 0; j < ext_sigcount; j++) { | ||
| 462 | sig = ext_sig->sig; | ||
| 463 | pf = ext_sig->pf; | ||
| 464 | |||
| 465 | pr_debug("\tExtended[%d]: sig=0x%x, pf=0x%x\n", | ||
| 466 | j, sig, pf); | ||
| 467 | |||
| 468 | ext_sig++; | ||
| 469 | } | ||
| 470 | |||
| 471 | } | ||
| 472 | } | ||
| 473 | #else | ||
| 474 | static inline void show_saved_mc(void) | ||
| 475 | { | ||
| 476 | } | ||
| 477 | #endif | ||
| 478 | |||
| 479 | #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU) | ||
| 480 | static DEFINE_MUTEX(x86_cpu_microcode_mutex); | ||
| 481 | /* | ||
| 482 | * Save this mc into mc_saved_data. So it will be loaded early when a CPU is | ||
| 483 | * hot added or resumes. | ||
| 484 | * | ||
| 485 | * Please make sure this mc should be a valid microcode patch before calling | ||
| 486 | * this function. | ||
| 487 | */ | ||
| 488 | int save_mc_for_early(u8 *mc) | ||
| 489 | { | ||
| 490 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | ||
| 491 | unsigned int mc_saved_count_init; | ||
| 492 | unsigned int mc_saved_count; | ||
| 493 | struct microcode_intel **mc_saved; | ||
| 494 | int ret = 0; | ||
| 495 | int i; | ||
| 496 | |||
| 497 | /* | ||
| 498 | * Hold hotplug lock so mc_saved_data is not accessed by a CPU in | ||
| 499 | * hotplug. | ||
| 500 | */ | ||
| 501 | mutex_lock(&x86_cpu_microcode_mutex); | ||
| 502 | |||
| 503 | mc_saved_count_init = mc_saved_data.mc_saved_count; | ||
| 504 | mc_saved_count = mc_saved_data.mc_saved_count; | ||
| 505 | mc_saved = mc_saved_data.mc_saved; | ||
| 506 | |||
| 507 | if (mc_saved && mc_saved_count) | ||
| 508 | memcpy(mc_saved_tmp, mc_saved, | ||
| 509 | mc_saved_count * sizeof(struct mirocode_intel *)); | ||
| 510 | /* | ||
| 511 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer | ||
| 512 | * version. | ||
| 513 | */ | ||
| 514 | |||
| 515 | _save_mc(mc_saved_tmp, mc, &mc_saved_count); | ||
| 516 | |||
| 517 | /* | ||
| 518 | * Save the mc_save_tmp in global mc_saved_data. | ||
| 519 | */ | ||
| 520 | ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count); | ||
| 521 | if (ret) { | ||
| 522 | pr_err("Cannot save microcode patch.\n"); | ||
| 523 | goto out; | ||
| 524 | } | ||
| 525 | |||
| 526 | show_saved_mc(); | ||
| 527 | |||
| 528 | /* | ||
| 529 | * Free old saved microcod data. | ||
| 530 | */ | ||
| 531 | if (mc_saved) { | ||
| 532 | for (i = 0; i < mc_saved_count_init; i++) | ||
| 533 | kfree(mc_saved[i]); | ||
| 534 | kfree(mc_saved); | ||
| 535 | } | ||
| 536 | |||
| 537 | out: | ||
| 538 | mutex_unlock(&x86_cpu_microcode_mutex); | ||
| 539 | |||
| 540 | return ret; | ||
| 541 | } | ||
| 542 | EXPORT_SYMBOL_GPL(save_mc_for_early); | ||
| 543 | #endif | ||
| 544 | |||
| 545 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; | ||
| 546 | static __init enum ucode_state | ||
| 547 | scan_microcode(unsigned long start, unsigned long end, | ||
| 548 | struct mc_saved_data *mc_saved_data, | ||
| 549 | unsigned long *mc_saved_in_initrd, | ||
| 550 | struct ucode_cpu_info *uci) | ||
| 551 | { | ||
| 552 | unsigned int size = end - start + 1; | ||
| 553 | struct cpio_data cd; | ||
| 554 | long offset = 0; | ||
| 555 | #ifdef CONFIG_X86_32 | ||
| 556 | char *p = (char *)__pa_nodebug(ucode_name); | ||
| 557 | #else | ||
| 558 | char *p = ucode_name; | ||
| 559 | #endif | ||
| 560 | |||
| 561 | cd.data = NULL; | ||
| 562 | cd.size = 0; | ||
| 563 | |||
| 564 | cd = find_cpio_data(p, (void *)start, size, &offset); | ||
| 565 | if (!cd.data) | ||
| 566 | return UCODE_ERROR; | ||
| 567 | |||
| 568 | |||
| 569 | return get_matching_model_microcode(0, start, cd.data, cd.size, | ||
| 570 | mc_saved_data, mc_saved_in_initrd, | ||
| 571 | uci); | ||
| 572 | } | ||
| 573 | |||
| 574 | /* | ||
| 575 | * Print ucode update info. | ||
| 576 | */ | ||
| 577 | static void | ||
| 578 | print_ucode_info(struct ucode_cpu_info *uci, unsigned int date) | ||
| 579 | { | ||
| 580 | int cpu = smp_processor_id(); | ||
| 581 | |||
| 582 | pr_info("CPU%d microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n", | ||
| 583 | cpu, | ||
| 584 | uci->cpu_sig.rev, | ||
| 585 | date & 0xffff, | ||
| 586 | date >> 24, | ||
| 587 | (date >> 16) & 0xff); | ||
| 588 | } | ||
| 589 | |||
| 590 | #ifdef CONFIG_X86_32 | ||
| 591 | |||
| 592 | static int delay_ucode_info; | ||
| 593 | static int current_mc_date; | ||
| 594 | |||
| 595 | /* | ||
| 596 | * Print early updated ucode info after printk works. This is delayed info dump. | ||
| 597 | */ | ||
| 598 | void show_ucode_info_early(void) | ||
| 599 | { | ||
| 600 | struct ucode_cpu_info uci; | ||
| 601 | |||
| 602 | if (delay_ucode_info) { | ||
| 603 | collect_cpu_info_early(&uci); | ||
| 604 | print_ucode_info(&uci, current_mc_date); | ||
| 605 | delay_ucode_info = 0; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 609 | /* | ||
| 610 | * At this point, we can not call printk() yet. Keep microcode patch number in | ||
| 611 | * mc_saved_data.mc_saved and delay printing microcode info in | ||
| 612 | * show_ucode_info_early() until printk() works. | ||
| 613 | */ | ||
| 614 | static void print_ucode(struct ucode_cpu_info *uci) | ||
| 615 | { | ||
| 616 | struct microcode_intel *mc_intel; | ||
| 617 | int *delay_ucode_info_p; | ||
| 618 | int *current_mc_date_p; | ||
| 619 | |||
| 620 | mc_intel = uci->mc; | ||
| 621 | if (mc_intel == NULL) | ||
| 622 | return; | ||
| 623 | |||
| 624 | delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info); | ||
| 625 | current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date); | ||
| 626 | |||
| 627 | *delay_ucode_info_p = 1; | ||
| 628 | *current_mc_date_p = mc_intel->hdr.date; | ||
| 629 | } | ||
| 630 | #else | ||
| 631 | |||
| 632 | /* | ||
| 633 | * Flush global tlb. We only do this in x86_64 where paging has been enabled | ||
| 634 | * already and PGE should be enabled as well. | ||
| 635 | */ | ||
| 636 | static inline void flush_tlb_early(void) | ||
| 637 | { | ||
| 638 | __native_flush_tlb_global_irq_disabled(); | ||
| 639 | } | ||
| 640 | |||
| 641 | static inline void print_ucode(struct ucode_cpu_info *uci) | ||
| 642 | { | ||
| 643 | struct microcode_intel *mc_intel; | ||
| 644 | |||
| 645 | mc_intel = uci->mc; | ||
| 646 | if (mc_intel == NULL) | ||
| 647 | return; | ||
| 648 | |||
| 649 | print_ucode_info(uci, mc_intel->hdr.date); | ||
| 650 | } | ||
| 651 | #endif | ||
| 652 | |||
| 653 | static int apply_microcode_early(struct mc_saved_data *mc_saved_data, | ||
| 654 | struct ucode_cpu_info *uci) | ||
| 655 | { | ||
| 656 | struct microcode_intel *mc_intel; | ||
| 657 | unsigned int val[2]; | ||
| 658 | |||
| 659 | mc_intel = uci->mc; | ||
| 660 | if (mc_intel == NULL) | ||
| 661 | return 0; | ||
| 662 | |||
| 663 | /* write microcode via MSR 0x79 */ | ||
| 664 | native_wrmsr(MSR_IA32_UCODE_WRITE, | ||
| 665 | (unsigned long) mc_intel->bits, | ||
| 666 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
| 667 | native_wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
| 668 | |||
| 669 | /* As documented in the SDM: Do a CPUID 1 here */ | ||
| 670 | sync_core(); | ||
| 671 | |||
| 672 | /* get the current revision from MSR 0x8B */ | ||
| 673 | native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | ||
| 674 | if (val[1] != mc_intel->hdr.rev) | ||
| 675 | return -1; | ||
| 676 | |||
| 677 | #ifdef CONFIG_X86_64 | ||
| 678 | /* Flush global tlb. This is precaution. */ | ||
| 679 | flush_tlb_early(); | ||
| 680 | #endif | ||
| 681 | uci->cpu_sig.rev = val[1]; | ||
| 682 | |||
| 683 | print_ucode(uci); | ||
| 684 | |||
| 685 | return 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | /* | ||
| 689 | * This function converts microcode patch offsets previously stored in | ||
| 690 | * mc_saved_in_initrd to pointers and stores the pointers in mc_saved_data. | ||
| 691 | */ | ||
| 692 | int __init save_microcode_in_initrd_intel(void) | ||
| 693 | { | ||
| 694 | unsigned int count = mc_saved_data.mc_saved_count; | ||
| 695 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; | ||
| 696 | int ret = 0; | ||
| 697 | |||
| 698 | if (count == 0) | ||
| 699 | return ret; | ||
| 700 | |||
| 701 | microcode_pointer(mc_saved, mc_saved_in_initrd, initrd_start, count); | ||
| 702 | ret = save_microcode(&mc_saved_data, mc_saved, count); | ||
| 703 | if (ret) | ||
| 704 | pr_err("Cannot save microcode patches from initrd.\n"); | ||
| 705 | |||
| 706 | show_saved_mc(); | ||
| 707 | |||
| 708 | return ret; | ||
| 709 | } | ||
| 710 | |||
| 711 | static void __init | ||
| 712 | _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | ||
| 713 | unsigned long *mc_saved_in_initrd, | ||
| 714 | unsigned long initrd_start_early, | ||
| 715 | unsigned long initrd_end_early, | ||
| 716 | struct ucode_cpu_info *uci) | ||
| 717 | { | ||
| 718 | collect_cpu_info_early(uci); | ||
| 719 | scan_microcode(initrd_start_early, initrd_end_early, mc_saved_data, | ||
| 720 | mc_saved_in_initrd, uci); | ||
| 721 | load_microcode(mc_saved_data, mc_saved_in_initrd, | ||
| 722 | initrd_start_early, uci); | ||
| 723 | apply_microcode_early(mc_saved_data, uci); | ||
| 724 | } | ||
| 725 | |||
| 726 | void __init | ||
| 727 | load_ucode_intel_bsp(void) | ||
| 728 | { | ||
| 729 | u64 ramdisk_image, ramdisk_size; | ||
| 730 | unsigned long initrd_start_early, initrd_end_early; | ||
| 731 | struct ucode_cpu_info uci; | ||
| 732 | #ifdef CONFIG_X86_32 | ||
| 733 | struct boot_params *boot_params_p; | ||
| 734 | |||
| 735 | boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params); | ||
| 736 | ramdisk_image = boot_params_p->hdr.ramdisk_image; | ||
| 737 | ramdisk_size = boot_params_p->hdr.ramdisk_size; | ||
| 738 | initrd_start_early = ramdisk_image; | ||
| 739 | initrd_end_early = initrd_start_early + ramdisk_size; | ||
| 740 | |||
| 741 | _load_ucode_intel_bsp( | ||
| 742 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | ||
| 743 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), | ||
| 744 | initrd_start_early, initrd_end_early, &uci); | ||
| 745 | #else | ||
| 746 | ramdisk_image = boot_params.hdr.ramdisk_image; | ||
| 747 | ramdisk_size = boot_params.hdr.ramdisk_size; | ||
| 748 | initrd_start_early = ramdisk_image + PAGE_OFFSET; | ||
| 749 | initrd_end_early = initrd_start_early + ramdisk_size; | ||
| 750 | |||
| 751 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, | ||
| 752 | initrd_start_early, initrd_end_early, &uci); | ||
| 753 | #endif | ||
| 754 | } | ||
| 755 | |||
| 756 | void load_ucode_intel_ap(void) | ||
| 757 | { | ||
| 758 | struct mc_saved_data *mc_saved_data_p; | ||
| 759 | struct ucode_cpu_info uci; | ||
| 760 | unsigned long *mc_saved_in_initrd_p; | ||
| 761 | unsigned long initrd_start_addr; | ||
| 762 | #ifdef CONFIG_X86_32 | ||
| 763 | unsigned long *initrd_start_p; | ||
| 764 | |||
| 765 | mc_saved_in_initrd_p = | ||
| 766 | (unsigned long *)__pa_nodebug(mc_saved_in_initrd); | ||
| 767 | mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); | ||
| 768 | initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); | ||
| 769 | initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p); | ||
| 770 | #else | ||
| 771 | mc_saved_data_p = &mc_saved_data; | ||
| 772 | mc_saved_in_initrd_p = mc_saved_in_initrd; | ||
| 773 | initrd_start_addr = initrd_start; | ||
| 774 | #endif | ||
| 775 | |||
| 776 | /* | ||
| 777 | * If there is no valid ucode previously saved in memory, no need to | ||
| 778 | * update ucode on this AP. | ||
| 779 | */ | ||
| 780 | if (mc_saved_data_p->mc_saved_count == 0) | ||
| 781 | return; | ||
| 782 | |||
| 783 | collect_cpu_info_early(&uci); | ||
| 784 | load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, | ||
| 785 | initrd_start_addr, &uci); | ||
| 786 | apply_microcode_early(mc_saved_data_p, &uci); | ||
| 787 | } | ||
diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c new file mode 100644 index 000000000000..ce69320d0179 --- /dev/null +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | /* | ||
| 2 | * Intel CPU Microcode Update Driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com> | ||
| 5 | * H Peter Anvin" <hpa@zytor.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 | */ | ||
| 25 | #include <linux/firmware.h> | ||
| 26 | #include <linux/uaccess.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | |||
| 30 | #include <asm/microcode_intel.h> | ||
| 31 | #include <asm/processor.h> | ||
| 32 | #include <asm/msr.h> | ||
| 33 | |||
| 34 | static inline int | ||
| 35 | update_match_cpu(unsigned int csig, unsigned int cpf, | ||
| 36 | unsigned int sig, unsigned int pf) | ||
| 37 | { | ||
| 38 | return (!sigmatch(sig, csig, pf, cpf)) ? 0 : 1; | ||
| 39 | } | ||
| 40 | |||
| 41 | int | ||
| 42 | update_match_revision(struct microcode_header_intel *mc_header, int rev) | ||
| 43 | { | ||
| 44 | return (mc_header->rev <= rev) ? 0 : 1; | ||
| 45 | } | ||
| 46 | |||
| 47 | int microcode_sanity_check(void *mc, int print_err) | ||
| 48 | { | ||
| 49 | unsigned long total_size, data_size, ext_table_size; | ||
| 50 | struct microcode_header_intel *mc_header = mc; | ||
| 51 | struct extended_sigtable *ext_header = NULL; | ||
| 52 | int sum, orig_sum, ext_sigcount = 0, i; | ||
| 53 | struct extended_signature *ext_sig; | ||
| 54 | |||
| 55 | total_size = get_totalsize(mc_header); | ||
| 56 | data_size = get_datasize(mc_header); | ||
| 57 | |||
| 58 | if (data_size + MC_HEADER_SIZE > total_size) { | ||
| 59 | if (print_err) | ||
| 60 | pr_err("error! Bad data size in microcode data file\n"); | ||
| 61 | return -EINVAL; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { | ||
| 65 | if (print_err) | ||
| 66 | pr_err("error! Unknown microcode update format\n"); | ||
| 67 | return -EINVAL; | ||
| 68 | } | ||
| 69 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | ||
| 70 | if (ext_table_size) { | ||
| 71 | if ((ext_table_size < EXT_HEADER_SIZE) | ||
| 72 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { | ||
| 73 | if (print_err) | ||
| 74 | pr_err("error! Small exttable size in microcode data file\n"); | ||
| 75 | return -EINVAL; | ||
| 76 | } | ||
| 77 | ext_header = mc + MC_HEADER_SIZE + data_size; | ||
| 78 | if (ext_table_size != exttable_size(ext_header)) { | ||
| 79 | if (print_err) | ||
| 80 | pr_err("error! Bad exttable size in microcode data file\n"); | ||
| 81 | return -EFAULT; | ||
| 82 | } | ||
| 83 | ext_sigcount = ext_header->count; | ||
| 84 | } | ||
| 85 | |||
| 86 | /* check extended table checksum */ | ||
| 87 | if (ext_table_size) { | ||
| 88 | int ext_table_sum = 0; | ||
| 89 | int *ext_tablep = (int *)ext_header; | ||
| 90 | |||
| 91 | i = ext_table_size / DWSIZE; | ||
| 92 | while (i--) | ||
| 93 | ext_table_sum += ext_tablep[i]; | ||
| 94 | if (ext_table_sum) { | ||
| 95 | if (print_err) | ||
| 96 | pr_warn("aborting, bad extended signature table checksum\n"); | ||
| 97 | return -EINVAL; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | /* calculate the checksum */ | ||
| 102 | orig_sum = 0; | ||
| 103 | i = (MC_HEADER_SIZE + data_size) / DWSIZE; | ||
| 104 | while (i--) | ||
| 105 | orig_sum += ((int *)mc)[i]; | ||
| 106 | if (orig_sum) { | ||
| 107 | if (print_err) | ||
| 108 | pr_err("aborting, bad checksum\n"); | ||
| 109 | return -EINVAL; | ||
| 110 | } | ||
| 111 | if (!ext_table_size) | ||
| 112 | return 0; | ||
| 113 | /* check extended signature checksum */ | ||
| 114 | for (i = 0; i < ext_sigcount; i++) { | ||
| 115 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + | ||
| 116 | EXT_SIGNATURE_SIZE * i; | ||
| 117 | sum = orig_sum | ||
| 118 | - (mc_header->sig + mc_header->pf + mc_header->cksum) | ||
| 119 | + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); | ||
| 120 | if (sum) { | ||
| 121 | if (print_err) | ||
| 122 | pr_err("aborting, bad checksum\n"); | ||
| 123 | return -EINVAL; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | EXPORT_SYMBOL_GPL(microcode_sanity_check); | ||
| 129 | |||
| 130 | /* | ||
| 131 | * return 0 - no update found | ||
| 132 | * return 1 - found update | ||
| 133 | */ | ||
| 134 | int get_matching_sig(unsigned int csig, int cpf, void *mc, int rev) | ||
| 135 | { | ||
| 136 | struct microcode_header_intel *mc_header = mc; | ||
| 137 | struct extended_sigtable *ext_header; | ||
| 138 | unsigned long total_size = get_totalsize(mc_header); | ||
| 139 | int ext_sigcount, i; | ||
| 140 | struct extended_signature *ext_sig; | ||
| 141 | |||
| 142 | if (update_match_cpu(csig, cpf, mc_header->sig, mc_header->pf)) | ||
| 143 | return 1; | ||
| 144 | |||
| 145 | /* Look for ext. headers: */ | ||
| 146 | if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE) | ||
| 147 | return 0; | ||
| 148 | |||
| 149 | ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE; | ||
| 150 | ext_sigcount = ext_header->count; | ||
| 151 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE; | ||
| 152 | |||
| 153 | for (i = 0; i < ext_sigcount; i++) { | ||
| 154 | if (update_match_cpu(csig, cpf, ext_sig->sig, ext_sig->pf)) | ||
| 155 | return 1; | ||
| 156 | ext_sig++; | ||
| 157 | } | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* | ||
| 162 | * return 0 - no update found | ||
| 163 | * return 1 - found update | ||
| 164 | */ | ||
| 165 | int get_matching_microcode(unsigned int csig, int cpf, void *mc, int rev) | ||
| 166 | { | ||
| 167 | struct microcode_header_intel *mc_header = mc; | ||
| 168 | |||
| 169 | if (!update_match_revision(mc_header, rev)) | ||
| 170 | return 0; | ||
| 171 | |||
| 172 | return get_matching_sig(csig, cpf, mc, rev); | ||
| 173 | } | ||
| 174 | EXPORT_SYMBOL_GPL(get_matching_microcode); | ||
