diff options
author | Simon Glass <sjg@chromium.org> | 2015-01-01 23:18:14 (GMT) |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2015-01-13 15:25:02 (GMT) |
commit | c72f74e2780350f16795dc4d69145b9c87cb3e97 (patch) | |
tree | 7a9b2cfce7be84f60e9e692049983a1c506da819 /arch/x86/cpu/ivybridge/microcode_intel.c | |
parent | 801d70ce026be4595e595fb6790621a6a898cee9 (diff) | |
download | u-boot-c72f74e2780350f16795dc4d69145b9c87cb3e97.tar.xz |
x86: ivybridge: Update microcode early in boot
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>
Diffstat (limited to 'arch/x86/cpu/ivybridge/microcode_intel.c')
-rw-r--r-- | arch/x86/cpu/ivybridge/microcode_intel.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c index 0817751..2440a97 100644 --- a/arch/x86/cpu/ivybridge/microcode_intel.c +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -13,7 +13,9 @@ #include <libfdt.h> #include <asm/cpu.h> #include <asm/msr.h> +#include <asm/msr-index.h> #include <asm/processor.h> +#include <asm/arch/microcode.h> /** * struct microcode_update - standard microcode header from Intel @@ -40,8 +42,8 @@ static int microcode_decode_node(const void *blob, int node, 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); @@ -71,15 +73,16 @@ static inline uint32_t microcode_read_rev(void) asm volatile ( "xorl %%eax, %%eax\n" "xorl %%edx, %%edx\n" - "movl $0x8b, %%ecx\n" + "movl %2, %%ecx\n" "wrmsr\n" "movl $0x01, %%eax\n" "cpuid\n" - "movl $0x8b, %%ecx\n" + "movl %2, %%ecx\n" "rdmsr\n" : /* outputs */ "=a" (low), "=d" (high) : /* inputs */ + "i" (MSR_IA32_UCODE_REV) : /* clobbers */ "ebx", "ecx" ); @@ -94,9 +97,9 @@ static void microcode_read_cpu(struct microcode_update *cpu) struct cpuid_result result; uint32_t low, high; - wrmsr(0x8b, 0, 0); + wrmsr(MSR_IA32_UCODE_REV, 0, 0); result = cpuid(1); - 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; @@ -120,6 +123,7 @@ int microcode_update_intel(void) int count; int node; int ret; + int rev; microcode_read_cpu(&cpu); node = 0; @@ -147,12 +151,16 @@ int microcode_update_intel(void) skipped++; continue; } - 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", - microcode_read_rev(), update.date_code & 0xffff, + rev, update.date_code & 0xffff, (update.date_code >> 24) & 0xff, (update.date_code >> 16) & 0xff); + if (update.update_revision != rev) { + printf("Microcode update failed\n"); + return -EFAULT; + } count++; } while (1); } |