Commit 18dbc916 authored by Dmitry Adamushko's avatar Dmitry Adamushko Committed by Ingo Molnar

x86: moved microcode.c to microcode_intel.c

Combine both generic and arch-specific parts of microcode into a
single module (arch-specific parts are config-dependent).

Also while we are at it, move arch-specific parts from microcode.h
into their respective arch-specific .c files.
Signed-off-by: default avatarDmitry Adamushko <dmitry.adamushko@gmail.com>
Cc: "Peter Oruba" <peter.oruba@amd.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent a1c75cc5
...@@ -801,7 +801,7 @@ config MICROCODE ...@@ -801,7 +801,7 @@ config MICROCODE
module will be called microcode. module will be called microcode.
config MICROCODE_INTEL config MICROCODE_INTEL
tristate "Intel microcode patch loading support" bool "Intel microcode patch loading support"
depends on MICROCODE depends on MICROCODE
default MICROCODE default MICROCODE
select FW_LOADER select FW_LOADER
...@@ -813,20 +813,14 @@ config MICROCODE_INTEL ...@@ -813,20 +813,14 @@ config MICROCODE_INTEL
Intel ingredients for this driver, check: Intel ingredients for this driver, check:
<http://www.urbanmyth.org/microcode/>. <http://www.urbanmyth.org/microcode/>.
This driver is only available as a module: the module
will be called microcode_intel.
config MICROCODE_AMD config MICROCODE_AMD
tristate "AMD microcode patch loading support" bool "AMD microcode patch loading support"
depends on MICROCODE depends on MICROCODE
select FW_LOADER select FW_LOADER
--help--- --help---
If you select this option, microcode patch loading support for AMD If you select this option, microcode patch loading support for AMD
processors will be enabled. processors will be enabled.
This driver is only available as a module: the module
will be called microcode_amd.
config MICROCODE_OLD_INTERFACE config MICROCODE_OLD_INTERFACE
def_bool y def_bool y
depends on MICROCODE depends on MICROCODE
......
...@@ -51,9 +51,6 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o ...@@ -51,9 +51,6 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_MCA) += mca_32.o
obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.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 obj-$(CONFIG_PCI) += early-quirks.o
apm-y := apm_32.o apm-y := apm_32.o
obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_APM) += apm.o
...@@ -101,6 +98,11 @@ scx200-y += scx200_32.o ...@@ -101,6 +98,11 @@ scx200-y += scx200_32.o
obj-$(CONFIG_OLPC) += olpc.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 # 64 bit specific files
ifeq ($(CONFIG_X86_64),y) ifeq ($(CONFIG_X86_64),y)
......
...@@ -46,6 +46,35 @@ MODULE_LICENSE("GPL v2"); ...@@ -46,6 +46,35 @@ MODULE_LICENSE("GPL v2");
#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
#define UCODE_UCODE_TYPE 0x00000001 #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 UCODE_MAX_SIZE (2048)
#define DEFAULT_UCODE_DATASIZE (896) #define DEFAULT_UCODE_DATASIZE (896)
#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd))
...@@ -189,17 +218,18 @@ static void apply_microcode_amd(int cpu) ...@@ -189,17 +218,18 @@ static void apply_microcode_amd(int cpu)
unsigned int rev; unsigned int rev;
int cpu_num = raw_smp_processor_id(); int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
struct microcode_amd *mc_amd = uci->mc;
unsigned long addr; unsigned long addr;
/* We should bind the task to the CPU */ /* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu); BUG_ON(cpu_num != cpu);
if (uci->mc.mc_amd == NULL) if (mc_amd == NULL)
return; return;
spin_lock_irqsave(&microcode_update_lock, flags); spin_lock_irqsave(&microcode_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))); edx = (unsigned int)(((unsigned long)upper_32_bits(addr)));
eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); eax = (unsigned int)(((unsigned long)lower_32_bits(addr)));
...@@ -214,16 +244,16 @@ static void apply_microcode_amd(int cpu) ...@@ -214,16 +244,16 @@ static void apply_microcode_amd(int cpu)
spin_unlock_irqrestore(&microcode_update_lock, flags); spin_unlock_irqrestore(&microcode_update_lock, flags);
/* check current patch id and patch's id for match */ /* 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 " printk(KERN_ERR "microcode: CPU%d update from revision "
"0x%x to 0x%x failed\n", cpu_num, "0x%x to 0x%x failed\n", cpu_num,
uci->mc.mc_amd->hdr.patch_id, rev); mc_amd->hdr.patch_id, rev);
return; return;
} }
printk(KERN_INFO "microcode: CPU%d updated from revision " printk(KERN_INFO "microcode: CPU%d updated from revision "
"0x%x to 0x%x \n", "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; uci->cpu_sig.rev = rev;
} }
...@@ -355,12 +385,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size, ...@@ -355,12 +385,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size,
if (new_mc) { if (new_mc) {
if (!leftover) { if (!leftover) {
if (uci->mc.mc_amd) if (uci->mc)
vfree(uci->mc.mc_amd); vfree(uci->mc);
uci->mc.mc_amd = (struct microcode_amd *)new_mc; uci->mc = new_mc;
pr_debug("microcode: CPU%d found a matching microcode update with" pr_debug("microcode: CPU%d found a matching microcode update with"
" version 0x%x (current=0x%x)\n", " 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 } else
vfree(new_mc); vfree(new_mc);
} }
...@@ -416,8 +446,8 @@ static void microcode_fini_cpu_amd(int cpu) ...@@ -416,8 +446,8 @@ static void microcode_fini_cpu_amd(int cpu)
{ {
struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
vfree(uci->mc.mc_amd); vfree(uci->mc);
uci->mc.mc_amd = NULL; uci->mc = NULL;
} }
static struct microcode_ops microcode_amd_ops = { static struct microcode_ops microcode_amd_ops = {
...@@ -428,23 +458,7 @@ static struct microcode_ops microcode_amd_ops = { ...@@ -428,23 +458,7 @@ static struct microcode_ops microcode_amd_ops = {
.microcode_fini_cpu = microcode_fini_cpu_amd, .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); return &microcode_amd_ops;
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(&microcode_amd_ops, THIS_MODULE);
}
static void __exit microcode_amd_module_exit(void)
{
microcode_exit();
} }
module_init(microcode_amd_module_init)
module_exit(microcode_amd_module_exit)
...@@ -298,7 +298,7 @@ static int microcode_resume_cpu(int cpu) ...@@ -298,7 +298,7 @@ static int microcode_resume_cpu(int cpu)
pr_debug("microcode: CPU%d resumed\n", cpu); pr_debug("microcode: CPU%d resumed\n", cpu);
if (!uci->mc.valid_mc) if (!uci->mc)
return 1; return 1;
/* /*
...@@ -443,17 +443,20 @@ static struct notifier_block __refdata mc_cpu_notifier = { ...@@ -443,17 +443,20 @@ static struct notifier_block __refdata mc_cpu_notifier = {
.notifier_call = mc_cpu_callback, .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; int error;
if (microcode_ops) { if (c->x86_vendor == X86_VENDOR_INTEL)
printk(KERN_ERR "microcode: already loaded the other module\n"); microcode_ops = init_intel_microcode();
return -EEXIST; 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(); error = microcode_dev_init();
if (error) if (error)
...@@ -483,9 +486,8 @@ int microcode_init(void *opaque, struct module *module) ...@@ -483,9 +486,8 @@ int microcode_init(void *opaque, struct module *module)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(microcode_init);
void __exit microcode_exit(void) static void __exit microcode_exit(void)
{ {
microcode_dev_exit(); microcode_dev_exit();
...@@ -502,4 +504,6 @@ void __exit microcode_exit(void) ...@@ -502,4 +504,6 @@ void __exit microcode_exit(void)
printk(KERN_INFO printk(KERN_INFO
"Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
} }
EXPORT_SYMBOL_GPL(microcode_exit);
module_init(microcode_init);
module_exit(microcode_exit);
...@@ -97,6 +97,38 @@ MODULE_DESCRIPTION("Microcode Update Driver"); ...@@ -97,6 +97,38 @@ MODULE_DESCRIPTION("Microcode Update Driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
MODULE_LICENSE("GPL"); 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 DEFAULT_UCODE_DATASIZE (2000)
#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel))
#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
...@@ -284,11 +316,12 @@ static void apply_microcode(int cpu) ...@@ -284,11 +316,12 @@ static void apply_microcode(int cpu)
unsigned int val[2]; unsigned int val[2];
int cpu_num = raw_smp_processor_id(); int cpu_num = raw_smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
struct microcode_intel *mc_intel = uci->mc;
/* We should bind the task to the CPU */ /* We should bind the task to the CPU */
BUG_ON(cpu_num != cpu); BUG_ON(cpu_num != cpu);
if (uci->mc.mc_intel == NULL) if (mc_intel == NULL)
return; return;
/* serialize access to the physical write to MSR 0x79 */ /* serialize access to the physical write to MSR 0x79 */
...@@ -296,8 +329,8 @@ static void apply_microcode(int cpu) ...@@ -296,8 +329,8 @@ static void apply_microcode(int cpu)
/* write microcode via MSR 0x79 */ /* write microcode via MSR 0x79 */
wrmsr(MSR_IA32_UCODE_WRITE, wrmsr(MSR_IA32_UCODE_WRITE,
(unsigned long) uci->mc.mc_intel->bits, (unsigned long) mc_intel->bits,
(unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); (unsigned long) mc_intel->bits >> 16 >> 16);
wrmsr(MSR_IA32_UCODE_REV, 0, 0); wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* see notes above for revision 1.07. Apparent chip bug */ /* see notes above for revision 1.07. Apparent chip bug */
...@@ -307,7 +340,7 @@ static void apply_microcode(int cpu) ...@@ -307,7 +340,7 @@ static void apply_microcode(int cpu)
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
spin_unlock_irqrestore(&microcode_update_lock, flags); spin_unlock_irqrestore(&microcode_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 " printk(KERN_ERR "microcode: CPU%d update from revision "
"0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]);
return; return;
...@@ -315,9 +348,9 @@ static void apply_microcode(int cpu) ...@@ -315,9 +348,9 @@ static void apply_microcode(int cpu)
printk(KERN_INFO "microcode: CPU%d updated from revision " printk(KERN_INFO "microcode: CPU%d updated from revision "
"0x%x to 0x%x, date = %04x-%02x-%02x \n", "0x%x to 0x%x, date = %04x-%02x-%02x \n",
cpu_num, uci->cpu_sig.rev, val[1], cpu_num, uci->cpu_sig.rev, val[1],
uci->mc.mc_intel->hdr.date & 0xffff, mc_intel->hdr.date & 0xffff,
uci->mc.mc_intel->hdr.date >> 24, mc_intel->hdr.date >> 24,
(uci->mc.mc_intel->hdr.date >> 16) & 0xff); (mc_intel->hdr.date >> 16) & 0xff);
uci->cpu_sig.rev = val[1]; uci->cpu_sig.rev = val[1];
} }
...@@ -367,12 +400,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size, ...@@ -367,12 +400,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size,
if (new_mc) { if (new_mc) {
if (!leftover) { if (!leftover) {
if (uci->mc.mc_intel) if (uci->mc)
vfree(uci->mc.mc_intel); vfree(uci->mc);
uci->mc.mc_intel = (struct microcode_intel *)new_mc; uci->mc = (struct microcode_intel *)new_mc;
pr_debug("microcode: CPU%d found a matching microcode update with" pr_debug("microcode: CPU%d found a matching microcode update with"
" version 0x%x (current=0x%x)\n", " 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 } else
vfree(new_mc); vfree(new_mc);
} }
...@@ -428,11 +461,11 @@ static void microcode_fini_cpu(int cpu) ...@@ -428,11 +461,11 @@ static void microcode_fini_cpu(int cpu)
{ {
struct ucode_cpu_info *uci = ucode_cpu_info + cpu; struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
vfree(uci->mc.mc_intel); vfree(uci->mc);
uci->mc.mc_intel = NULL; uci->mc = NULL;
} }
static struct microcode_ops microcode_intel_ops = { struct microcode_ops microcode_intel_ops = {
.request_microcode_user = request_microcode_user, .request_microcode_user = request_microcode_user,
.request_microcode_fw = request_microcode_fw, .request_microcode_fw = request_microcode_fw,
.collect_cpu_info = collect_cpu_info, .collect_cpu_info = collect_cpu_info,
...@@ -440,22 +473,8 @@ static struct microcode_ops microcode_intel_ops = { ...@@ -440,22 +473,8 @@ static struct microcode_ops microcode_intel_ops = {
.microcode_fini_cpu = microcode_fini_cpu, .microcode_fini_cpu = microcode_fini_cpu,
}; };
static int __init microcode_intel_module_init(void) struct microcode_ops * __init init_intel_microcode(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(&microcode_intel_ops, THIS_MODULE);
}
static void __exit microcode_intel_module_exit(void)
{ {
microcode_exit(); return &microcode_intel_ops;
} }
module_init(microcode_intel_module_init)
module_exit(microcode_intel_module_exit)
#ifndef ASM_X86__MICROCODE_H #ifndef ASM_X86__MICROCODE_H
#define ASM_X86__MICROCODE_H #define ASM_X86__MICROCODE_H
extern int microcode_init(void *opaque, struct module *module); struct cpu_signature {
extern void microcode_exit(void); unsigned int sig;
unsigned int pf;
unsigned int rev;
};
struct cpu_signature;
struct device; struct device;
struct microcode_ops { struct microcode_ops {
...@@ -17,82 +19,29 @@ struct microcode_ops { ...@@ -17,82 +19,29 @@ struct microcode_ops {
void (*microcode_fini_cpu) (int cpu); 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 ucode_cpu_info {
struct cpu_signature cpu_sig; struct cpu_signature cpu_sig;
int valid; int valid;
union { void *mc;
struct microcode_intel *mc_intel;
struct microcode_amd *mc_amd;
void *valid_mc;
} mc;
}; };
extern struct ucode_cpu_info ucode_cpu_info[]; 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 */ #endif /* ASM_X86__MICROCODE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment