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.h> 21#include <asm/microcode_intel.h> 22#include <asm/microcode_amd.h> 23#include <asm/processor.h> 24#include <asm/cmdline.h> 25 26static bool __init check_loader_disabled_bsp(void) 27{ 28#ifdef CONFIG_X86_32 29 const char *cmdline = (const char *)__pa_nodebug(boot_command_line); 30 const char *opt = "dis_ucode_ldr"; 31 const char *option = (const char *)__pa_nodebug(opt); 32 bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr); 33 34#else /* CONFIG_X86_64 */ 35 const char *cmdline = boot_command_line; 36 const char *option = "dis_ucode_ldr"; 37 bool *res = &dis_ucode_ldr; 38#endif 39 40 if (cmdline_find_option_bool(cmdline, option)) 41 *res = true; 42 43 return *res; 44} 45 46void __init load_ucode_bsp(void) 47{ 48 int vendor, family; 49 50 if (check_loader_disabled_bsp()) 51 return; 52 53 if (!have_cpuid_p()) 54 return; 55 56 vendor = x86_vendor(); 57 family = x86_family(); 58 59 switch (vendor) { 60 case X86_VENDOR_INTEL: 61 if (family >= 6) 62 load_ucode_intel_bsp(); 63 break; 64 case X86_VENDOR_AMD: 65 if (family >= 0x10) 66 load_ucode_amd_bsp(); 67 break; 68 default: 69 break; 70 } 71} 72 73static bool check_loader_disabled_ap(void) 74{ 75#ifdef CONFIG_X86_32 76 return *((bool *)__pa_nodebug(&dis_ucode_ldr)); 77#else 78 return dis_ucode_ldr; 79#endif 80} 81 82void load_ucode_ap(void) 83{ 84 int vendor, family; 85 86 if (check_loader_disabled_ap()) 87 return; 88 89 if (!have_cpuid_p()) 90 return; 91 92 vendor = x86_vendor(); 93 family = x86_family(); 94 95 switch (vendor) { 96 case X86_VENDOR_INTEL: 97 if (family >= 6) 98 load_ucode_intel_ap(); 99 break; 100 case X86_VENDOR_AMD: 101 if (family >= 0x10) 102 load_ucode_amd_ap(); 103 break; 104 default: 105 break; 106 } 107} 108 109int __init save_microcode_in_initrd(void) 110{ 111 struct cpuinfo_x86 *c = &boot_cpu_data; 112 113 switch (c->x86_vendor) { 114 case X86_VENDOR_INTEL: 115 if (c->x86 >= 6) 116 save_microcode_in_initrd_intel(); 117 break; 118 case X86_VENDOR_AMD: 119 if (c->x86 >= 0x10) 120 save_microcode_in_initrd_amd(); 121 break; 122 default: 123 break; 124 } 125 126 return 0; 127} 128 129void reload_early_microcode(void) 130{ 131 int vendor, family; 132 133 vendor = x86_vendor(); 134 family = x86_family(); 135 136 switch (vendor) { 137 case X86_VENDOR_INTEL: 138 if (family >= 6) 139 reload_ucode_intel(); 140 break; 141 case X86_VENDOR_AMD: 142 if (family >= 0x10) 143 reload_ucode_amd(); 144 break; 145 default: 146 break; 147 } 148} 149