module will be called microcode.
config MICROCODE_INTEL
- tristate "Intel microcode patch loading support"
+ bool "Intel microcode patch loading support"
depends on MICROCODE
default MICROCODE
select FW_LOADER
Intel ingredients for this driver, check:
<http://www.urbanmyth.org/microcode/>.
- This driver is only available as a module: the module
- will be called microcode_intel.
-
config MICROCODE_AMD
- tristate "AMD microcode patch loading support"
+ bool "AMD microcode patch loading support"
depends on MICROCODE
select FW_LOADER
--help---
If you select this option, microcode patch loading support for AMD
processors will be enabled.
- This driver is only available as a module: the module
- will be called microcode_amd.
-
config MICROCODE_OLD_INTERFACE
def_bool y
depends on MICROCODE
obj-$(CONFIG_MCA) += mca_32.o
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
-obj-$(CONFIG_MICROCODE) += microcode.o
-obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
-obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
obj-$(CONFIG_PCI) += early-quirks.o
apm-y := apm_32.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_OLPC) += olpc.o
+microcode-y := microcode_core.o
+microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
+microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
+obj-$(CONFIG_MICROCODE) += microcode.o
+
###
# 64 bit specific files
ifeq ($(CONFIG_X86_64),y)
#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
#define UCODE_UCODE_TYPE 0x00000001
+struct equiv_cpu_entry {
+ unsigned int installed_cpu;
+ unsigned int fixed_errata_mask;
+ unsigned int fixed_errata_compare;
+ unsigned int equiv_cpu;
+};
+
+struct microcode_header_amd {
+ unsigned int data_code;
+ unsigned int patch_id;
+ unsigned char mc_patch_data_id[2];
+ unsigned char mc_patch_data_len;
+ unsigned char init_flag;
+ unsigned int mc_patch_data_checksum;
+ unsigned int nb_dev_id;
+ unsigned int sb_dev_id;
+ unsigned char processor_rev_id[2];
+ unsigned char nb_rev_id;
+ unsigned char sb_rev_id;
+ unsigned char bios_api_rev;
+ unsigned char reserved1[3];
+ unsigned int match_reg[8];
+};
+
+struct microcode_amd {
+ struct microcode_header_amd hdr;
+ unsigned int mpb[0];
+};
+
#define UCODE_MAX_SIZE (2048)
#define DEFAULT_UCODE_DATASIZE (896)
#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd))
unsigned int rev;
int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+ struct microcode_amd *mc_amd = uci->mc;
unsigned long addr;
/* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu);
- if (uci->mc.mc_amd == NULL)
+ if (mc_amd == NULL)
return;
spin_lock_irqsave(µcode_update_lock, flags);
- addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code;
+ addr = (unsigned long)&mc_amd->hdr.data_code;
edx = (unsigned int)(((unsigned long)upper_32_bits(addr)));
eax = (unsigned int)(((unsigned long)lower_32_bits(addr)));
spin_unlock_irqrestore(µcode_update_lock, flags);
/* check current patch id and patch's id for match */
- if (rev != uci->mc.mc_amd->hdr.patch_id) {
+ if (rev != mc_amd->hdr.patch_id) {
printk(KERN_ERR "microcode: CPU%d update from revision "
"0x%x to 0x%x failed\n", cpu_num,
- uci->mc.mc_amd->hdr.patch_id, rev);
+ mc_amd->hdr.patch_id, rev);
return;
}
printk(KERN_INFO "microcode: CPU%d updated from revision "
"0x%x to 0x%x \n",
- cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id);
+ cpu_num, uci->cpu_sig.rev, mc_amd->hdr.patch_id);
uci->cpu_sig.rev = rev;
}
if (new_mc) {
if (!leftover) {
- if (uci->mc.mc_amd)
- vfree(uci->mc.mc_amd);
- uci->mc.mc_amd = (struct microcode_amd *)new_mc;
+ if (uci->mc)
+ vfree(uci->mc);
+ uci->mc = new_mc;
pr_debug("microcode: CPU%d found a matching microcode update with"
" version 0x%x (current=0x%x)\n",
- cpu, uci->mc.mc_amd->hdr.patch_id, uci->cpu_sig.rev);
+ cpu, new_rev, uci->cpu_sig.rev);
} else
vfree(new_mc);
}
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- vfree(uci->mc.mc_amd);
- uci->mc.mc_amd = NULL;
+ vfree(uci->mc);
+ uci->mc = NULL;
}
static struct microcode_ops microcode_amd_ops = {
.microcode_fini_cpu = microcode_fini_cpu_amd,
};
-static int __init microcode_amd_module_init(void)
+struct microcode_ops * __init init_amd_microcode(void)
{
- struct cpuinfo_x86 *c = &cpu_data(0);
-
- equiv_cpu_table = NULL;
- if (c->x86_vendor != X86_VENDOR_AMD) {
- printk(KERN_ERR "microcode: CPU platform is not AMD-capable\n");
- return -ENODEV;
- }
-
- return microcode_init(µcode_amd_ops, THIS_MODULE);
-}
-
-static void __exit microcode_amd_module_exit(void)
-{
- microcode_exit();
+ return µcode_amd_ops;
}
-
-module_init(microcode_amd_module_init)
-module_exit(microcode_amd_module_exit)
pr_debug("microcode: CPU%d resumed\n", cpu);
- if (!uci->mc.valid_mc)
+ if (!uci->mc)
return 1;
/*
.notifier_call = mc_cpu_callback,
};
-int microcode_init(void *opaque, struct module *module)
+static int __init microcode_init(void)
{
- struct microcode_ops *ops = (struct microcode_ops *)opaque;
+ struct cpuinfo_x86 *c = &cpu_data(0);
int error;
- if (microcode_ops) {
- printk(KERN_ERR "microcode: already loaded the other module\n");
- return -EEXIST;
- }
+ if (c->x86_vendor == X86_VENDOR_INTEL)
+ microcode_ops = init_intel_microcode();
+ else if (c->x86_vendor != X86_VENDOR_AMD)
+ microcode_ops = init_amd_microcode();
- microcode_ops = ops;
+ if (!microcode_ops) {
+ printk(KERN_ERR "microcode: no support for this CPU vendor\n");
+ return -ENODEV;
+ }
error = microcode_dev_init();
if (error)
return 0;
}
-EXPORT_SYMBOL_GPL(microcode_init);
-void __exit microcode_exit(void)
+static void __exit microcode_exit(void)
{
microcode_dev_exit();
printk(KERN_INFO
"Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
}
-EXPORT_SYMBOL_GPL(microcode_exit);
+
+module_init(microcode_init);
+module_exit(microcode_exit);
MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
MODULE_LICENSE("GPL");
+struct microcode_header_intel {
+ unsigned int hdrver;
+ unsigned int rev;
+ unsigned int date;
+ unsigned int sig;
+ unsigned int cksum;
+ unsigned int ldrver;
+ unsigned int pf;
+ unsigned int datasize;
+ unsigned int totalsize;
+ unsigned int reserved[3];
+};
+
+struct microcode_intel {
+ struct microcode_header_intel hdr;
+ unsigned int bits[0];
+};
+
+/* microcode format is extended from prescott processors */
+struct extended_signature {
+ unsigned int sig;
+ unsigned int pf;
+ unsigned int cksum;
+};
+
+struct extended_sigtable {
+ unsigned int count;
+ unsigned int cksum;
+ unsigned int reserved[3];
+ struct extended_signature sigs[0];
+};
+
#define DEFAULT_UCODE_DATASIZE (2000)
#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel))
#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
unsigned int val[2];
int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ struct microcode_intel *mc_intel = uci->mc;
/* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu);
- if (uci->mc.mc_intel == NULL)
+ if (mc_intel == NULL)
return;
/* serialize access to the physical write to MSR 0x79 */
/* write microcode via MSR 0x79 */
wrmsr(MSR_IA32_UCODE_WRITE,
- (unsigned long) uci->mc.mc_intel->bits,
- (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
+ (unsigned long) mc_intel->bits,
+ (unsigned long) mc_intel->bits >> 16 >> 16);
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* see notes above for revision 1.07. Apparent chip bug */
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
spin_unlock_irqrestore(µcode_update_lock, flags);
- if (val[1] != uci->mc.mc_intel->hdr.rev) {
+ if (val[1] != mc_intel->hdr.rev) {
printk(KERN_ERR "microcode: CPU%d update from revision "
"0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]);
return;
printk(KERN_INFO "microcode: CPU%d updated from revision "
"0x%x to 0x%x, date = %04x-%02x-%02x \n",
cpu_num, uci->cpu_sig.rev, val[1],
- uci->mc.mc_intel->hdr.date & 0xffff,
- uci->mc.mc_intel->hdr.date >> 24,
- (uci->mc.mc_intel->hdr.date >> 16) & 0xff);
+ mc_intel->hdr.date & 0xffff,
+ mc_intel->hdr.date >> 24,
+ (mc_intel->hdr.date >> 16) & 0xff);
uci->cpu_sig.rev = val[1];
}
if (new_mc) {
if (!leftover) {
- if (uci->mc.mc_intel)
- vfree(uci->mc.mc_intel);
- uci->mc.mc_intel = (struct microcode_intel *)new_mc;
+ if (uci->mc)
+ vfree(uci->mc);
+ uci->mc = (struct microcode_intel *)new_mc;
pr_debug("microcode: CPU%d found a matching microcode update with"
" version 0x%x (current=0x%x)\n",
- cpu, uci->mc.mc_intel->hdr.rev, uci->cpu_sig.rev);
+ cpu, new_rev, uci->cpu_sig.rev);
} else
vfree(new_mc);
}
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- vfree(uci->mc.mc_intel);
- uci->mc.mc_intel = NULL;
+ vfree(uci->mc);
+ uci->mc = NULL;
}
-static struct microcode_ops microcode_intel_ops = {
+struct microcode_ops microcode_intel_ops = {
.request_microcode_user = request_microcode_user,
.request_microcode_fw = request_microcode_fw,
.collect_cpu_info = collect_cpu_info,
.microcode_fini_cpu = microcode_fini_cpu,
};
-static int __init microcode_intel_module_init(void)
-{
- struct cpuinfo_x86 *c = &cpu_data(0);
-
- if (c->x86_vendor != X86_VENDOR_INTEL) {
- printk(KERN_ERR "microcode: CPU platform is not Intel-capable\n");
- return -ENODEV;
- }
-
- return microcode_init(µcode_intel_ops, THIS_MODULE);
-}
-
-static void __exit microcode_intel_module_exit(void)
+struct microcode_ops * __init init_intel_microcode(void)
{
- microcode_exit();
+ return µcode_intel_ops;
}
-module_init(microcode_intel_module_init)
-module_exit(microcode_intel_module_exit)
#ifndef ASM_X86__MICROCODE_H
#define ASM_X86__MICROCODE_H
-extern int microcode_init(void *opaque, struct module *module);
-extern void microcode_exit(void);
+struct cpu_signature {
+ unsigned int sig;
+ unsigned int pf;
+ unsigned int rev;
+};
-struct cpu_signature;
struct device;
struct microcode_ops {
void (*microcode_fini_cpu) (int cpu);
};
-struct microcode_header_intel {
- unsigned int hdrver;
- unsigned int rev;
- unsigned int date;
- unsigned int sig;
- unsigned int cksum;
- unsigned int ldrver;
- unsigned int pf;
- unsigned int datasize;
- unsigned int totalsize;
- unsigned int reserved[3];
-};
-
-struct microcode_intel {
- struct microcode_header_intel hdr;
- unsigned int bits[0];
-};
-
-/* microcode format is extended from prescott processors */
-struct extended_signature {
- unsigned int sig;
- unsigned int pf;
- unsigned int cksum;
-};
-
-struct extended_sigtable {
- unsigned int count;
- unsigned int cksum;
- unsigned int reserved[3];
- struct extended_signature sigs[0];
-};
-
-struct equiv_cpu_entry {
- unsigned int installed_cpu;
- unsigned int fixed_errata_mask;
- unsigned int fixed_errata_compare;
- unsigned int equiv_cpu;
-};
-
-struct microcode_header_amd {
- unsigned int data_code;
- unsigned int patch_id;
- unsigned char mc_patch_data_id[2];
- unsigned char mc_patch_data_len;
- unsigned char init_flag;
- unsigned int mc_patch_data_checksum;
- unsigned int nb_dev_id;
- unsigned int sb_dev_id;
- unsigned char processor_rev_id[2];
- unsigned char nb_rev_id;
- unsigned char sb_rev_id;
- unsigned char bios_api_rev;
- unsigned char reserved1[3];
- unsigned int match_reg[8];
-};
-
-struct microcode_amd {
- struct microcode_header_amd hdr;
- unsigned int mpb[0];
-};
-
-struct cpu_signature {
- unsigned int sig;
- unsigned int pf;
- unsigned int rev;
-};
-
struct ucode_cpu_info {
struct cpu_signature cpu_sig;
int valid;
- union {
- struct microcode_intel *mc_intel;
- struct microcode_amd *mc_amd;
- void *valid_mc;
- } mc;
+ void *mc;
};
extern struct ucode_cpu_info ucode_cpu_info[];
+#ifdef CONFIG_MICROCODE_INTEL
+extern struct microcode_ops * __init init_intel_microcode(void);
+#else
+static inline struct microcode_ops * __init init_intel_microcode(void)
+{
+ return NULL;
+}
+#endif /* CONFIG_MICROCODE_INTEL */
+
+#ifdef CONFIG_MICROCODE_AMD
+extern struct microcode_ops * __init init_amd_microcode(void);
+#else
+static inline struct microcode_ops * __init init_amd_microcode(void)
+{
+ return NULL;
+}
+#endif
+
#endif /* ASM_X86__MICROCODE_H */