mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
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: Dmitry Adamushko <dmitry.adamushko@gmail.com> Cc: "Peter Oruba" <peter.oruba@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
a1c75cc501
commit
18dbc91605
@ -801,7 +801,7 @@ config MICROCODE
|
||||
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
|
||||
@ -813,20 +813,14 @@ config MICROCODE_INTEL
|
||||
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
|
||||
|
@ -51,9 +51,6 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
|
||||
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
|
||||
@ -101,6 +98,11 @@ scx200-y += scx200_32.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)
|
||||
|
@ -46,6 +46,35 @@ MODULE_LICENSE("GPL v2");
|
||||
#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))
|
||||
@ -189,17 +218,18 @@ static void apply_microcode_amd(int cpu)
|
||||
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)));
|
||||
|
||||
@ -214,16 +244,16 @@ static void apply_microcode_amd(int cpu)
|
||||
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;
|
||||
}
|
||||
@ -355,12 +385,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size,
|
||||
|
||||
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);
|
||||
}
|
||||
@ -416,8 +446,8 @@ static void microcode_fini_cpu_amd(int cpu)
|
||||
{
|
||||
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 = {
|
||||
@ -428,23 +458,7 @@ 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);
|
||||
return µcode_amd_ops;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
pr_debug("microcode: CPU%d resumed\n", cpu);
|
||||
|
||||
if (!uci->mc.valid_mc)
|
||||
if (!uci->mc)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -443,17 +443,20 @@ static struct notifier_block __refdata mc_cpu_notifier = {
|
||||
.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)
|
||||
@ -483,9 +486,8 @@ int microcode_init(void *opaque, struct module *module)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(microcode_init);
|
||||
|
||||
void __exit microcode_exit(void)
|
||||
static void __exit microcode_exit(void)
|
||||
{
|
||||
microcode_dev_exit();
|
||||
|
||||
@ -502,4 +504,6 @@ void __exit microcode_exit(void)
|
||||
printk(KERN_INFO
|
||||
"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");
|
||||
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)
|
||||
@ -284,11 +316,12 @@ static void apply_microcode(int cpu)
|
||||
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 */
|
||||
@ -296,8 +329,8 @@ static void apply_microcode(int cpu)
|
||||
|
||||
/* 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 */
|
||||
@ -307,7 +340,7 @@ static void apply_microcode(int cpu)
|
||||
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;
|
||||
@ -315,9 +348,9 @@ static void apply_microcode(int cpu)
|
||||
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];
|
||||
}
|
||||
|
||||
@ -367,12 +400,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size,
|
||||
|
||||
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);
|
||||
}
|
||||
@ -428,11 +461,11 @@ static void microcode_fini_cpu(int cpu)
|
||||
{
|
||||
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,
|
||||
@ -440,22 +473,8 @@ static struct microcode_ops microcode_intel_ops = {
|
||||
.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(µcode_intel_ops, THIS_MODULE);
|
||||
return µcode_intel_ops;
|
||||
}
|
||||
|
||||
static void __exit microcode_intel_module_exit(void)
|
||||
{
|
||||
microcode_exit();
|
||||
}
|
||||
|
||||
module_init(microcode_intel_module_init)
|
||||
module_exit(microcode_intel_module_exit)
|
||||
|
@ -1,10 +1,12 @@
|
||||
#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 {
|
||||
@ -17,82 +19,29 @@ 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user