At present the normal update (which happens much later) does not work. This
seems to have something to do with the 'no eviction' mode in the CAR, or at
least moving the microcode update after that causes it not to work.
For now, do an update early on so that it definitely works. Also refuse to
continue unless the microcode update check (later in boot) is successful.
Signed-off-by: Simon Glass <sjg@chromium.org>
+#include <asm/msr-index.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor-flags.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor-flags.h>
+#include <asm/arch/microcode.h>
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
movl $0xFEE00300, %esi
movl %eax, (%esi)
movl $0xFEE00300, %esi
movl %eax, (%esi)
+ /* TODO: Load microcode later - the 'no eviction' mode breaks this */
+ movl $MSR_IA32_UCODE_WRITE, %ecx
+ xorl %edx, %edx
+ movl $_dt_ucode_base_size, %eax
+ movl (%eax), %eax
+ addl $UCODE_HEADER_LEN, %eax
+ wrmsr
+
post_code(POST_CAR_SIPI)
/* Zero out all fixed range and variable range MTRRs */
movl $mtrr_table, %esi
post_code(POST_CAR_SIPI)
/* Zero out all fixed range and variable range MTRRs */
movl $mtrr_table, %esi
.word 0x20C, 0x20D, 0x20E, 0x20F
.word 0x210, 0x211, 0x212, 0x213
mtrr_table_end:
.word 0x20C, 0x20D, 0x20E, 0x20F
.word 0x210, 0x211, 0x212, 0x213
mtrr_table_end:
+
+ .align 4
+_dt_ucode_base_size:
+ /* These next two fields are filled in by ifdtool */
+ .long 0 /* microcode base */
+ .long 0 /* microcode size */
enable_lapic();
ret = microcode_update_intel();
enable_lapic();
ret = microcode_update_intel();
- if (ret && ret != -ENOENT && ret != -EEXIST)
return ret;
/* Enable upper 128bytes of CMOS */
return ret;
/* Enable upper 128bytes of CMOS */
#include <libfdt.h>
#include <asm/cpu.h>
#include <asm/msr.h>
#include <libfdt.h>
#include <asm/cpu.h>
#include <asm/msr.h>
+#include <asm/msr-index.h>
#include <asm/processor.h>
#include <asm/processor.h>
+#include <asm/arch/microcode.h>
/**
* struct microcode_update - standard microcode header from Intel
/**
* struct microcode_update - standard microcode header from Intel
update->data = fdt_getprop(blob, node, "data", &update->size);
if (!update->data)
return -EINVAL;
update->data = fdt_getprop(blob, node, "data", &update->size);
if (!update->data)
return -EINVAL;
- update->data += 48;
- update->size -= 48;
+ update->data += UCODE_HEADER_LEN;
+ update->size -= UCODE_HEADER_LEN;
update->header_version = fdtdec_get_int(blob, node,
"intel,header-version", 0);
update->header_version = fdtdec_get_int(blob, node,
"intel,header-version", 0);
asm volatile (
"xorl %%eax, %%eax\n"
"xorl %%edx, %%edx\n"
asm volatile (
"xorl %%eax, %%eax\n"
"xorl %%edx, %%edx\n"
"wrmsr\n"
"movl $0x01, %%eax\n"
"cpuid\n"
"wrmsr\n"
"movl $0x01, %%eax\n"
"cpuid\n"
"rdmsr\n"
: /* outputs */
"=a" (low), "=d" (high)
: /* inputs */
"rdmsr\n"
: /* outputs */
"=a" (low), "=d" (high)
: /* inputs */
+ "i" (MSR_IA32_UCODE_REV)
: /* clobbers */
"ebx", "ecx"
);
: /* clobbers */
"ebx", "ecx"
);
struct cpuid_result result;
uint32_t low, high;
struct cpuid_result result;
uint32_t low, high;
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
- rdmsr(0x8b, low, cpu->update_revision);
+ rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision);
x86_model = (result.eax >> 4) & 0x0f;
x86_family = (result.eax >> 8) & 0x0f;
cpu->processor_signature = result.eax;
x86_model = (result.eax >> 4) & 0x0f;
x86_family = (result.eax >> 8) & 0x0f;
cpu->processor_signature = result.eax;
int count;
int node;
int ret;
int count;
int node;
int ret;
microcode_read_cpu(&cpu);
node = 0;
microcode_read_cpu(&cpu);
node = 0;
- ret = microcode_read_rev();
- wrmsr(0x79, (ulong)update.data, 0);
+ wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0);
+ rev = microcode_read_rev();
debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
- microcode_read_rev(), update.date_code & 0xffff,
+ rev, update.date_code & 0xffff,
(update.date_code >> 24) & 0xff,
(update.date_code >> 16) & 0xff);
(update.date_code >> 24) & 0xff,
(update.date_code >> 16) & 0xff);
+ if (update.update_revision != rev) {
+ printf("Microcode update failed\n");
+ return -EFAULT;
+ }
-#include "microcode/m12206a7_00000029.dtsi"
- };
- update@1 {
#include "microcode/m12306a9_0000001b.dtsi"
};
};
#include "microcode/m12306a9_0000001b.dtsi"
};
};
#ifndef __ASM_ARCH_MICROCODE_H
#define __ASM_ARCH_MICROCODE_H
#ifndef __ASM_ARCH_MICROCODE_H
#define __ASM_ARCH_MICROCODE_H
+/* Length of the public header on Intel microcode blobs */
+#define UCODE_HEADER_LEN 0x30
+
+#ifndef __ASSEMBLY__
+
/**
* microcode_update_intel() - Apply microcode updates
*
/**
* microcode_update_intel() - Apply microcode updates
*
* not updates were found, -EINVAL if an update was invalid
*/
int microcode_update_intel(void);
* not updates were found, -EINVAL if an update was invalid
*/
int microcode_update_intel(void);
+#endif /* __ASSEMBLY__ */