diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/cpu/ivybridge/car.S | 16 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/cpu.c | 2 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/microcode_intel.c | 26 | ||||
-rw-r--r-- | arch/x86/dts/link.dts | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/arch-ivybridge/microcode.h | 6 |
5 files changed, 40 insertions, 13 deletions
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index d5f1acfe3d..9441666f5a 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -12,9 +12,11 @@ */ #include <common.h> +#include <asm/msr-index.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) @@ -45,6 +47,14 @@ car_init: 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 @@ -222,3 +232,9 @@ mtrr_table: .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 */ diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 0543e06aef..e9253100f6 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -263,7 +263,7 @@ int print_cpuinfo(void) enable_lapic(); ret = microcode_update_intel(); - if (ret && ret != -ENOENT && ret != -EEXIST) + if (ret) return ret; /* Enable upper 128bytes of CMOS */ diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c index 08177510ab..2440a97c48 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); } diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 107af60004..9490b169fb 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -209,9 +209,6 @@ microcode { update@0 { -#include "microcode/m12206a7_00000029.dtsi" - }; - update@1 { #include "microcode/m12306a9_0000001b.dtsi" }; }; diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h index bc9b87c44c..b868283761 100644 --- a/arch/x86/include/asm/arch-ivybridge/microcode.h +++ b/arch/x86/include/asm/arch-ivybridge/microcode.h @@ -7,6 +7,11 @@ #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 * @@ -16,5 +21,6 @@ * not updates were found, -EINVAL if an update was invalid */ int microcode_update_intel(void); +#endif /* __ASSEMBLY__ */ #endif |