linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/9] x86: AMD microcode patch loading support
@ 2008-07-25 16:17 Peter Oruba
  2008-07-25 16:17 ` [patch 1/9] [PATCH 1/9] x86: Moved Intel microcode patch loader declarations to seperate header file Peter Oruba
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML

This patch set introduces microcode patch loading support for AMD processors. It includes refactoring
of existing code to allow code sharing. Vendor specific code has been split off, leading to a
multi-module solution as compared to the current single-module approach.

Thanks,

Peter Oruba

--
Advanced Micro Devices, Inc.
Operating System Research Center
email: peter.oruba@amd.com
>From peter.oruba@amd.com Fri Jul 25 18:20:02 2008
Message-Id: <20080725162001.917239960@amd.com>
User-Agent: quilt/0.46_cvs20080326-19.1
Date: Fri, 25 Jul 2008 18:17:24 +0200
From: Peter Oruba <peter.oruba@amd.com>
To: Ingo Molnar <mingo@elte.hu>,
 Thomas Gleixner <tglx@linutronix.de>,
 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
Cc: LKML <linux-kernel@vger.kernel.org>,
 Peter Oruba <peter.oruba@amd.com>
Bcc: osrc-patches@elbe.amd.com
Subject: [patch 1/9] [PATCH 1/9] x86: Moved Intel microcode patch loader declarations to seperate header file.
References: <20080725161723.636932280@amd.com>
Content-Disposition: inline; filename=0001-x86-Moved-Intel-microcode-patch-loader-declarations.patch

Intel specific microcode declarations have been moved to a seperate header file.
There are no code changes to the code itself and no side effects to other parts.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/kernel/microcode.c |    1 +
 include/asm-x86/microcode.h |   34 ++++++++++++++++++++++++++++++++++
 include/asm-x86/processor.h |   35 -----------------------------------
 3 files changed, 35 insertions(+), 35 deletions(-)
 create mode 100644 include/asm-x86/microcode.h

diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 56b9331..230ca7e 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -93,6 +93,7 @@
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
+#include <asm/microcode.h>
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
new file mode 100644
index 0000000..5a05568
--- /dev/null
+++ b/include/asm-x86/microcode.h
@@ -0,0 +1,34 @@
+struct microcode_header {
+	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 {
+	struct microcode_header hdr;
+	unsigned int            bits[0];
+};
+
+typedef struct microcode          microcode_t;
+typedef struct microcode_header   microcode_header_t;
+
+/* 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];
+};
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
index 15cb82a..f3c5c93 100644
--- a/include/asm-x86/processor.h
+++ b/include/asm-x86/processor.h
@@ -561,41 +561,6 @@ static inline void clear_in_cr4(unsigned long mask)
 	write_cr4(cr4);
 }
 
-struct microcode_header {
-	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 {
-	struct microcode_header	hdr;
-	unsigned int		bits[0];
-};
-
-typedef struct microcode	microcode_t;
-typedef struct microcode_header	microcode_header_t;
-
-/* 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];
-};
-
 typedef struct {
 	unsigned long		seg;
 } mm_segment_t;
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 1/9] [PATCH 1/9] x86: Moved Intel microcode patch loader declarations to seperate header file.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 2/9] [PATCH 2/9] x86: Typedef removal Peter Oruba
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0001-x86-Moved-Intel-microcode-patch-loader-declarations.patch --]
[-- Type: text/plain, Size: 3123 bytes --]

Intel specific microcode declarations have been moved to a seperate header file.
There are no code changes to the code itself and no side effects to other parts.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/kernel/microcode.c |    1 +
 include/asm-x86/microcode.h |   34 ++++++++++++++++++++++++++++++++++
 include/asm-x86/processor.h |   35 -----------------------------------
 3 files changed, 35 insertions(+), 35 deletions(-)
 create mode 100644 include/asm-x86/microcode.h

diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 56b9331..230ca7e 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -93,6 +93,7 @@
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
+#include <asm/microcode.h>
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
new file mode 100644
index 0000000..5a05568
--- /dev/null
+++ b/include/asm-x86/microcode.h
@@ -0,0 +1,34 @@
+struct microcode_header {
+	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 {
+	struct microcode_header hdr;
+	unsigned int            bits[0];
+};
+
+typedef struct microcode          microcode_t;
+typedef struct microcode_header   microcode_header_t;
+
+/* 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];
+};
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
index 15cb82a..f3c5c93 100644
--- a/include/asm-x86/processor.h
+++ b/include/asm-x86/processor.h
@@ -561,41 +561,6 @@ static inline void clear_in_cr4(unsigned long mask)
 	write_cr4(cr4);
 }
 
-struct microcode_header {
-	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 {
-	struct microcode_header	hdr;
-	unsigned int		bits[0];
-};
-
-typedef struct microcode	microcode_t;
-typedef struct microcode_header	microcode_header_t;
-
-/* 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];
-};
-
 typedef struct {
 	unsigned long		seg;
 } mm_segment_t;
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 2/9] [PATCH 2/9] x86: Typedef removal.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
  2008-07-25 16:17 ` [patch 1/9] [PATCH 1/9] x86: Moved Intel microcode patch loader declarations to seperate header file Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 3/9] [PATCH 3/9] x86: Moved per CPU microcode structure declaration to header file Peter Oruba
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0002-x86-Typedef-removal.patch --]
[-- Type: text/plain, Size: 4097 bytes --]

Removed typedefs. No functional changes to the code.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/kernel/microcode.c |   24 ++++++++++++------------
 include/asm-x86/microcode.h |    3 ---
 2 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 230ca7e..406261a 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -102,17 +102,17 @@ MODULE_LICENSE("GPL");
 #define MICROCODE_VERSION 	"1.14a"
 
 #define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
-#define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
+#define MC_HEADER_SIZE		(sizeof (struct microcode_header))  	  /* 48 bytes */
 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
 #define EXT_HEADER_SIZE		(sizeof (struct extended_sigtable)) /* 20 bytes */
 #define EXT_SIGNATURE_SIZE	(sizeof (struct extended_signature)) /* 12 bytes */
 #define DWSIZE			(sizeof (u32))
 #define get_totalsize(mc) \
-	(((microcode_t *)mc)->hdr.totalsize ? \
-	 ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
+	(((struct microcode *)mc)->hdr.totalsize ? \
+	 ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
 #define get_datasize(mc) \
-	(((microcode_t *)mc)->hdr.datasize ? \
-	 ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
+	(((struct microcode *)mc)->hdr.datasize ? \
+	 ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
 
 #define sigmatch(s1, s2, p1, p2) \
 	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
@@ -130,7 +130,7 @@ static struct ucode_cpu_info {
 	unsigned int sig;
 	unsigned int pf;
 	unsigned int rev;
-	microcode_t *mc;
+	struct microcode *mc;
 } ucode_cpu_info[NR_CPUS];
 
 static void collect_cpu_info(int cpu_num)
@@ -171,7 +171,7 @@ static void collect_cpu_info(int cpu_num)
 }
 
 static inline int microcode_update_match(int cpu_num,
-	microcode_header_t *mc_header, int sig, int pf)
+	struct microcode_header *mc_header, int sig, int pf)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
@@ -183,7 +183,7 @@ static inline int microcode_update_match(int cpu_num,
 
 static int microcode_sanity_check(void *mc)
 {
-	microcode_header_t *mc_header = mc;
+	struct microcode_header *mc_header = mc;
 	struct extended_sigtable *ext_header = NULL;
 	struct extended_signature *ext_sig;
 	unsigned long total_size, data_size, ext_table_size;
@@ -268,7 +268,7 @@ static int microcode_sanity_check(void *mc)
 static int get_maching_microcode(void *mc, int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	microcode_header_t *mc_header = mc;
+	struct microcode_header *mc_header = mc;
 	struct extended_sigtable *ext_header;
 	unsigned long total_size = get_totalsize(mc_header);
 	int ext_sigcount, i;
@@ -355,7 +355,7 @@ static unsigned int user_buffer_size;	/* it's size */
 
 static long get_next_ucode(void **mc, long offset)
 {
-	microcode_header_t mc_header;
+	struct microcode_header mc_header;
 	unsigned long total_size;
 
 	/* No more data */
@@ -495,13 +495,13 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
 static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
 	unsigned long size, long offset)
 {
-	microcode_header_t *mc_header;
+	struct microcode_header *mc_header;
 	unsigned long total_size;
 
 	/* No more data */
 	if (offset >= size)
 		return 0;
-	mc_header = (microcode_header_t *)(buf + offset);
+	mc_header = (struct microcode_header *)(buf + offset);
 	total_size = get_totalsize(mc_header);
 
 	if (offset + total_size > size) {
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index 5a05568..1519ef0 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -16,9 +16,6 @@ struct microcode {
 	unsigned int            bits[0];
 };
 
-typedef struct microcode          microcode_t;
-typedef struct microcode_header   microcode_header_t;
-
 /* microcode format is extended from prescott processors */
 struct extended_signature {
 	unsigned int            sig;
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 3/9] [PATCH 3/9] x86: Moved per CPU microcode structure declaration to header file.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
  2008-07-25 16:17 ` [patch 1/9] [PATCH 1/9] x86: Moved Intel microcode patch loader declarations to seperate header file Peter Oruba
  2008-07-25 16:17 ` [patch 2/9] [PATCH 2/9] x86: Typedef removal Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 4/9] [PATCH 4/9] x86: Code split to two parts Peter Oruba
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0003-x86-Moved-per-CPU-microcode-structure-declaration-t.patch --]
[-- Type: text/plain, Size: 1348 bytes --]

This structure will be later used by other modules as well and
needs therfore to be moved out to a header file.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/kernel/microcode.c |    8 +-------
 include/asm-x86/microcode.h |    8 ++++++++
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 406261a..d3bc0e8 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -125,13 +125,7 @@ static DEFINE_SPINLOCK(microcode_update_lock);
 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
 static DEFINE_MUTEX(microcode_mutex);
 
-static struct ucode_cpu_info {
-	int valid;
-	unsigned int sig;
-	unsigned int pf;
-	unsigned int rev;
-	struct microcode *mc;
-} ucode_cpu_info[NR_CPUS];
+static struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
 
 static void collect_cpu_info(int cpu_num)
 {
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index 1519ef0..d34a1fc 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -29,3 +29,11 @@ struct extended_sigtable {
 	unsigned int            reserved[3];
 	struct extended_signature sigs[0];
 };
+
+struct ucode_cpu_info {
+	int valid;
+	unsigned int sig;
+	unsigned int pf;
+	unsigned int rev;
+	struct microcode *mc;
+};
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 4/9] [PATCH 4/9] x86: Code split to two parts.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (2 preceding siblings ...)
  2008-07-25 16:17 ` [patch 3/9] [PATCH 3/9] x86: Moved per CPU microcode structure declaration to header file Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 5/9] [PATCH 5/9] x86: Structure declaration renaming Peter Oruba
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0004-x86-Code-split-to-two-parts.patch --]
[-- Type: text/plain, Size: 31077 bytes --]

Split off existing code into two seperate files. One file holds general
code, the other file vendor specific parts. No functional changes, only
refactoring. Temporarily Introduced a new module name 'ucode' for result,
due to already taken name 'microcode'.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/kernel/Makefile          |    3 +-
 arch/x86/kernel/microcode.c       |  421 +-----------------------------
 arch/x86/kernel/microcode_intel.c |  513 +++++++++++++++++++++++++++++++++++++
 3 files changed, 530 insertions(+), 407 deletions(-)
 create mode 100644 arch/x86/kernel/microcode_intel.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3db651f..abb32ae 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -51,7 +51,8 @@ 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)		+= ucode.o
+ucode-objs                      := microcode.o microcode_intel.o
 obj-$(CONFIG_PCI)		+= early-quirks.o
 apm-y				:= apm_32.o
 obj-$(CONFIG_APM)		+= apm.o
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index d3bc0e8..72b899c 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -95,286 +95,29 @@
 #include <asm/processor.h>
 #include <asm/microcode.h>
 
-MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
+MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_LICENSE("GPL");
 
 #define MICROCODE_VERSION 	"1.14a"
 
-#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
-#define MC_HEADER_SIZE		(sizeof (struct microcode_header))  	  /* 48 bytes */
-#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
-#define EXT_HEADER_SIZE		(sizeof (struct extended_sigtable)) /* 20 bytes */
-#define EXT_SIGNATURE_SIZE	(sizeof (struct extended_signature)) /* 12 bytes */
-#define DWSIZE			(sizeof (u32))
-#define get_totalsize(mc) \
-	(((struct microcode *)mc)->hdr.totalsize ? \
-	 ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
-#define get_datasize(mc) \
-	(((struct microcode *)mc)->hdr.datasize ? \
-	 ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
-
-#define sigmatch(s1, s2, p1, p2) \
-	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
-
-#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
-
-/* serialize access to the physical write to MSR 0x79 */
-static DEFINE_SPINLOCK(microcode_update_lock);
-
 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
-static DEFINE_MUTEX(microcode_mutex);
-
-static struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
-
-static void collect_cpu_info(int cpu_num)
-{
-	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-	unsigned int val[2];
-
-	/* We should bind the task to the CPU */
-	BUG_ON(raw_smp_processor_id() != cpu_num);
-	uci->pf = uci->rev = 0;
-	uci->mc = NULL;
-	uci->valid = 1;
-
-	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
-	    	cpu_has(c, X86_FEATURE_IA64)) {
-		printk(KERN_ERR "microcode: CPU%d not a capable Intel "
-			"processor\n", cpu_num);
-		uci->valid = 0;
-		return;
-	}
-
-	uci->sig = cpuid_eax(0x00000001);
-
-	if ((c->x86_model >= 5) || (c->x86 > 6)) {
-		/* get processor flags from MSR 0x17 */
-		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		uci->pf = 1 << ((val[1] >> 18) & 7);
-	}
-
-	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-	/* see notes above for revision 1.07.  Apparent chip bug */
-	sync_core();
-	/* get the current revision from MSR 0x8B */
-	rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
-	pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
-			uci->sig, uci->pf, uci->rev);
-}
-
-static inline int microcode_update_match(int cpu_num,
-	struct microcode_header *mc_header, int sig, int pf)
-{
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-	if (!sigmatch(sig, uci->sig, pf, uci->pf)
-		|| mc_header->rev <= uci->rev)
-		return 0;
-	return 1;
-}
-
-static int microcode_sanity_check(void *mc)
-{
-	struct microcode_header *mc_header = mc;
-	struct extended_sigtable *ext_header = NULL;
-	struct extended_signature *ext_sig;
-	unsigned long total_size, data_size, ext_table_size;
-	int sum, orig_sum, ext_sigcount = 0, i;
-
-	total_size = get_totalsize(mc_header);
-	data_size = get_datasize(mc_header);
-	if (data_size + MC_HEADER_SIZE > total_size) {
-		printk(KERN_ERR "microcode: error! "
-			"Bad data size in microcode data file\n");
-		return -EINVAL;
-	}
+DEFINE_MUTEX(microcode_mutex);
 
-	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
-		printk(KERN_ERR "microcode: error! "
-			"Unknown microcode update format\n");
-		return -EINVAL;
-	}
-	ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-	if (ext_table_size) {
-		if ((ext_table_size < EXT_HEADER_SIZE)
-		 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
-			printk(KERN_ERR "microcode: error! "
-				"Small exttable size in microcode data file\n");
-			return -EINVAL;
-		}
-		ext_header = mc + MC_HEADER_SIZE + data_size;
-		if (ext_table_size != exttable_size(ext_header)) {
-			printk(KERN_ERR "microcode: error! "
-				"Bad exttable size in microcode data file\n");
-			return -EFAULT;
-		}
-		ext_sigcount = ext_header->count;
-	}
+struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
 
-	/* check extended table checksum */
-	if (ext_table_size) {
-		int ext_table_sum = 0;
-		int *ext_tablep = (int *)ext_header;
-
-		i = ext_table_size / DWSIZE;
-		while (i--)
-			ext_table_sum += ext_tablep[i];
-		if (ext_table_sum) {
-			printk(KERN_WARNING "microcode: aborting, "
-				"bad extended signature table checksum\n");
-			return -EINVAL;
-		}
-	}
-
-	/* calculate the checksum */
-	orig_sum = 0;
-	i = (MC_HEADER_SIZE + data_size) / DWSIZE;
-	while (i--)
-		orig_sum += ((int *)mc)[i];
-	if (orig_sum) {
-		printk(KERN_ERR "microcode: aborting, bad checksum\n");
-		return -EINVAL;
-	}
-	if (!ext_table_size)
-		return 0;
-	/* check extended signature checksum */
-	for (i = 0; i < ext_sigcount; i++) {
-		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
-			  EXT_SIGNATURE_SIZE * i;
-		sum = orig_sum
-			- (mc_header->sig + mc_header->pf + mc_header->cksum)
-			+ (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
-		if (sum) {
-			printk(KERN_ERR "microcode: aborting, bad checksum\n");
-			return -EINVAL;
-		}
-	}
-	return 0;
-}
-
-/*
- * return 0 - no update found
- * return 1 - found update
- * return < 0 - error
- */
-static int get_maching_microcode(void *mc, int cpu)
-{
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	struct microcode_header *mc_header = mc;
-	struct extended_sigtable *ext_header;
-	unsigned long total_size = get_totalsize(mc_header);
-	int ext_sigcount, i;
-	struct extended_signature *ext_sig;
-	void *new_mc;
-
-	if (microcode_update_match(cpu, mc_header,
-			mc_header->sig, mc_header->pf))
-		goto find;
-
-	if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
-		return 0;
-
-	ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
-	ext_sigcount = ext_header->count;
-	ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
-	for (i = 0; i < ext_sigcount; i++) {
-		if (microcode_update_match(cpu, mc_header,
-				ext_sig->sig, ext_sig->pf))
-			goto find;
-		ext_sig++;
-	}
-	return 0;
-find:
-	pr_debug("microcode: CPU%d found a matching microcode update with"
-		" version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
-	new_mc = vmalloc(total_size);
-	if (!new_mc) {
-		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
-		return -ENOMEM;
-	}
-
-	/* free previous update file */
-	vfree(uci->mc);
-
-	memcpy(new_mc, mc, total_size);
-	uci->mc = new_mc;
-	return 1;
-}
-
-static void apply_microcode(int cpu)
-{
-	unsigned long flags;
-	unsigned int val[2];
-	int cpu_num = raw_smp_processor_id();
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-	/* We should bind the task to the CPU */
-	BUG_ON(cpu_num != cpu);
-
-	if (uci->mc == NULL)
-		return;
-
-	/* serialize access to the physical write to MSR 0x79 */
-	spin_lock_irqsave(&microcode_update_lock, flags);
-
-	/* write microcode via MSR 0x79 */
-	wrmsr(MSR_IA32_UCODE_WRITE,
-		(unsigned long) uci->mc->bits,
-		(unsigned long) uci->mc->bits >> 16 >> 16);
-	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-
-	/* see notes above for revision 1.07.  Apparent chip bug */
-	sync_core();
-
-	/* get the current revision from MSR 0x8B */
-	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-
-	spin_unlock_irqrestore(&microcode_update_lock, flags);
-	if (val[1] != uci->mc->hdr.rev) {
-		printk(KERN_ERR "microcode: CPU%d update from revision "
-			"0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
-		return;
-	}
-	printk(KERN_INFO "microcode: CPU%d updated from revision "
-	       "0x%x to 0x%x, date = %08x \n",
-	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
-	uci->rev = val[1];
-}
+extern long get_next_ucode(void **mc, long offset);
+extern int microcode_sanity_check(void *mc);
+extern int get_matching_microcode(void *mc, int cpu);
+extern void collect_cpu_info(int cpu_num);
+extern int cpu_request_microcode(int cpu);
+extern void microcode_fini_cpu(int cpu);
+extern void apply_microcode(int cpu);
+extern int apply_microcode_check_cpu(int cpu);
 
 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
-static void __user *user_buffer;	/* user area microcode data buffer */
-static unsigned int user_buffer_size;	/* it's size */
-
-static long get_next_ucode(void **mc, long offset)
-{
-	struct microcode_header mc_header;
-	unsigned long total_size;
-
-	/* No more data */
-	if (offset >= user_buffer_size)
-		return 0;
-	if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
-		printk(KERN_ERR "microcode: error! Can not read user data\n");
-		return -EFAULT;
-	}
-	total_size = get_totalsize(&mc_header);
-	if (offset + total_size > user_buffer_size) {
-		printk(KERN_ERR "microcode: error! Bad total size in microcode "
-				"data file\n");
-		return -EINVAL;
-	}
-	*mc = vmalloc(total_size);
-	if (!*mc)
-		return -ENOMEM;
-	if (copy_from_user(*mc, user_buffer + offset, total_size)) {
-		printk(KERN_ERR "microcode: error! Can not read user data\n");
-		vfree(*mc);
-		return -EFAULT;
-	}
-	return offset + total_size;
-}
+void __user *user_buffer;	/* user area microcode data buffer */
+unsigned int user_buffer_size;	/* it's size */
 
 static int do_microcode_update (void)
 {
@@ -400,7 +143,7 @@ static int do_microcode_update (void)
 			if (!uci->valid)
 				continue;
 			set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-			error = get_maching_microcode(new_mc, cpu);
+			error = get_matching_microcode(new_mc, cpu);
 			if (error < 0)
 				goto out;
 			if (error == 1)
@@ -486,131 +229,8 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
 #define microcode_dev_exit() do { } while(0)
 #endif
 
-static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
-	unsigned long size, long offset)
-{
-	struct microcode_header *mc_header;
-	unsigned long total_size;
-
-	/* No more data */
-	if (offset >= size)
-		return 0;
-	mc_header = (struct microcode_header *)(buf + offset);
-	total_size = get_totalsize(mc_header);
-
-	if (offset + total_size > size) {
-		printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-		return -EINVAL;
-	}
-
-	*mc = vmalloc(total_size);
-	if (!*mc) {
-		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
-		return -ENOMEM;
-	}
-	memcpy(*mc, buf + offset, total_size);
-	return offset + total_size;
-}
-
 /* fake device for request_firmware */
-static struct platform_device *microcode_pdev;
-
-static int cpu_request_microcode(int cpu)
-{
-	char name[30];
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	const struct firmware *firmware;
-	const u8 *buf;
-	unsigned long size;
-	long offset = 0;
-	int error;
-	void *mc;
-
-	/* We should bind the task to the CPU */
-	BUG_ON(cpu != raw_smp_processor_id());
-	sprintf(name,"intel-ucode/%02x-%02x-%02x",
-		c->x86, c->x86_model, c->x86_mask);
-	error = request_firmware(&firmware, name, &microcode_pdev->dev);
-	if (error) {
-		pr_debug("microcode: data file %s load failed\n", name);
-		return error;
-	}
-	buf = firmware->data;
-	size = firmware->size;
-	while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
-			> 0) {
-		error = microcode_sanity_check(mc);
-		if (error)
-			break;
-		error = get_maching_microcode(mc, cpu);
-		if (error < 0)
-			break;
-		/*
-		 * It's possible the data file has multiple matching ucode,
-		 * lets keep searching till the latest version
-		 */
-		if (error == 1) {
-			apply_microcode(cpu);
-			error = 0;
-		}
-		vfree(mc);
-	}
-	if (offset > 0)
-		vfree(mc);
-	if (offset < 0)
-		error = offset;
-	release_firmware(firmware);
-
-	return error;
-}
-
-static int apply_microcode_check_cpu(int cpu)
-{
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	cpumask_t old;
-	unsigned int val[2];
-	int err = 0;
-
-	/* Check if the microcode is available */
-	if (!uci->mc)
-		return 0;
-
-	old = current->cpus_allowed;
-	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-
-	/* Check if the microcode we have in memory matches the CPU */
-	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
-	    cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
-		err = -EINVAL;
-
-	if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
-		/* get processor flags from MSR 0x17 */
-		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-		if (uci->pf != (1 << ((val[1] >> 18) & 7)))
-			err = -EINVAL;
-	}
-
-	if (!err) {
-		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-		/* see notes above for revision 1.07.  Apparent chip bug */
-		sync_core();
-		/* get the current revision from MSR 0x8B */
-		rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-		if (uci->rev != val[1])
-			err = -EINVAL;
-	}
-
-	if (!err)
-		apply_microcode(cpu);
-	else
-		printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
-			" sig=0x%x, pf=0x%x, rev=0x%x\n",
-			cpu, uci->sig, uci->pf, uci->rev);
-
-	set_cpus_allowed_ptr(current, &old);
-	return err;
-}
+struct platform_device *microcode_pdev;
 
 static void microcode_init_cpu(int cpu, int resume)
 {
@@ -628,17 +248,6 @@ static void microcode_init_cpu(int cpu, int resume)
 	set_cpus_allowed_ptr(current, &old);
 }
 
-static void microcode_fini_cpu(int cpu)
-{
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-	mutex_lock(&microcode_mutex);
-	uci->valid = 0;
-	vfree(uci->mc);
-	uci->mc = NULL;
-	mutex_unlock(&microcode_mutex);
-}
-
 static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
new file mode 100644
index 0000000..a30c799
--- /dev/null
+++ b/arch/x86/kernel/microcode_intel.c
@@ -0,0 +1,513 @@
+/*
+ *	Intel CPU Microcode Update Driver for Linux
+ *
+ *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ *		      2006	Shaohua Li <shaohua.li@intel.com>
+ *
+ *	This driver allows to upgrade microcode on Intel processors
+ *	belonging to IA-32 family - PentiumPro, Pentium II,
+ *	Pentium III, Xeon, Pentium 4, etc.
+ *
+ *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ *	Software Developer's Manual
+ *	Order Number 253668 or free download from:
+ *
+ *	http://developer.intel.com/design/pentium4/manuals/253668.htm
+ *
+ *	For more information, go to http://www.urbanmyth.org/microcode
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	1.0	16 Feb 2000, Tigran Aivazian <tigran@sco.com>
+ *		Initial release.
+ *	1.01	18 Feb 2000, Tigran Aivazian <tigran@sco.com>
+ *		Added read() support + cleanups.
+ *	1.02	21 Feb 2000, Tigran Aivazian <tigran@sco.com>
+ *		Added 'device trimming' support. open(O_WRONLY) zeroes
+ *		and frees the saved copy of applied microcode.
+ *	1.03	29 Feb 2000, Tigran Aivazian <tigran@sco.com>
+ *		Made to use devfs (/dev/cpu/microcode) + cleanups.
+ *	1.04	06 Jun 2000, Simon Trimmer <simon@veritas.com>
+ *		Added misc device support (now uses both devfs and misc).
+ *		Added MICROCODE_IOCFREE ioctl to clear memory.
+ *	1.05	09 Jun 2000, Simon Trimmer <simon@veritas.com>
+ *		Messages for error cases (non Intel & no suitable microcode).
+ *	1.06	03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
+ *		Removed ->release(). Removed exclusive open and status bitmap.
+ *		Added microcode_rwsem to serialize read()/write()/ioctl().
+ *		Removed global kernel lock usage.
+ *	1.07	07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
+ *		Write 0 to 0x8B msr and then cpuid before reading revision,
+ *		so that it works even if there were no update done by the
+ *		BIOS. Otherwise, reading from 0x8B gives junk (which happened
+ *		to be 0 on my machine which is why it worked even when I
+ *		disabled update by the BIOS)
+ *		Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
+ *	1.08	11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
+ *			     Tigran Aivazian <tigran@veritas.com>
+ *		Intel Pentium 4 processor support and bugfixes.
+ *	1.09	30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
+ *		Bugfix for HT (Hyper-Threading) enabled processors
+ *		whereby processor resources are shared by all logical processors
+ *		in a single CPU package.
+ *	1.10	28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
+ *		Tigran Aivazian <tigran@veritas.com>,
+ *		Serialize updates as required on HT processors due to speculative
+ *		nature of implementation.
+ *	1.11	22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
+ *		Fix the panic when writing zero-length microcode chunk.
+ *	1.12	29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>,
+ *		Jun Nakajima <jun.nakajima@intel.com>
+ *		Support for the microcode updates in the new format.
+ *	1.13	10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
+ *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
+ *		because we no longer hold a copy of applied microcode
+ *		in kernel memory.
+ *	1.14	25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
+ *		Fix sigmatch() macro to handle old CPUs with pf == 0.
+ *		Thanks to Stuart Swales for pointing out this bug.
+ */
+
+//#define DEBUG /* pr_debug */
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/microcode.h>
+
+MODULE_DESCRIPTION("Microcode Update Driver");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+MODULE_LICENSE("GPL");
+
+#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
+#define MC_HEADER_SIZE		(sizeof(struct microcode_header))  	  /* 48 bytes */
+#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
+#define EXT_HEADER_SIZE		(sizeof(struct extended_sigtable)) /* 20 bytes */
+#define EXT_SIGNATURE_SIZE	(sizeof(struct extended_signature)) /* 12 bytes */
+#define DWSIZE			(sizeof(u32))
+#define get_totalsize(mc) \
+	(((struct microcode *)mc)->hdr.totalsize ? \
+	 ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
+#define get_datasize(mc) \
+	(((struct microcode *)mc)->hdr.datasize ? \
+	 ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
+
+#define sigmatch(s1, s2, p1, p2) \
+	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
+
+#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
+
+/* serialize access to the physical write to MSR 0x79 */
+static DEFINE_SPINLOCK(microcode_update_lock);
+
+/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+extern struct mutex microcode_mutex;
+
+extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
+
+void collect_cpu_info(int cpu_num)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+	unsigned int val[2];
+
+	/* We should bind the task to the CPU */
+	BUG_ON(raw_smp_processor_id() != cpu_num);
+	uci->pf = uci->rev = 0;
+	uci->mc = NULL;
+	uci->valid = 1;
+
+	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+	    cpu_has(c, X86_FEATURE_IA64)) {
+		printk(KERN_ERR "microcode: CPU%d not a capable Intel "
+			"processor\n", cpu_num);
+		uci->valid = 0;
+		return;
+	}
+
+	uci->sig = cpuid_eax(0x00000001);
+
+	if ((c->x86_model >= 5) || (c->x86 > 6)) {
+		/* get processor flags from MSR 0x17 */
+		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		uci->pf = 1 << ((val[1] >> 18) & 7);
+	}
+
+	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+	/* see notes above for revision 1.07.  Apparent chip bug */
+	sync_core();
+	/* get the current revision from MSR 0x8B */
+	rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
+	pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
+			uci->sig, uci->pf, uci->rev);
+}
+
+static inline int microcode_update_match(int cpu_num,
+	struct microcode_header *mc_header, int sig, int pf)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+	if (!sigmatch(sig, uci->sig, pf, uci->pf)
+		|| mc_header->rev <= uci->rev)
+		return 0;
+	return 1;
+}
+
+int microcode_sanity_check(void *mc)
+{
+	struct microcode_header *mc_header = mc;
+	struct extended_sigtable *ext_header = NULL;
+	struct extended_signature *ext_sig;
+	unsigned long total_size, data_size, ext_table_size;
+	int sum, orig_sum, ext_sigcount = 0, i;
+
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
+	if (data_size + MC_HEADER_SIZE > total_size) {
+		printk(KERN_ERR "microcode: error! "
+			"Bad data size in microcode data file\n");
+		return -EINVAL;
+	}
+
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		printk(KERN_ERR "microcode: error! "
+			"Unknown microcode update format\n");
+		return -EINVAL;
+	}
+	ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+	if (ext_table_size) {
+		if ((ext_table_size < EXT_HEADER_SIZE)
+		 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+			printk(KERN_ERR "microcode: error! "
+				"Small exttable size in microcode data file\n");
+			return -EINVAL;
+		}
+		ext_header = mc + MC_HEADER_SIZE + data_size;
+		if (ext_table_size != exttable_size(ext_header)) {
+			printk(KERN_ERR "microcode: error! "
+				"Bad exttable size in microcode data file\n");
+			return -EFAULT;
+		}
+		ext_sigcount = ext_header->count;
+	}
+
+	/* check extended table checksum */
+	if (ext_table_size) {
+		int ext_table_sum = 0;
+		int *ext_tablep = (int *)ext_header;
+
+		i = ext_table_size / DWSIZE;
+		while (i--)
+			ext_table_sum += ext_tablep[i];
+		if (ext_table_sum) {
+			printk(KERN_WARNING "microcode: aborting, "
+				"bad extended signature table checksum\n");
+			return -EINVAL;
+		}
+	}
+
+	/* calculate the checksum */
+	orig_sum = 0;
+	i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+	while (i--)
+		orig_sum += ((int *)mc)[i];
+	if (orig_sum) {
+		printk(KERN_ERR "microcode: aborting, bad checksum\n");
+		return -EINVAL;
+	}
+	if (!ext_table_size)
+		return 0;
+	/* check extended signature checksum */
+	for (i = 0; i < ext_sigcount; i++) {
+		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+			  EXT_SIGNATURE_SIZE * i;
+		sum = orig_sum
+			- (mc_header->sig + mc_header->pf + mc_header->cksum)
+			+ (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+		if (sum) {
+			printk(KERN_ERR "microcode: aborting, bad checksum\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+/*
+ * return 0 - no update found
+ * return 1 - found update
+ * return < 0 - error
+ */
+int get_matching_microcode(void *mc, int cpu)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	struct microcode_header *mc_header = mc;
+	struct extended_sigtable *ext_header;
+	unsigned long total_size = get_totalsize(mc_header);
+	int ext_sigcount, i;
+	struct extended_signature *ext_sig;
+	void *new_mc;
+
+	if (microcode_update_match(cpu, mc_header,
+			mc_header->sig, mc_header->pf))
+		goto find;
+
+	if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
+		return 0;
+
+	ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
+	ext_sigcount = ext_header->count;
+	ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
+	for (i = 0; i < ext_sigcount; i++) {
+		if (microcode_update_match(cpu, mc_header,
+				ext_sig->sig, ext_sig->pf))
+			goto find;
+		ext_sig++;
+	}
+	return 0;
+find:
+	pr_debug("microcode: CPU%d found a matching microcode update with"
+		 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev);
+	new_mc = vmalloc(total_size);
+	if (!new_mc) {
+		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+		return -ENOMEM;
+	}
+
+	/* free previous update file */
+	vfree(uci->mc);
+
+	memcpy(new_mc, mc, total_size);
+	uci->mc = new_mc;
+	return 1;
+}
+
+void apply_microcode(int cpu)
+{
+	unsigned long flags;
+	unsigned int val[2];
+	int cpu_num = raw_smp_processor_id();
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+	/* We should bind the task to the CPU */
+	BUG_ON(cpu_num != cpu);
+
+	if (uci->mc == NULL)
+		return;
+
+	/* serialize access to the physical write to MSR 0x79 */
+	spin_lock_irqsave(&microcode_update_lock, flags);
+
+	/* write microcode via MSR 0x79 */
+	wrmsr(MSR_IA32_UCODE_WRITE,
+		(unsigned long) uci->mc->bits,
+		(unsigned long) uci->mc->bits >> 16 >> 16);
+	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+
+	/* see notes above for revision 1.07.  Apparent chip bug */
+	sync_core();
+
+	/* get the current revision from MSR 0x8B */
+	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+	spin_unlock_irqrestore(&microcode_update_lock, flags);
+	if (val[1] != uci->mc->hdr.rev) {
+		printk(KERN_ERR "microcode: CPU%d update from revision "
+			"0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
+		return;
+	}
+	printk(KERN_INFO "microcode: CPU%d updated from revision "
+	       "0x%x to 0x%x, date = %08x \n",
+	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
+	uci->rev = val[1];
+}
+
+#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+extern void __user *user_buffer;        /* user area microcode data buffer */
+extern unsigned int user_buffer_size;   /* it's size */
+
+long get_next_ucode(void **mc, long offset)
+{
+	struct microcode_header mc_header;
+	unsigned long total_size;
+
+	/* No more data */
+	if (offset >= user_buffer_size)
+		return 0;
+	if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
+		printk(KERN_ERR "microcode: error! Can not read user data\n");
+		return -EFAULT;
+	}
+	total_size = get_totalsize(&mc_header);
+	if (offset + total_size > user_buffer_size) {
+		printk(KERN_ERR "microcode: error! Bad total size in microcode "
+				"data file\n");
+		return -EINVAL;
+	}
+	*mc = vmalloc(total_size);
+	if (!*mc)
+		return -ENOMEM;
+	if (copy_from_user(*mc, user_buffer + offset, total_size)) {
+		printk(KERN_ERR "microcode: error! Can not read user data\n");
+		vfree(*mc);
+		return -EFAULT;
+	}
+	return offset + total_size;
+}
+#endif
+
+static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
+	unsigned long size, long offset)
+{
+	struct microcode_header *mc_header;
+	unsigned long total_size;
+
+	/* No more data */
+	if (offset >= size)
+		return 0;
+	mc_header = (struct microcode_header *)(buf + offset);
+	total_size = get_totalsize(mc_header);
+
+	if (offset + total_size > size) {
+		printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+		return -EINVAL;
+	}
+
+	*mc = vmalloc(total_size);
+	if (!*mc) {
+		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+		return -ENOMEM;
+	}
+	memcpy(*mc, buf + offset, total_size);
+	return offset + total_size;
+}
+
+/* fake device for request_firmware */
+extern struct platform_device *microcode_pdev;
+
+int cpu_request_microcode(int cpu)
+{
+	char name[30];
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	const struct firmware *firmware;
+	const u8 *buf;
+	unsigned long size;
+	long offset = 0;
+	int error;
+	void *mc;
+
+	/* We should bind the task to the CPU */
+	BUG_ON(cpu != raw_smp_processor_id());
+	sprintf(name, "intel-ucode/%02x-%02x-%02x",
+		c->x86, c->x86_model, c->x86_mask);
+	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+	if (error) {
+		pr_debug("microcode: data file %s load failed\n", name);
+		return error;
+	}
+	buf = firmware->data;
+	size = firmware->size;
+	while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
+			> 0) {
+		error = microcode_sanity_check(mc);
+		if (error)
+			break;
+		error = get_matching_microcode(mc, cpu);
+		if (error < 0)
+			break;
+		/*
+		 * It's possible the data file has multiple matching ucode,
+		 * lets keep searching till the latest version
+		 */
+		if (error == 1) {
+			apply_microcode(cpu);
+			error = 0;
+		}
+		vfree(mc);
+	}
+	if (offset > 0)
+		vfree(mc);
+	if (offset < 0)
+		error = offset;
+	release_firmware(firmware);
+
+	return error;
+}
+
+int apply_microcode_check_cpu(int cpu)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	cpumask_t old;
+	unsigned int val[2];
+	int err = 0;
+
+	/* Check if the microcode is available */
+	if (!uci->mc)
+		return 0;
+
+	old = current->cpus_allowed;
+	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
+
+	/* Check if the microcode we have in memory matches the CPU */
+	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+	    cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
+		err = -EINVAL;
+
+	if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
+		/* get processor flags from MSR 0x17 */
+		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+		if (uci->pf != (1 << ((val[1] >> 18) & 7)))
+			err = -EINVAL;
+	}
+
+	if (!err) {
+		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+		/* see notes above for revision 1.07.  Apparent chip bug */
+		sync_core();
+		/* get the current revision from MSR 0x8B */
+		rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+		if (uci->rev != val[1])
+			err = -EINVAL;
+	}
+
+	if (!err)
+		apply_microcode(cpu);
+	else
+		printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
+			" sig=0x%x, pf=0x%x, rev=0x%x\n",
+			cpu, uci->sig, uci->pf, uci->rev);
+
+	set_cpus_allowed_ptr(current, &old);
+	return err;
+}
+
+void microcode_fini_cpu(int cpu)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+	mutex_lock(&microcode_mutex);
+	uci->valid = 0;
+	kfree(uci->mc);
+	uci->mc = NULL;
+	mutex_unlock(&microcode_mutex);
+}
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 5/9] [PATCH 5/9] x86: Structure declaration renaming.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (3 preceding siblings ...)
  2008-07-25 16:17 ` [patch 4/9] [PATCH 4/9] x86: Code split to two parts Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 6/9] [PATCH 6/9] x86: Add AMD specific declarations Peter Oruba
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0005-x86-Structure-declaration-renaming.patch --]
[-- Type: text/plain, Size: 6644 bytes --]

Renamed common structures to vendor specific naming scheme
so other vendors will be able to use the same naming
convention.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>

Conflicts:
---
 arch/x86/kernel/microcode_intel.c |   46 +++++++++++++++++++-----------------
 include/asm-x86/microcode.h       |   10 +++++---
 2 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index a30c799..4754137 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -100,17 +100,19 @@ MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_LICENSE("GPL");
 
 #define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
-#define MC_HEADER_SIZE		(sizeof(struct microcode_header))  	  /* 48 bytes */
+#define MC_HEADER_SIZE		(sizeof(struct microcode_header_intel)) /* 48 bytes */
 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
 #define EXT_HEADER_SIZE		(sizeof(struct extended_sigtable)) /* 20 bytes */
 #define EXT_SIGNATURE_SIZE	(sizeof(struct extended_signature)) /* 12 bytes */
 #define DWSIZE			(sizeof(u32))
 #define get_totalsize(mc) \
-	(((struct microcode *)mc)->hdr.totalsize ? \
-	 ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
+	(((struct microcode_intel *)mc)->hdr.totalsize ? \
+	 ((struct microcode_intel *)mc)->hdr.totalsize : \
+	 DEFAULT_UCODE_TOTALSIZE)
+
 #define get_datasize(mc) \
-	(((struct microcode *)mc)->hdr.datasize ? \
-	 ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
+	(((struct microcode_intel *)mc)->hdr.datasize ? \
+	 ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
 
 #define sigmatch(s1, s2, p1, p2) \
 	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
@@ -134,7 +136,7 @@ void collect_cpu_info(int cpu_num)
 	/* We should bind the task to the CPU */
 	BUG_ON(raw_smp_processor_id() != cpu_num);
 	uci->pf = uci->rev = 0;
-	uci->mc = NULL;
+	uci->mc.mc_intel = NULL;
 	uci->valid = 1;
 
 	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
@@ -163,7 +165,7 @@ void collect_cpu_info(int cpu_num)
 }
 
 static inline int microcode_update_match(int cpu_num,
-	struct microcode_header *mc_header, int sig, int pf)
+	struct microcode_header_intel *mc_header, int sig, int pf)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
@@ -175,7 +177,7 @@ static inline int microcode_update_match(int cpu_num,
 
 int microcode_sanity_check(void *mc)
 {
-	struct microcode_header *mc_header = mc;
+	struct microcode_header_intel *mc_header = mc;
 	struct extended_sigtable *ext_header = NULL;
 	struct extended_signature *ext_sig;
 	unsigned long total_size, data_size, ext_table_size;
@@ -260,7 +262,7 @@ int microcode_sanity_check(void *mc)
 int get_matching_microcode(void *mc, int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	struct microcode_header *mc_header = mc;
+	struct microcode_header_intel *mc_header = mc;
 	struct extended_sigtable *ext_header;
 	unsigned long total_size = get_totalsize(mc_header);
 	int ext_sigcount, i;
@@ -294,10 +296,10 @@ find:
 	}
 
 	/* free previous update file */
-	vfree(uci->mc);
+	vfree(uci->mc.mc_intel);
 
 	memcpy(new_mc, mc, total_size);
-	uci->mc = new_mc;
+	uci->mc.mc_intel = new_mc;
 	return 1;
 }
 
@@ -311,7 +313,7 @@ void apply_microcode(int cpu)
 	/* We should bind the task to the CPU */
 	BUG_ON(cpu_num != cpu);
 
-	if (uci->mc == NULL)
+	if (uci->mc.mc_intel == NULL)
 		return;
 
 	/* serialize access to the physical write to MSR 0x79 */
@@ -319,8 +321,8 @@ void apply_microcode(int cpu)
 
 	/* write microcode via MSR 0x79 */
 	wrmsr(MSR_IA32_UCODE_WRITE,
-		(unsigned long) uci->mc->bits,
-		(unsigned long) uci->mc->bits >> 16 >> 16);
+	      (unsigned long) uci->mc.mc_intel->bits,
+	      (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 
 	/* see notes above for revision 1.07.  Apparent chip bug */
@@ -330,14 +332,14 @@ 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->hdr.rev) {
+	if (val[1] != uci->mc.mc_intel->hdr.rev) {
 		printk(KERN_ERR "microcode: CPU%d update from revision "
 			"0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
 		return;
 	}
 	printk(KERN_INFO "microcode: CPU%d updated from revision "
 	       "0x%x to 0x%x, date = %08x \n",
-	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
+	       cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date);
 	uci->rev = val[1];
 }
 
@@ -347,7 +349,7 @@ extern unsigned int user_buffer_size;   /* it's size */
 
 long get_next_ucode(void **mc, long offset)
 {
-	struct microcode_header mc_header;
+	struct microcode_header_intel mc_header;
 	unsigned long total_size;
 
 	/* No more data */
@@ -378,13 +380,13 @@ long get_next_ucode(void **mc, long offset)
 static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
 	unsigned long size, long offset)
 {
-	struct microcode_header *mc_header;
+	struct microcode_header_intel *mc_header;
 	unsigned long total_size;
 
 	/* No more data */
 	if (offset >= size)
 		return 0;
-	mc_header = (struct microcode_header *)(buf + offset);
+	mc_header = (struct microcode_header_intel *)(buf + offset);
 	total_size = get_totalsize(mc_header);
 
 	if (offset + total_size > size) {
@@ -462,7 +464,7 @@ int apply_microcode_check_cpu(int cpu)
 	int err = 0;
 
 	/* Check if the microcode is available */
-	if (!uci->mc)
+	if (!uci->mc.mc_intel)
 		return 0;
 
 	old = current->cpus_allowed;
@@ -507,7 +509,7 @@ void microcode_fini_cpu(int cpu)
 
 	mutex_lock(&microcode_mutex);
 	uci->valid = 0;
-	kfree(uci->mc);
-	uci->mc = NULL;
+	kfree(uci->mc.mc_intel);
+	uci->mc.mc_intel = NULL;
 	mutex_unlock(&microcode_mutex);
 }
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index d34a1fc..ef77c6f 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -1,4 +1,4 @@
-struct microcode_header {
+struct microcode_header_intel {
 	unsigned int            hdrver;
 	unsigned int            rev;
 	unsigned int            date;
@@ -11,8 +11,8 @@ struct microcode_header {
 	unsigned int            reserved[3];
 };
 
-struct microcode {
-	struct microcode_header hdr;
+struct microcode_intel {
+	struct microcode_header_intel hdr;
 	unsigned int            bits[0];
 };
 
@@ -35,5 +35,7 @@ struct ucode_cpu_info {
 	unsigned int sig;
 	unsigned int pf;
 	unsigned int rev;
-	struct microcode *mc;
+	union {
+		struct microcode_intel *mc_intel;
+	} mc;
 };
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 6/9] [PATCH 6/9] x86: Add AMD specific declarations.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (4 preceding siblings ...)
  2008-07-25 16:17 ` [patch 5/9] [PATCH 5/9] x86: Structure declaration renaming Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 7/9] [PATCH 7/9] x86: First step of refactoring, introducing microcode_ops Peter Oruba
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0006-x86-Add-AMD-specific-declarations.patch --]
[-- Type: text/plain, Size: 1418 bytes --]

Added AMD specific declarations to header file.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 include/asm-x86/microcode.h |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index ef77c6f..4e94172 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -30,6 +30,35 @@ struct extended_sigtable {
 	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 ucode_cpu_info {
 	int valid;
 	unsigned int sig;
@@ -37,5 +66,6 @@ struct ucode_cpu_info {
 	unsigned int rev;
 	union {
 		struct microcode_intel *mc_intel;
+		struct microcode_amd *mc_amd;
 	} mc;
 };
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 7/9] [PATCH 7/9] x86: First step of refactoring, introducing microcode_ops.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (5 preceding siblings ...)
  2008-07-25 16:17 ` [patch 6/9] [PATCH 6/9] x86: Add AMD specific declarations Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-25 16:17 ` [patch 8/9] [PATCH 8/9] x86: Major refactoring Peter Oruba
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0007-x86-First-step-of-refactoring-introducing-microcod.patch --]
[-- Type: text/plain, Size: 1239 bytes --]

Refactoring with the goal of having one general module and separate
vendor specific modules that hook into the general one.

Microcode_ops is a function pointer structure in which vendor
specific modules will enter all functions that differ between
vendors and that need to be accessed from the general module.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 include/asm-x86/microcode.h |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
index 4e94172..9231c87 100644
--- a/include/asm-x86/microcode.h
+++ b/include/asm-x86/microcode.h
@@ -1,3 +1,16 @@
+struct microcode_ops {
+	long (*get_next_ucode)(void **mc, long offset);
+	long (*microcode_get_next_ucode)(void **mc, long offset);
+	int (*get_matching_microcode)(void *mc, int cpu);
+	int (*apply_microcode_check_cpu)(int cpu);
+	int (*microcode_sanity_check)(void *mc);
+	int (*cpu_request_microcode)(int cpu);
+	void (*collect_cpu_info)(int cpu_num);
+	void (*apply_microcode)(int cpu);
+	void (*microcode_fini_cpu)(int cpu);
+	void (*clear_patch)(void *data);
+};
+
 struct microcode_header_intel {
 	unsigned int            hdrver;
 	unsigned int            rev;
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 8/9] [PATCH 8/9] x86: Major refactoring.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (6 preceding siblings ...)
  2008-07-25 16:17 ` [patch 7/9] [PATCH 7/9] x86: First step of refactoring, introducing microcode_ops Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-26  9:11   ` Daniel K.
  2008-07-25 16:17 ` [patch 9/9] [PATCH 9/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0008-x86-Major-refactoring.patch --]
[-- Type: text/plain, Size: 13368 bytes --]

Refactored code by introducing a two-module solution. There is one
general module in which vendor specific modules can hook into.
However, that is exclusive, there is only one vendor specific module
allowed at a time. A CPU vendor check makes sure only the corect
module for the underlying system gets called. Functinally in terms
of patch loading itself there are no changes. This refactoring
provides a basis for future implementations of other vendors'
patch loaders.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/Kconfig                  |   24 +++++++++--
 arch/x86/kernel/Makefile          |    4 +-
 arch/x86/kernel/microcode.c       |   80 +++++++++++++++++++++---------------
 arch/x86/kernel/microcode_intel.c |   54 ++++++++++++++++++++-----
 4 files changed, 112 insertions(+), 50 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 03980cb..ece1e27 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -782,7 +782,7 @@ config X86_REBOOTFIXUPS
 	  Say N otherwise.
 
 config MICROCODE
-	tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
+	tristate "/dev/cpu/microcode - microcode support"
 	select FW_LOADER
 	---help---
 	  If you say Y here, you will be able to update the microcode on
@@ -791,14 +791,28 @@ config MICROCODE
 	  actual microcode binary data itself which is not shipped with the
 	  Linux kernel.
 
-	  For latest news and information on obtaining all the required
-	  ingredients for this driver, check:
-	  <http://www.urbanmyth.org/microcode/>.
+	  This option selects the general module only, you need to select
+	  at least one vendor specific module as well.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called microcode.
 
-config MICROCODE_OLD_INTERFACE
+config MICROCODE_INTEL
+       tristate "Intel microcode patch loading support"
+       depends on MICROCODE
+       select FW_LOADER
+       --help---
+         This options enables microcode patch loading support for Intel
+         processors.
+
+         For latest news and information on obtaining all the required
+         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_OLD_INTERFACE
 	def_bool y
 	depends on MICROCODE
 
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index abb32ae..f2f9f6d 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -51,8 +51,8 @@ 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)		+= ucode.o
-ucode-objs                      := microcode.o microcode_intel.o
+obj-$(CONFIG_MICROCODE)		+= microcode.o
+obj-$(CONFIG_MICROCODE_INTEL)	+= microcode_intel.o
 obj-$(CONFIG_PCI)		+= early-quirks.o
 apm-y				:= apm_32.o
 obj-$(CONFIG_APM)		+= apm.o
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 72b899c..f6414bc 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -99,25 +99,22 @@ MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_LICENSE("GPL");
 
-#define MICROCODE_VERSION 	"1.14a"
+#define MICROCODE_VERSION 	"2.00"
 
-/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
-DEFINE_MUTEX(microcode_mutex);
+struct microcode_ops *microcode_ops;
 
-struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
+/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+static DEFINE_MUTEX(microcode_mutex);
+EXPORT_SYMBOL_GPL(microcode_mutex);
 
-extern long get_next_ucode(void **mc, long offset);
-extern int microcode_sanity_check(void *mc);
-extern int get_matching_microcode(void *mc, int cpu);
-extern void collect_cpu_info(int cpu_num);
-extern int cpu_request_microcode(int cpu);
-extern void microcode_fini_cpu(int cpu);
-extern void apply_microcode(int cpu);
-extern int apply_microcode_check_cpu(int cpu);
+static struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
+EXPORT_SYMBOL_GPL(ucode_cpu_info);
 
 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
-void __user *user_buffer;	/* user area microcode data buffer */
-unsigned int user_buffer_size;	/* it's size */
+static void __user *user_buffer;	/* user area microcode data buffer */
+EXPORT_SYMBOL_GPL(user_buffer);
+static unsigned int user_buffer_size;	/* it's size */
+EXPORT_SYMBOL_GPL(user_buffer_size);
 
 static int do_microcode_update (void)
 {
@@ -129,8 +126,8 @@ static int do_microcode_update (void)
 
 	old = current->cpus_allowed;
 
-	while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
-		error = microcode_sanity_check(new_mc);
+	while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) {
+		error = microcode_ops->microcode_sanity_check(new_mc);
 		if (error)
 			goto out;
 		/*
@@ -143,11 +140,12 @@ static int do_microcode_update (void)
 			if (!uci->valid)
 				continue;
 			set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-			error = get_matching_microcode(new_mc, cpu);
+			error = microcode_ops->get_matching_microcode(new_mc,
+								      cpu);
 			if (error < 0)
 				goto out;
 			if (error == 1)
-				apply_microcode(cpu);
+				microcode_ops->apply_microcode(cpu);
 		}
 		vfree(new_mc);
 	}
@@ -230,7 +228,8 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
 #endif
 
 /* fake device for request_firmware */
-struct platform_device *microcode_pdev;
+static struct platform_device *microcode_pdev;
+EXPORT_SYMBOL_GPL(microcode_pdev);
 
 static void microcode_init_cpu(int cpu, int resume)
 {
@@ -241,9 +240,9 @@ static void microcode_init_cpu(int cpu, int resume)
 
 	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
 	mutex_lock(&microcode_mutex);
-	collect_cpu_info(cpu);
+	microcode_ops->collect_cpu_info(cpu);
 	if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
-		cpu_request_microcode(cpu);
+		microcode_ops->cpu_request_microcode(cpu);
 	mutex_unlock(&microcode_mutex);
 	set_cpus_allowed_ptr(current, &old);
 }
@@ -268,7 +267,7 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
 
 		mutex_lock(&microcode_mutex);
 		if (uci->valid)
-			err = cpu_request_microcode(cpu);
+			err = microcode_ops->cpu_request_microcode(cpu);
 		mutex_unlock(&microcode_mutex);
 		put_online_cpus();
 		set_cpus_allowed_ptr(current, &old);
@@ -341,7 +340,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
 		return 0;
 
 	pr_debug("microcode: CPU%d removed\n", cpu);
-	microcode_fini_cpu(cpu);
+	microcode_ops->microcode_fini_cpu(cpu);
 	sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
 	return 0;
 }
@@ -354,7 +353,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
 		return 0;
 	pr_debug("microcode: CPU%d resumed\n", cpu);
 	/* only CPU 0 will apply ucode here */
-	apply_microcode(0);
+	microcode_ops->apply_microcode(0);
 	return 0;
 }
 
@@ -374,7 +373,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 	switch (action) {
 	case CPU_UP_CANCELED_FROZEN:
 		/* The CPU refused to come up during a system resume */
-		microcode_fini_cpu(cpu);
+		microcode_ops->microcode_fini_cpu(cpu);
 		break;
 	case CPU_ONLINE:
 	case CPU_DOWN_FAILED:
@@ -382,9 +381,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 		break;
 	case CPU_ONLINE_FROZEN:
 		/* System-wide resume is in progress, try to apply microcode */
-		if (apply_microcode_check_cpu(cpu)) {
+		if (microcode_ops->apply_microcode_check_cpu(cpu)) {
 			/* The application of microcode failed */
-			microcode_fini_cpu(cpu);
+			microcode_ops->microcode_fini_cpu(cpu);
 			__mc_sysdev_add(sys_dev, 1);
 			break;
 		}
@@ -408,12 +407,17 @@ static struct notifier_block __refdata mc_cpu_notifier = {
 	.notifier_call = mc_cpu_callback,
 };
 
-static int __init microcode_init (void)
+static int microcode_init(void *opaque, struct module *module)
 {
+	struct microcode_ops *ops = (struct microcode_ops *)opaque;
 	int error;
 
-	printk(KERN_INFO
-		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
+	if (microcode_ops) {
+		printk(KERN_ERR "microcode: already loaded the other module\n");
+		return -EEXIST;
+	}
+
+	microcode_ops = ops;
 
 	error = microcode_dev_init();
 	if (error)
@@ -435,8 +439,15 @@ static int __init microcode_init (void)
 	}
 
 	register_hotcpu_notifier(&mc_cpu_notifier);
+
+	printk(KERN_INFO
+	       "Microcode Update Driver: v" MICROCODE_VERSION
+	       " <tigran@aivazian.fsnet.co.uk>"
+	       " <peter.oruba@amd.com>\n");
+
 	return 0;
 }
+EXPORT_SYMBOL_GPL(microcode_init);
 
 static void __exit microcode_exit (void)
 {
@@ -449,7 +460,10 @@ static void __exit microcode_exit (void)
 	put_online_cpus();
 
 	platform_device_unregister(microcode_pdev);
-}
 
-module_init(microcode_init)
-module_exit(microcode_exit)
+	microcode_ops = NULL;
+
+	printk(KERN_INFO
+	       "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
+}
+EXPORT_SYMBOL_GPL(microcode_exit);
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 4754137..dd2133b 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -119,6 +119,10 @@ MODULE_LICENSE("GPL");
 
 #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 
+
+extern int microcode_init(void *opaque, struct module *module);
+extern void microcode_exit(void);
+
 /* serialize access to the physical write to MSR 0x79 */
 static DEFINE_SPINLOCK(microcode_update_lock);
 
@@ -127,7 +131,7 @@ extern struct mutex microcode_mutex;
 
 extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
 
-void collect_cpu_info(int cpu_num)
+static void collect_cpu_info(int cpu_num)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
@@ -175,7 +179,7 @@ static inline int microcode_update_match(int cpu_num,
 	return 1;
 }
 
-int microcode_sanity_check(void *mc)
+static int microcode_sanity_check(void *mc)
 {
 	struct microcode_header_intel *mc_header = mc;
 	struct extended_sigtable *ext_header = NULL;
@@ -259,7 +263,7 @@ int microcode_sanity_check(void *mc)
  * return 1 - found update
  * return < 0 - error
  */
-int get_matching_microcode(void *mc, int cpu)
+static int get_matching_microcode(void *mc, int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	struct microcode_header_intel *mc_header = mc;
@@ -288,7 +292,8 @@ int get_matching_microcode(void *mc, int cpu)
 	return 0;
 find:
 	pr_debug("microcode: CPU%d found a matching microcode update with"
-		 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev);
+		 " version 0x%x (current=0x%x)\n",
+		 cpu, mc_header->rev, uci->rev);
 	new_mc = vmalloc(total_size);
 	if (!new_mc) {
 		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
@@ -303,7 +308,7 @@ find:
 	return 1;
 }
 
-void apply_microcode(int cpu)
+static void apply_microcode(int cpu)
 {
 	unsigned long flags;
 	unsigned int val[2];
@@ -347,7 +352,7 @@ void apply_microcode(int cpu)
 extern void __user *user_buffer;        /* user area microcode data buffer */
 extern unsigned int user_buffer_size;   /* it's size */
 
-long get_next_ucode(void **mc, long offset)
+static long get_next_ucode(void **mc, long offset)
 {
 	struct microcode_header_intel mc_header;
 	unsigned long total_size;
@@ -406,7 +411,7 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
 /* fake device for request_firmware */
 extern struct platform_device *microcode_pdev;
 
-int cpu_request_microcode(int cpu)
+static int cpu_request_microcode(int cpu)
 {
 	char name[30];
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -455,7 +460,7 @@ int cpu_request_microcode(int cpu)
 	return error;
 }
 
-int apply_microcode_check_cpu(int cpu)
+static int apply_microcode_check_cpu(int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -503,13 +508,42 @@ int apply_microcode_check_cpu(int cpu)
 	return err;
 }
 
-void microcode_fini_cpu(int cpu)
+static void microcode_fini_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
 	mutex_lock(&microcode_mutex);
 	uci->valid = 0;
-	kfree(uci->mc.mc_intel);
+	vfree(uci->mc.mc_intel);
 	uci->mc.mc_intel = NULL;
 	mutex_unlock(&microcode_mutex);
 }
+
+static struct microcode_ops microcode_intel_ops = {
+	.get_next_ucode                   = get_next_ucode,
+	.get_matching_microcode           = get_matching_microcode,
+	.microcode_sanity_check           = microcode_sanity_check,
+	.apply_microcode_check_cpu        = apply_microcode_check_cpu,
+	.cpu_request_microcode            = cpu_request_microcode,
+	.collect_cpu_info                 = collect_cpu_info,
+	.apply_microcode                  = apply_microcode,
+	.microcode_fini_cpu               = microcode_fini_cpu,
+};
+
+static int __init microcode_intel_module_init(void)
+{
+	struct cpuinfo_x86 *c = &cpu_data(get_cpu());
+
+	if (c->x86_vendor == X86_VENDOR_INTEL)
+		return microcode_init(&microcode_intel_ops, THIS_MODULE);
+	else
+		return -ENODEV;
+}
+
+static void __exit microcode_intel_module_exit(void)
+{
+	microcode_exit();
+}
+
+module_init(microcode_intel_module_init)
+module_exit(microcode_intel_module_exit)
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [patch 9/9] [PATCH 9/9] x86: AMD microcode patch loading support.
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (7 preceding siblings ...)
  2008-07-25 16:17 ` [patch 8/9] [PATCH 8/9] x86: Major refactoring Peter Oruba
@ 2008-07-25 16:17 ` Peter Oruba
  2008-07-26  8:00   ` Rabin Vincent
  2008-07-25 16:44 ` [PATCH] x86: Add entry to MAINTAINERS file Peter Oruba
  2008-07-26 13:37 ` [patch 0/9] x86: AMD microcode patch loading support Ingo Molnar
  10 siblings, 1 reply; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:17 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0009-x86-AMD-microcode-patch-loading-support.patch --]
[-- Type: text/plain, Size: 17257 bytes --]

This patch introduces microcode patch loading for AMD
processors. It is based on previous corresponding work
for Intel processors.

It hooks into the general patch loading module. Main
difference is that a container file format is used to hold
all patch data for multiple processors as well as an
equivalent CPU table, which comes seperately, as opposed
to Intel's microcode patching solution.

Kconfig and Makefile have been changed provice config
and build option for new source file.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 arch/x86/Kconfig                |   21 ++-
 arch/x86/kernel/Makefile        |    1 +
 arch/x86/kernel/microcode_amd.c |  516 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 534 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/kernel/microcode_amd.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ece1e27..b102d24 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -786,10 +786,12 @@ config MICROCODE
 	select FW_LOADER
 	---help---
 	  If you say Y here, you will be able to update the microcode on
-	  Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
-	  Pentium III, Pentium 4, Xeon etc.  You will obviously need the
-	  actual microcode binary data itself which is not shipped with the
-	  Linux kernel.
+	  certain Intel and AMD processors. The Intel support is for the
+	  IA32 family, e.g. Pentium Pro, Pentium II, Pentium III,
+	  Pentium 4, Xeon etc. The AMD support is for family 0x10 and
+	  0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra.
+	  You will obviously need the actual microcode binary data itself
+	  which is not shipped with the Linux kernel.
 
 	  This option selects the general module only, you need to select
 	  at least one vendor specific module as well.
@@ -812,6 +814,17 @@ config MICROCODE_INTEL
          This driver is only available as a module: the module
          will be called microcode_intel.  
 
+config MICROCODE_AMD
+       tristate "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_intel.
+
    config MICROCODE_OLD_INTERFACE
 	def_bool y
 	depends on MICROCODE
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index f2f9f6d..be454f3 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -53,6 +53,7 @@ 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
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
new file mode 100644
index 0000000..c9eebc7
--- /dev/null
+++ b/arch/x86/kernel/microcode_amd.c
@@ -0,0 +1,516 @@
+/*
+ *  AMD CPU Microcode Update Driver for Linux
+ *  Copyright (C) 2008 Advanced Micro Devices Inc.
+ *
+ *  Author: Peter Oruba <peter.oruba@amd.com>
+ *
+ *  Based on work by:
+ *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ *
+ *  This driver allows to upgrade microcode on AMD
+ *  family 0x10 and 0x11 processors.
+ *
+ *  Licensed unter the terms of the GNU General Public
+ *  License version 2. See file COPYING for details.
+*/
+
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/microcode.h>
+
+MODULE_DESCRIPTION("AMD Microcode Update Driver");
+MODULE_AUTHOR("Peter Oruba <peter.oruba@amd.com>");
+MODULE_LICENSE("GPL");
+
+#define UCODE_MAGIC                0x00414d44
+#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
+#define UCODE_UCODE_TYPE           0x00000001
+
+#define UCODE_MAX_SIZE          (2048)
+#define DEFAULT_UCODE_DATASIZE	(896)	  /* 896 bytes */
+#define MC_HEADER_SIZE		(sizeof(struct microcode_header_amd))	  /* 64 bytes */
+#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */
+#define DWSIZE			(sizeof(u32))
+/* For now we support a fixed ucode total size only */
+#define get_totalsize(mc) \
+	((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
+	 + MC_HEADER_SIZE)
+
+extern int microcode_init(void *opaque, struct module *module);
+extern void microcode_exit(void);
+
+/* serialize access to the physical write */
+static DEFINE_SPINLOCK(microcode_update_lock);
+
+/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+extern struct mutex (microcode_mutex);
+
+struct equiv_cpu_entry *equiv_cpu_table;
+
+extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
+
+static void collect_cpu_info_amd(int cpu)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+	/* We should bind the task to the CPU */
+	BUG_ON(raw_smp_processor_id() != cpu);
+	uci->rev = 0;
+	uci->pf = 0;
+	uci->mc.mc_amd = NULL;
+	uci->valid = 1;
+
+	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
+		printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
+		       cpu);
+		uci->valid = 0;
+		return;
+	}
+
+	asm volatile("movl %1, %%ecx; rdmsr"
+		     : "=a" (uci->rev)
+		     : "i" (0x0000008B) : "ecx");
+
+	printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n",
+	       uci->rev);
+}
+
+static int get_matching_microcode_amd(void *mc, int cpu)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	struct microcode_header_amd *mc_header = mc;
+	unsigned long total_size = get_totalsize(mc_header);
+	void *new_mc;
+	struct pci_dev *nb_pci_dev, *sb_pci_dev;
+	unsigned int current_cpu_id;
+	unsigned int equiv_cpu_id = 0x00;
+	unsigned int i = 0;
+
+	/* We should bind the task to the CPU */
+	BUG_ON(cpu != raw_smp_processor_id());
+
+	/* This is a tricky part. We might be called from a write operation */
+	/* to the device file instead of the usual process of firmware */
+	/* loading. This routine needs to be able to distinguish both */
+        /* cases. This is done by checking if there alread is a equivalent */
+	/* CPU table installed. If not, we're written through */
+	/* /dev/cpu/microcode. */
+        /* Since we ignore all checks. The error case in which going through */
+        /* firmware loading and that table is not loaded has already been */
+	/* checked earlier. */
+	if (equiv_cpu_table == NULL) {
+		printk(KERN_INFO "microcode: CPU%d microcode update with "
+		       "version 0x%x (current=0x%x)\n",
+		       cpu, mc_header->patch_id, uci->rev);
+		goto out;
+	}
+
+	current_cpu_id = cpuid_eax(0x00000001);
+
+	while (equiv_cpu_table[i].installed_cpu != 0) {
+		if (current_cpu_id == equiv_cpu_table[i].installed_cpu) {
+			equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
+			break;
+		}
+		i++;
+	}
+
+	if (!equiv_cpu_id) {
+		printk(KERN_ERR "microcode: CPU%d cpu_id "
+		       "not found in equivalent cpu table \n", cpu);
+		return 0;
+	}
+
+	if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) {
+		printk(KERN_ERR
+			"microcode: CPU%d patch does not match "
+			"(patch is %x, cpu extended is %x) \n",
+			cpu, mc_header->processor_rev_id[0],
+			(equiv_cpu_id & 0xff));
+		return 0;
+	}
+
+	if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) {
+		printk(KERN_ERR "microcode: CPU%d patch does not match "
+			"(patch is %x, cpu base id is %x) \n",
+			cpu, mc_header->processor_rev_id[1],
+			((equiv_cpu_id >> 16) & 0xff));
+
+		return 0;
+	}
+
+	/* ucode may be northbridge specific */
+	if (mc_header->nb_dev_id) {
+		nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+					    (mc_header->nb_dev_id & 0xff),
+					    NULL);
+		if ((!nb_pci_dev) ||
+		    (mc_header->nb_rev_id != nb_pci_dev->revision)) {
+			printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu);
+			pci_dev_put(nb_pci_dev);
+			return 0;
+		}
+		pci_dev_put(nb_pci_dev);
+	}
+
+	/* ucode may be southbridge specific */
+	if (mc_header->sb_dev_id) {
+		sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+					    (mc_header->sb_dev_id & 0xff),
+					    NULL);
+		if ((!sb_pci_dev) ||
+		    (mc_header->sb_rev_id != sb_pci_dev->revision)) {
+			printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu);
+			pci_dev_put(sb_pci_dev);
+			return 0;
+		}
+		pci_dev_put(sb_pci_dev);
+	}
+
+	if (mc_header->patch_id <= uci->rev)
+		return 0;
+
+	printk(KERN_INFO "microcode: CPU%d found a matching microcode "
+	       "update with version 0x%x (current=0x%x)\n",
+	       cpu, mc_header->patch_id, uci->rev);
+
+out:
+	new_mc = vmalloc(UCODE_MAX_SIZE);
+	memset(new_mc, 0, UCODE_MAX_SIZE);
+
+	if (!new_mc) {
+		printk(KERN_ERR "microcode: error, can't allocate memory\n");
+		return -ENOMEM;
+	}
+
+	/* free previous update file */
+	vfree(uci->mc.mc_amd);
+
+	memcpy(new_mc, mc, total_size);
+
+	uci->mc.mc_amd = new_mc;
+	return 1;
+}
+
+static void apply_microcode_amd(int cpu)
+{
+	unsigned long flags;
+	unsigned int eax, edx;
+	unsigned int rev;
+	int cpu_num = raw_smp_processor_id();
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
+
+	/* We should bind the task to the CPU */
+	BUG_ON(cpu_num != cpu);
+
+	if (uci->mc.mc_amd == NULL)
+		return;
+
+	spin_lock_irqsave(&microcode_update_lock, flags);
+
+	edx = (unsigned int)(((unsigned long)
+			      &(uci->mc.mc_amd->hdr.data_code)) >> 32);
+	eax = (unsigned int)(((unsigned long)
+			      &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL);
+
+	asm volatile("movl %0, %%ecx; wrmsr" :
+		     : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx");
+
+	/* get patch id after patching */
+	asm volatile("movl %1, %%ecx; rdmsr"
+		     : "=a" (rev)
+		     : "i" (0x0000008B) : "ecx");
+
+	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) {
+		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);
+		return;
+	}
+
+	printk(KERN_INFO "microcode: CPU%d updated from revision "
+	       "0x%x to 0x%x \n",
+	       cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id);
+
+	uci->rev = rev;
+}
+
+#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+extern void __user *user_buffer;        /* user area microcode data buffer */
+extern unsigned int user_buffer_size;   /* it's size */
+
+static long get_next_ucode_amd(void **mc, long offset)
+{
+	struct microcode_header_amd mc_header;
+	unsigned long total_size;
+
+	/* No more data */
+	if (offset >= user_buffer_size)
+		return 0;
+	if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
+		printk(KERN_ERR "microcode: error! Can not read user data\n");
+		return -EFAULT;
+	}
+	total_size = get_totalsize(&mc_header);
+	if (offset + total_size > user_buffer_size) {
+		printk(KERN_ERR "microcode: error! Bad total size in microcode "
+		       "data file\n");
+		return -EINVAL;
+	}
+	*mc = vmalloc(UCODE_MAX_SIZE);
+	memset(*mc, 0, UCODE_MAX_SIZE);
+
+	if (!*mc)
+		return -ENOMEM;
+	if (copy_from_user(*mc, user_buffer + offset, total_size)) {
+		printk(KERN_ERR "microcode: error! Can not read user data\n");
+		vfree(*mc);
+		return -EFAULT;
+	}
+	return offset + total_size;
+}
+#else
+#define get_next_ucode_amd() NULL
+#endif
+
+static long get_next_ucode_from_buffer_amd(void **mc, void *buf,
+				       unsigned long size, long offset)
+{
+	struct microcode_header_amd *mc_header;
+	unsigned long total_size;
+	unsigned char *buf_pos = buf;
+
+	/* No more data */
+	if (offset >= size)
+		return 0;
+
+	if (buf_pos[offset] != UCODE_UCODE_TYPE) {
+		printk(KERN_ERR "microcode: error! "
+		       "Wrong microcode payload type field\n");
+		return -EINVAL;
+	}
+
+	mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
+
+	total_size = (unsigned long) (buf_pos[offset+4] +
+				      (buf_pos[offset+5] << 8));
+
+	printk(KERN_ERR "microcode: size %lu, total_size %lu, offset %ld\n",
+		size, total_size, offset);
+
+	if (offset + total_size > size) {
+		printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+		return -EINVAL;
+	}
+
+	*mc = vmalloc(UCODE_MAX_SIZE);
+	memset(*mc, 0, UCODE_MAX_SIZE);
+
+	if (!*mc) {
+		printk(KERN_ERR "microcode: error! "
+		       "Can not allocate memory for microcode patch\n");
+		return -ENOMEM;
+	}
+	memcpy(*mc, buf + offset + 8, total_size);
+
+	return offset + total_size + 8;
+}
+
+static long install_equiv_cpu_table(void *buf, unsigned long size, long offset)
+{
+	unsigned int *buf_pos = buf;
+
+	/* No more data */
+	if (offset >= size)
+		return 0;
+
+	if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) {
+		printk(KERN_ERR "microcode: error! "
+		       "Wrong microcode equivalnet cpu table type field\n");
+		return 0;
+	}
+
+	if (size == 0) {
+		printk(KERN_ERR "microcode: error! "
+		       "Wrong microcode equivalnet cpu table length\n");
+		return 0;
+	}
+
+	equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size);
+	memset(equiv_cpu_table, 0, size);
+
+	memcpy(equiv_cpu_table, &buf_pos[3], size);
+
+	return size + 12; /* add header length */
+}
+
+/* fake device for request_firmware */
+extern struct platform_device *microcode_pdev;
+
+static int cpu_request_microcode_amd(int cpu)
+{
+	char name[30];
+	const struct firmware *firmware;
+	void *buf;
+	unsigned int *buf_pos;
+	unsigned long size;
+	long offset = 0;
+	int error;
+	void *mc;
+
+	/* We should bind the task to the CPU */
+	BUG_ON(cpu != raw_smp_processor_id());
+
+	sprintf(name, "amd-ucode/microcode_amd.bin");
+	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+	if (error) {
+		printk(KERN_ERR "microcode: ucode data file %s load failed\n",
+		       name);
+		return error;
+	}
+
+	buf_pos = buf = firmware->data;
+	size = firmware->size;
+
+	if (buf_pos[0] != UCODE_MAGIC) {
+		printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n");
+		return 0;
+	}
+
+	offset = install_equiv_cpu_table(buf, buf_pos[2], offset);
+
+	if (!offset) {
+		printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
+		return error;
+	}
+
+	while ((offset =
+		get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) {
+		error = get_matching_microcode_amd(mc, cpu);
+		if (error < 0)
+			break;
+		/*
+		 * It's possible the data file has multiple matching ucode,
+		 * lets keep searching till the latest version
+		 */
+		if (error == 1) {
+			apply_microcode_amd(cpu);
+			error = 0;
+		}
+		vfree(mc);
+	}
+
+	if (offset > 0) {
+		vfree(mc);
+		vfree(equiv_cpu_table);
+	}
+	if (offset < 0)
+		error = offset;
+	release_firmware(firmware);
+
+	return error;
+}
+
+static int apply_microcode_check_cpu_amd(int cpu)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	unsigned int rev;
+	cpumask_t old;
+	int err = 0;
+
+	/* Check if the microcode is available */
+	if (!uci->mc.mc_amd)
+		return 0;
+
+	old = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+	/* Check if the microcode we have in memory matches the CPU */
+	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16)
+		err = -EINVAL;
+
+	if (!err) {
+		asm volatile("movl %1, %%ecx; rdmsr"
+		     : "=a" (rev)
+		     : "i" (0x0000008B) : "ecx");
+
+		if (uci->rev != rev)
+			err = -EINVAL;
+	}
+
+	if (!err)
+		apply_microcode_amd(cpu);
+	else
+		printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
+		       " rev=0x%x\n",
+		       cpu,  uci->rev);
+
+	set_cpus_allowed(current, old);
+	return err;
+}
+
+static void microcode_fini_cpu_amd(int cpu)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+	mutex_lock(&microcode_mutex);
+	uci->valid = 0;
+	vfree(uci->mc.mc_amd);
+	uci->mc.mc_amd = NULL;
+	mutex_unlock(&microcode_mutex);
+}
+
+static struct microcode_ops microcode_amd_ops = {
+	.get_next_ucode                   = get_next_ucode_amd,
+	.get_matching_microcode           = get_matching_microcode_amd,
+	.microcode_sanity_check           = NULL,
+	.apply_microcode_check_cpu        = apply_microcode_check_cpu_amd,
+	.cpu_request_microcode            = cpu_request_microcode_amd,
+	.collect_cpu_info                 = collect_cpu_info_amd,
+	.apply_microcode                  = apply_microcode_amd,
+	.microcode_fini_cpu               = microcode_fini_cpu_amd,
+};
+
+static int __init microcode_amd_module_init(void)
+{
+	struct cpuinfo_x86 *c = &cpu_data(get_cpu());
+
+	equiv_cpu_table = NULL;
+	if (c->x86_vendor == X86_VENDOR_AMD)
+		return microcode_init(&microcode_amd_ops, THIS_MODULE);
+	else
+		return -ENODEV;
+}
+
+static void __exit microcode_amd_module_exit(void)
+{
+	microcode_exit();
+}
+
+module_init(microcode_amd_module_init)
+module_exit(microcode_amd_module_exit)
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH] x86: Add entry to MAINTAINERS file
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (8 preceding siblings ...)
  2008-07-25 16:17 ` [patch 9/9] [PATCH 9/9] x86: AMD microcode patch loading support Peter Oruba
@ 2008-07-25 16:44 ` Peter Oruba
  2008-07-26 13:37 ` [patch 0/9] x86: AMD microcode patch loading support Ingo Molnar
  10 siblings, 0 replies; 14+ messages in thread
From: Peter Oruba @ 2008-07-25 16:44 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, Tigran Aivazian; +Cc: LKML, Peter Oruba

[-- Attachment #1: 0001-x86-Add-entry-to-MAINTAINERS-file.patch --]
[-- Type: text/plain, Size: 606 bytes --]

Add an entry to the MAINTAINERS file for AMD CPU microcode
patch loading support.

Signed-off-by: Peter Oruba <peter.oruba@amd.com>
---
 MAINTAINERS |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index df3fa0e..da77c18 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -384,6 +384,11 @@ M:	joerg.roedel@amd.com
 L:	iommu@lists.linux-foundation.org
 S:	Supported
 
+AMD MICROCODE UPDATE SUPPORT
+P:      Peter Oruba
+M:      peter.oruba@amd.com
+S:      Supported
+
 AMS (Apple Motion Sensor) DRIVER
 P:	Stelian Pop
 M:	stelian@popies.net
-- 
1.5.4.5





^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [patch 9/9] [PATCH 9/9] x86: AMD microcode patch loading support.
  2008-07-25 16:17 ` [patch 9/9] [PATCH 9/9] x86: AMD microcode patch loading support Peter Oruba
@ 2008-07-26  8:00   ` Rabin Vincent
  0 siblings, 0 replies; 14+ messages in thread
From: Rabin Vincent @ 2008-07-26  8:00 UTC (permalink / raw)
  To: Peter Oruba; +Cc: Ingo Molnar, Thomas Gleixner, Tigran Aivazian, LKML

On Fri, Jul 25, 2008 at 06:17:32PM +0200, Peter Oruba wrote:
> This patch introduces microcode patch loading for AMD
> processors. It is based on previous corresponding work
> for Intel processors.
> 
> It hooks into the general patch loading module. Main
> difference is that a container file format is used to hold
> all patch data for multiple processors as well as an
> equivalent CPU table, which comes seperately, as opposed
> to Intel's microcode patching solution.
> 
> Kconfig and Makefile have been changed provice config
> and build option for new source file.
> 
> Signed-off-by: Peter Oruba <peter.oruba@amd.com>

Can't comment on your refactoring/design, but see below for some
things to possibly fix in the code.

> ---
>  arch/x86/Kconfig                |   21 ++-
>  arch/x86/kernel/Makefile        |    1 +
>  arch/x86/kernel/microcode_amd.c |  516 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 534 insertions(+), 4 deletions(-)
>  create mode 100644 arch/x86/kernel/microcode_amd.c
> 
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index ece1e27..b102d24 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -786,10 +786,12 @@ config MICROCODE
>  	select FW_LOADER
>  	---help---
>  	  If you say Y here, you will be able to update the microcode on
> -	  Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II,
> -	  Pentium III, Pentium 4, Xeon etc.  You will obviously need the
> -	  actual microcode binary data itself which is not shipped with the
> -	  Linux kernel.
> +	  certain Intel and AMD processors. The Intel support is for the
> +	  IA32 family, e.g. Pentium Pro, Pentium II, Pentium III,
> +	  Pentium 4, Xeon etc. The AMD support is for family 0x10 and
> +	  0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra.
> +	  You will obviously need the actual microcode binary data itself
> +	  which is not shipped with the Linux kernel.
>  
>  	  This option selects the general module only, you need to select
>  	  at least one vendor specific module as well.
> @@ -812,6 +814,17 @@ config MICROCODE_INTEL
>           This driver is only available as a module: the module
>           will be called microcode_intel.  
>  
> +config MICROCODE_AMD
> +       tristate "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_intel.

Should say microcode_amd.

> +
>     config MICROCODE_OLD_INTERFACE
>  	def_bool y
>  	depends on MICROCODE
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index f2f9f6d..be454f3 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -53,6 +53,7 @@ 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
> diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
> new file mode 100644
> index 0000000..c9eebc7
> --- /dev/null
> +++ b/arch/x86/kernel/microcode_amd.c
> @@ -0,0 +1,516 @@
> +/*
> + *  AMD CPU Microcode Update Driver for Linux
> + *  Copyright (C) 2008 Advanced Micro Devices Inc.
> + *
> + *  Author: Peter Oruba <peter.oruba@amd.com>
> + *
> + *  Based on work by:
> + *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
> + *
> + *  This driver allows to upgrade microcode on AMD
> + *  family 0x10 and 0x11 processors.
> + *
> + *  Licensed unter the terms of the GNU General Public
> + *  License version 2. See file COPYING for details.
> +*/
> +
> +#include <linux/capability.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/sched.h>
> +#include <linux/cpumask.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/vmalloc.h>
> +#include <linux/miscdevice.h>
> +#include <linux/spinlock.h>
> +#include <linux/mm.h>
> +#include <linux/fs.h>
> +#include <linux/mutex.h>
> +#include <linux/cpu.h>
> +#include <linux/firmware.h>
> +#include <linux/platform_device.h>
> +#include <linux/pci.h>
> +#include <linux/pci_ids.h>
> +
> +#include <asm/msr.h>
> +#include <asm/uaccess.h>
> +#include <asm/processor.h>
> +#include <asm/microcode.h>
> +
> +MODULE_DESCRIPTION("AMD Microcode Update Driver");
> +MODULE_AUTHOR("Peter Oruba <peter.oruba@amd.com>");
> +MODULE_LICENSE("GPL");

Based on the license in the comments at the top of the file, I think
this should be "GPLv2".

> +
> +#define UCODE_MAGIC                0x00414d44
> +#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
> +#define UCODE_UCODE_TYPE           0x00000001
> +
> +#define UCODE_MAX_SIZE          (2048)
> +#define DEFAULT_UCODE_DATASIZE	(896)	  /* 896 bytes */
> +#define MC_HEADER_SIZE		(sizeof(struct microcode_header_amd))	  /* 64 bytes */
> +#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */
> +#define DWSIZE			(sizeof(u32))
> +/* For now we support a fixed ucode total size only */
> +#define get_totalsize(mc) \
> +	((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
> +	 + MC_HEADER_SIZE)
> +
> +extern int microcode_init(void *opaque, struct module *module);
> +extern void microcode_exit(void);

Since these declarations (and the other externs) are shared with the
other Intel driver, why not move them to the header file?

> +
> +/* serialize access to the physical write */
> +static DEFINE_SPINLOCK(microcode_update_lock);
> +
> +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
> +extern struct mutex (microcode_mutex);
> +
> +struct equiv_cpu_entry *equiv_cpu_table;
> +
> +extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
> +
> +static void collect_cpu_info_amd(int cpu)
> +{
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
> +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
> +
> +	/* We should bind the task to the CPU */
> +	BUG_ON(raw_smp_processor_id() != cpu);
> +	uci->rev = 0;
> +	uci->pf = 0;
> +	uci->mc.mc_amd = NULL;
> +	uci->valid = 1;
> +
> +	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
> +		printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
> +		       cpu);
> +		uci->valid = 0;
> +		return;
> +	}
> +
> +	asm volatile("movl %1, %%ecx; rdmsr"
> +		     : "=a" (uci->rev)
> +		     : "i" (0x0000008B) : "ecx");
> +
> +	printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n",
> +	       uci->rev);
> +}
> +
> +static int get_matching_microcode_amd(void *mc, int cpu)
> +{
> +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
> +	struct microcode_header_amd *mc_header = mc;
> +	unsigned long total_size = get_totalsize(mc_header);
> +	void *new_mc;
> +	struct pci_dev *nb_pci_dev, *sb_pci_dev;
> +	unsigned int current_cpu_id;
> +	unsigned int equiv_cpu_id = 0x00;
> +	unsigned int i = 0;
> +
> +	/* We should bind the task to the CPU */
> +	BUG_ON(cpu != raw_smp_processor_id());
> +
> +	/* This is a tricky part. We might be called from a write operation */
> +	/* to the device file instead of the usual process of firmware */
> +	/* loading. This routine needs to be able to distinguish both */
> +        /* cases. This is done by checking if there alread is a equivalent */
> +	/* CPU table installed. If not, we're written through */
> +	/* /dev/cpu/microcode. */
> +        /* Since we ignore all checks. The error case in which going through */
> +        /* firmware loading and that table is not loaded has already been */
> +	/* checked earlier. */

Some spaces seem to have sneaked in the indentation above. 

> +	if (equiv_cpu_table == NULL) {
> +		printk(KERN_INFO "microcode: CPU%d microcode update with "
> +		       "version 0x%x (current=0x%x)\n",
> +		       cpu, mc_header->patch_id, uci->rev);
> +		goto out;
> +	}
> +
> +	current_cpu_id = cpuid_eax(0x00000001);
> +
> +	while (equiv_cpu_table[i].installed_cpu != 0) {
> +		if (current_cpu_id == equiv_cpu_table[i].installed_cpu) {
> +			equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
> +			break;
> +		}
> +		i++;
> +	}
> +
> +	if (!equiv_cpu_id) {
> +		printk(KERN_ERR "microcode: CPU%d cpu_id "
> +		       "not found in equivalent cpu table \n", cpu);
> +		return 0;
> +	}
> +
> +	if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) {
> +		printk(KERN_ERR
> +			"microcode: CPU%d patch does not match "
> +			"(patch is %x, cpu extended is %x) \n",
> +			cpu, mc_header->processor_rev_id[0],
> +			(equiv_cpu_id & 0xff));
> +		return 0;
> +	}
> +
> +	if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) {
> +		printk(KERN_ERR "microcode: CPU%d patch does not match "
> +			"(patch is %x, cpu base id is %x) \n",
> +			cpu, mc_header->processor_rev_id[1],
> +			((equiv_cpu_id >> 16) & 0xff));
> +
> +		return 0;
> +	}
> +
> +	/* ucode may be northbridge specific */
> +	if (mc_header->nb_dev_id) {
> +		nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
> +					    (mc_header->nb_dev_id & 0xff),
> +					    NULL);
> +		if ((!nb_pci_dev) ||
> +		    (mc_header->nb_rev_id != nb_pci_dev->revision)) {
> +			printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu);
> +			pci_dev_put(nb_pci_dev);
> +			return 0;
> +		}
> +		pci_dev_put(nb_pci_dev);
> +	}
> +
> +	/* ucode may be southbridge specific */
> +	if (mc_header->sb_dev_id) {
> +		sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
> +					    (mc_header->sb_dev_id & 0xff),
> +					    NULL);
> +		if ((!sb_pci_dev) ||
> +		    (mc_header->sb_rev_id != sb_pci_dev->revision)) {
> +			printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu);
> +			pci_dev_put(sb_pci_dev);
> +			return 0;
> +		}
> +		pci_dev_put(sb_pci_dev);
> +	}
> +
> +	if (mc_header->patch_id <= uci->rev)
> +		return 0;
> +
> +	printk(KERN_INFO "microcode: CPU%d found a matching microcode "
> +	       "update with version 0x%x (current=0x%x)\n",
> +	       cpu, mc_header->patch_id, uci->rev);
> +
> +out:
> +	new_mc = vmalloc(UCODE_MAX_SIZE);
> +	memset(new_mc, 0, UCODE_MAX_SIZE);

The memset() should come after the vmalloc() failure check.

> +
> +	if (!new_mc) {
> +		printk(KERN_ERR "microcode: error, can't allocate memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* free previous update file */
> +	vfree(uci->mc.mc_amd);
> +
> +	memcpy(new_mc, mc, total_size);
> +
> +	uci->mc.mc_amd = new_mc;
> +	return 1;
> +}
> +
> +static void apply_microcode_amd(int cpu)
> +{
> +	unsigned long flags;
> +	unsigned int eax, edx;
> +	unsigned int rev;
> +	int cpu_num = raw_smp_processor_id();
> +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
> +
> +	/* We should bind the task to the CPU */
> +	BUG_ON(cpu_num != cpu);
> +
> +	if (uci->mc.mc_amd == NULL)
> +		return;
> +
> +	spin_lock_irqsave(&microcode_update_lock, flags);
> +
> +	edx = (unsigned int)(((unsigned long)
> +			      &(uci->mc.mc_amd->hdr.data_code)) >> 32);
> +	eax = (unsigned int)(((unsigned long)
> +			      &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL);
> +
> +	asm volatile("movl %0, %%ecx; wrmsr" :
> +		     : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx");
> +
> +	/* get patch id after patching */
> +	asm volatile("movl %1, %%ecx; rdmsr"
> +		     : "=a" (rev)
> +		     : "i" (0x0000008B) : "ecx");
> +
> +	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) {
> +		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);
> +		return;
> +	}
> +
> +	printk(KERN_INFO "microcode: CPU%d updated from revision "
> +	       "0x%x to 0x%x \n",
> +	       cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id);
> +
> +	uci->rev = rev;
> +}
> +
> +#ifdef CONFIG_MICROCODE_OLD_INTERFACE
> +extern void __user *user_buffer;        /* user area microcode data buffer */
> +extern unsigned int user_buffer_size;   /* it's size */
> +
> +static long get_next_ucode_amd(void **mc, long offset)
> +{
> +	struct microcode_header_amd mc_header;
> +	unsigned long total_size;
> +
> +	/* No more data */
> +	if (offset >= user_buffer_size)
> +		return 0;
> +	if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
> +		printk(KERN_ERR "microcode: error! Can not read user data\n");
> +		return -EFAULT;
> +	}
> +	total_size = get_totalsize(&mc_header);
> +	if (offset + total_size > user_buffer_size) {
> +		printk(KERN_ERR "microcode: error! Bad total size in microcode "
> +		       "data file\n");
> +		return -EINVAL;
> +	}
> +	*mc = vmalloc(UCODE_MAX_SIZE);
> +	memset(*mc, 0, UCODE_MAX_SIZE);

The memset() should come after the vmalloc() failure check.

> +
> +	if (!*mc)
> +		return -ENOMEM;
> +	if (copy_from_user(*mc, user_buffer + offset, total_size)) {
> +		printk(KERN_ERR "microcode: error! Can not read user data\n");
> +		vfree(*mc);
> +		return -EFAULT;
> +	}
> +	return offset + total_size;
> +}
> +#else
> +#define get_next_ucode_amd() NULL
> +#endif
> +
> +static long get_next_ucode_from_buffer_amd(void **mc, void *buf,
> +				       unsigned long size, long offset)
> +{
> +	struct microcode_header_amd *mc_header;
> +	unsigned long total_size;
> +	unsigned char *buf_pos = buf;
> +
> +	/* No more data */
> +	if (offset >= size)
> +		return 0;
> +
> +	if (buf_pos[offset] != UCODE_UCODE_TYPE) {
> +		printk(KERN_ERR "microcode: error! "
> +		       "Wrong microcode payload type field\n");
> +		return -EINVAL;
> +	}
> +
> +	mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
> +
> +	total_size = (unsigned long) (buf_pos[offset+4] +
> +				      (buf_pos[offset+5] << 8));
> +
> +	printk(KERN_ERR "microcode: size %lu, total_size %lu, offset %ld\n",
> +		size, total_size, offset);

Unconditional KERN_ERR?

> +
> +	if (offset + total_size > size) {
> +		printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
> +		return -EINVAL;
> +	}
> +
> +	*mc = vmalloc(UCODE_MAX_SIZE);
> +	memset(*mc, 0, UCODE_MAX_SIZE);

The memset() should come after the vmalloc() failure check.

> +
> +	if (!*mc) {
> +		printk(KERN_ERR "microcode: error! "
> +		       "Can not allocate memory for microcode patch\n");
> +		return -ENOMEM;
> +	}
> +	memcpy(*mc, buf + offset + 8, total_size);
> +
> +	return offset + total_size + 8;
> +}
> +
> +static long install_equiv_cpu_table(void *buf, unsigned long size, long offset)
> +{
> +	unsigned int *buf_pos = buf;
> +
> +	/* No more data */
> +	if (offset >= size)
> +		return 0;
> +
> +	if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) {
> +		printk(KERN_ERR "microcode: error! "
> +		       "Wrong microcode equivalnet cpu table type field\n");
> +		return 0;
> +	}
> +
> +	if (size == 0) {
> +		printk(KERN_ERR "microcode: error! "
> +		       "Wrong microcode equivalnet cpu table length\n");
> +		return 0;
> +	}
> +
> +	equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size);
> +	memset(equiv_cpu_table, 0, size);

No failure check for the allocation here.

> +
> +	memcpy(equiv_cpu_table, &buf_pos[3], size);
> +
> +	return size + 12; /* add header length */
> +}
> +
> +/* fake device for request_firmware */
> +extern struct platform_device *microcode_pdev;
> +
> +static int cpu_request_microcode_amd(int cpu)
> +{
> +	char name[30];
> +	const struct firmware *firmware;
> +	void *buf;
> +	unsigned int *buf_pos;
> +	unsigned long size;
> +	long offset = 0;
> +	int error;
> +	void *mc;
> +
> +	/* We should bind the task to the CPU */
> +	BUG_ON(cpu != raw_smp_processor_id());
> +
> +	sprintf(name, "amd-ucode/microcode_amd.bin");

Just pass the string directly to request_firmware.

> +	error = request_firmware(&firmware, name, &microcode_pdev->dev);
> +	if (error) {
> +		printk(KERN_ERR "microcode: ucode data file %s load failed\n",
> +		       name);
> +		return error;
> +	}
> +
> +	buf_pos = buf = firmware->data;
> +	size = firmware->size;
> +
> +	if (buf_pos[0] != UCODE_MAGIC) {
> +		printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n");
> +		return 0;
> +	}
> +
> +	offset = install_equiv_cpu_table(buf, buf_pos[2], offset);
> +
> +	if (!offset) {
> +		printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
> +		return error;

This will always return zero, since error has not been touched since the
last check after request_firmware().

> +	}
> +
> +	while ((offset =
> +		get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) {
> +		error = get_matching_microcode_amd(mc, cpu);
> +		if (error < 0)
> +			break;
> +		/*
> +		 * It's possible the data file has multiple matching ucode,
> +		 * lets keep searching till the latest version
> +		 */
> +		if (error == 1) {
> +			apply_microcode_amd(cpu);
> +			error = 0;
> +		}
> +		vfree(mc);
> +	}
> +
> +	if (offset > 0) {
> +		vfree(mc);
> +		vfree(equiv_cpu_table);

Set equiv_cpu_table to NULL after freeing it.

> +	}
> +	if (offset < 0)
> +		error = offset;
> +	release_firmware(firmware);
> +
> +	return error;
> +}
> +
> +static int apply_microcode_check_cpu_amd(int cpu)
> +{
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
> +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
> +	unsigned int rev;
> +	cpumask_t old;
> +	int err = 0;
> +
> +	/* Check if the microcode is available */
> +	if (!uci->mc.mc_amd)
> +		return 0;
> +
> +	old = current->cpus_allowed;
> +	set_cpus_allowed(current, cpumask_of_cpu(cpu));
> +
> +	/* Check if the microcode we have in memory matches the CPU */
> +	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16)
> +		err = -EINVAL;
> +
> +	if (!err) {
> +		asm volatile("movl %1, %%ecx; rdmsr"
> +		     : "=a" (rev)
> +		     : "i" (0x0000008B) : "ecx");
> +
> +		if (uci->rev != rev)
> +			err = -EINVAL;
> +	}
> +
> +	if (!err)
> +		apply_microcode_amd(cpu);
> +	else
> +		printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
> +		       " rev=0x%x\n",
> +		       cpu,  uci->rev);
> +
> +	set_cpus_allowed(current, old);
> +	return err;
> +}
> +
> +static void microcode_fini_cpu_amd(int cpu)
> +{
> +	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
> +
> +	mutex_lock(&microcode_mutex);
> +	uci->valid = 0;
> +	vfree(uci->mc.mc_amd);
> +	uci->mc.mc_amd = NULL;
> +	mutex_unlock(&microcode_mutex);
> +}
> +
> +static struct microcode_ops microcode_amd_ops = {
> +	.get_next_ucode                   = get_next_ucode_amd,
> +	.get_matching_microcode           = get_matching_microcode_amd,
> +	.microcode_sanity_check           = NULL,
> +	.apply_microcode_check_cpu        = apply_microcode_check_cpu_amd,
> +	.cpu_request_microcode            = cpu_request_microcode_amd,
> +	.collect_cpu_info                 = collect_cpu_info_amd,
> +	.apply_microcode                  = apply_microcode_amd,
> +	.microcode_fini_cpu               = microcode_fini_cpu_amd,
> +};
> +
> +static int __init microcode_amd_module_init(void)
> +{
> +	struct cpuinfo_x86 *c = &cpu_data(get_cpu());
> +
> +	equiv_cpu_table = NULL;
> +	if (c->x86_vendor == X86_VENDOR_AMD)
> +		return microcode_init(&microcode_amd_ops, THIS_MODULE);
> +	else
> +		return -ENODEV;
> +}
> +
> +static void __exit microcode_amd_module_exit(void)
> +{
> +	microcode_exit();
> +}
> +
> +module_init(microcode_amd_module_init)
> +module_exit(microcode_amd_module_exit)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 8/9] [PATCH 8/9] x86: Major refactoring.
  2008-07-25 16:17 ` [patch 8/9] [PATCH 8/9] x86: Major refactoring Peter Oruba
@ 2008-07-26  9:11   ` Daniel K.
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel K. @ 2008-07-26  9:11 UTC (permalink / raw)
  To: Peter Oruba; +Cc: Ingo Molnar, Thomas Gleixner, Tigran Aivazian, LKML

Peter Oruba wrote:
> Refactored code by introducing a two-module solution. There is one
> general module in which vendor specific modules can hook into.
>  
>  config MICROCODE
> -	tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
> +	tristate "/dev/cpu/microcode - microcode support"
>  	select FW_LOADER
>  	---help---
>  	  If you say Y here, you will be able to update the microcode on
> @@ -791,14 +791,28 @@ config MICROCODE
>  	  actual microcode binary data itself which is not shipped with the
>  	  Linux kernel.
>  
> -	  For latest news and information on obtaining all the required
> -	  ingredients for this driver, check:
> -	  <http://www.urbanmyth.org/microcode/>.
> +	  This option selects the general module only, you need to select
> +	  at least one vendor specific module as well.
>  
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called microcode.
>  
> -config MICROCODE_OLD_INTERFACE
> +config MICROCODE_INTEL
> +       tristate "Intel microcode patch loading support"
> +       depends on MICROCODE

	default MICROCODE

so that users doing make oldconfig don't get a surprise?

> +       select FW_LOADER
> +       --help---
> +         This options enables microcode patch loading support for Intel
> +         processors.
> +
> +         For latest news and information on obtaining all the required
> +         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_OLD_INTERFACE

Kill the extra spaces.


Daniel K.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [patch 0/9] x86: AMD microcode patch loading support
  2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
                   ` (9 preceding siblings ...)
  2008-07-25 16:44 ` [PATCH] x86: Add entry to MAINTAINERS file Peter Oruba
@ 2008-07-26 13:37 ` Ingo Molnar
  10 siblings, 0 replies; 14+ messages in thread
From: Ingo Molnar @ 2008-07-26 13:37 UTC (permalink / raw)
  To: Peter Oruba; +Cc: Thomas Gleixner, Tigran Aivazian, LKML


* Peter Oruba <peter.oruba@amd.com> wrote:

> This patch set introduces microcode patch loading support for AMD 
> processors. It includes refactoring of existing code to allow code 
> sharing. Vendor specific code has been split off, leading to a 
> multi-module solution as compared to the current single-module 
> approach.

patch #4 does not apply anymore to latest -git:

 patching file arch/x86/kernel/microcode.c
 Hunk #2 FAILED at 143.
 Hunk #3 FAILED at 229.
 Hunk #4 FAILED at 248.
 3 out of 4 hunks FAILED -- rejects in file arch/x86/kernel/microcode.c

could you please resend?

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-07-26 13:38 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-25 16:17 [patch 0/9] x86: AMD microcode patch loading support Peter Oruba
2008-07-25 16:17 ` [patch 1/9] [PATCH 1/9] x86: Moved Intel microcode patch loader declarations to seperate header file Peter Oruba
2008-07-25 16:17 ` [patch 2/9] [PATCH 2/9] x86: Typedef removal Peter Oruba
2008-07-25 16:17 ` [patch 3/9] [PATCH 3/9] x86: Moved per CPU microcode structure declaration to header file Peter Oruba
2008-07-25 16:17 ` [patch 4/9] [PATCH 4/9] x86: Code split to two parts Peter Oruba
2008-07-25 16:17 ` [patch 5/9] [PATCH 5/9] x86: Structure declaration renaming Peter Oruba
2008-07-25 16:17 ` [patch 6/9] [PATCH 6/9] x86: Add AMD specific declarations Peter Oruba
2008-07-25 16:17 ` [patch 7/9] [PATCH 7/9] x86: First step of refactoring, introducing microcode_ops Peter Oruba
2008-07-25 16:17 ` [patch 8/9] [PATCH 8/9] x86: Major refactoring Peter Oruba
2008-07-26  9:11   ` Daniel K.
2008-07-25 16:17 ` [patch 9/9] [PATCH 9/9] x86: AMD microcode patch loading support Peter Oruba
2008-07-26  8:00   ` Rabin Vincent
2008-07-25 16:44 ` [PATCH] x86: Add entry to MAINTAINERS file Peter Oruba
2008-07-26 13:37 ` [patch 0/9] x86: AMD microcode patch loading support Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).