Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -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
+5 −3
Original line number Diff line number Diff line
@@ -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)
+43 −29
Original line number Diff line number Diff line
@@ -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(&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)));
	eax = (unsigned int)(((unsigned long)lower_32_bits(addr)));

@@ -214,16 +244,16 @@ static void apply_microcode_amd(int cpu)
	spin_unlock_irqrestore(&microcode_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 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(&microcode_amd_ops, THIS_MODULE);
}

static void __exit microcode_amd_module_exit(void)
struct microcode_ops * __init init_amd_microcode(void)
{
	microcode_exit();
	return &microcode_amd_ops;
}

module_init(microcode_amd_module_init)
module_exit(microcode_amd_module_exit)
+15 −11
Original line number Diff line number Diff line
@@ -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);
+49 −30
Original line number Diff line number Diff line
@@ -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(&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 "
			"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 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)
struct microcode_ops * __init init_intel_microcode(void)
{
	microcode_exit();
	return &microcode_intel_ops;
}
module_init(microcode_intel_module_init)
module_exit(microcode_intel_module_exit)
Loading