Update to 2.6.32.39 Mainline
/arch/x86/kernel/microcode_amd.c
blob:f4c538b681cad13734aae36da2fdcda167fbdf67 -> blob:1e47679de3afedd50dc2d9b668c50dd1d65a9140
--- arch/x86/kernel/microcode_amd.c
+++ arch/x86/kernel/microcode_amd.c
@@ -63,7 +63,6 @@ struct microcode_amd {
unsigned int mpb[0];
};
-#define UCODE_MAX_SIZE 2048
#define UCODE_CONTAINER_SECTION_HDR 8
#define UCODE_CONTAINER_HEADER_SIZE 12
@@ -109,12 +108,8 @@ static int get_matching_microcode(int cp
return 0;
}
- if (mc_header->processor_rev_id != equiv_cpu_id) {
- printk(KERN_ERR "microcode: CPU%d: patch mismatch "
- "(processor_rev_id: %x, equiv_cpu_id: %x)\n",
- cpu, mc_header->processor_rev_id, equiv_cpu_id);
+ if (mc_header->processor_rev_id != equiv_cpu_id)
return 0;
- }
/* ucode might be chipset specific -- currently we don't support this */
if (mc_header->nb_dev_id || mc_header->sb_dev_id) {
@@ -129,6 +124,37 @@ static int get_matching_microcode(int cp
return 1;
}
+static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
+{
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+ unsigned int max_size, actual_size;
+
+#define F1XH_MPB_MAX_SIZE 2048
+#define F14H_MPB_MAX_SIZE 1824
+#define F15H_MPB_MAX_SIZE 4096
+
+ switch (c->x86) {
+ case 0x14:
+ max_size = F14H_MPB_MAX_SIZE;
+ break;
+ case 0x15:
+ max_size = F15H_MPB_MAX_SIZE;
+ break;
+ default:
+ max_size = F1XH_MPB_MAX_SIZE;
+ break;
+ }
+
+ actual_size = buf[4] + (buf[5] << 8);
+
+ if (actual_size > size || actual_size > max_size) {
+ pr_err("section size mismatch\n");
+ return 0;
+ }
+
+ return actual_size;
+}
+
static int apply_microcode_amd(int cpu)
{
u32 rev, dummy;
@@ -168,11 +194,11 @@ static int get_ucode_data(void *to, cons
}
static void *
-get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
+get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
{
- unsigned int total_size;
+ unsigned int actual_size = 0;
u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
- void *mc;
+ void *mc = NULL;
if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR))
return NULL;
@@ -183,26 +209,18 @@ get_next_ucode(const u8 *buf, unsigned i
return NULL;
}
- total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8));
-
- printk(KERN_DEBUG "microcode: size %u, total_size %u\n",
- size, total_size);
+ actual_size = verify_ucode_size(cpu, buf, size);
+ if (!actual_size)
+ return NULL;
- if (total_size > size || total_size > UCODE_MAX_SIZE) {
- printk(KERN_ERR "microcode: error: size mismatch\n");
+ mc = vmalloc(actual_size);
+ if (!mc)
return NULL;
- }
- mc = vmalloc(UCODE_MAX_SIZE);
- if (mc) {
- memset(mc, 0, UCODE_MAX_SIZE);
- if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR,
- total_size)) {
- vfree(mc);
- mc = NULL;
- } else
- *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
- }
+ memset(mc, 0, actual_size);
+ get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
+ *mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
+
return mc;
}
@@ -271,7 +289,7 @@ generic_load_microcode(int cpu, const u8
unsigned int uninitialized_var(mc_size);
struct microcode_header_amd *mc_header;
- mc = get_next_ucode(ucode_ptr, leftover, &mc_size);
+ mc = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
if (!mc)
break;