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 Original line Diff line number Diff line
@@ -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
         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
+5 −3
Original line number Original line Diff line number Diff line
@@ -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


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)
+43 −29
Original line number Original line Diff line number Diff line
@@ -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)
	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)
	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,


	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)
{
{
	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 = {
	.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);

	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();
	return &microcode_amd_ops;
}
}

module_init(microcode_amd_module_init)
module_exit(microcode_amd_module_exit)
+15 −11
Original line number Original line Diff line number Diff line
@@ -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 = {
	.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)


	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)
	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);
+49 −30
Original line number Original line Diff line number Diff line
@@ -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)
	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)


	/* 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)
	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)
	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,


	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)
{
{
	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 = {
	.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)
Loading