Re: [U-Boot] [PATCH 32/39] x86: ivybridge: Perform Intel microcode update on boot
Hi Bin, On 9 November 2014 19:54, Bin Meng bmeng...@gmail.com wrote: Hi Simon, On Fri, Nov 7, 2014 at 4:20 AM, Simon Glass s...@chromium.org wrote: Microcode updates are stored in the device tree. Work through these and apply any that are needed. Signed-off-by: Simon Glass s...@chromium.org --- arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/cpu.c| 5 + arch/x86/cpu/ivybridge/microcode_intel.c| 150 arch/x86/include/asm/arch-ivybridge/microcode.h | 20 include/fdtdec.h| 1 + lib/fdtdec.c| 1 + 6 files changed, 178 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/microcode_intel.c create mode 100644 arch/x86/include/asm/arch-ivybridge/microcode.h diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index ce16697..a3ea566 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,4 +7,5 @@ obj-y += car.o obj-y += cpu.o obj-y += lpc.o +obj-y += microcode_intel.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index e73ccb7..bd2660f 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -19,6 +19,7 @@ #include asm/post.h #include asm/processor.h #include asm/arch/model_206ax.h +#include asm/arch/microcode.h #include asm/arch/pch.h DECLARE_GLOBAL_DATA_PTR; @@ -198,6 +199,10 @@ int print_cpuinfo(void) if (ret) return ret; + ret = microcode_update_intel(); + if (ret ret != -ENOENT ret != -EEXIST) + return ret; + /* Print processor name */ name = cpu_get_name(processor_name); printf(CPU: %s\n, name); diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c new file mode 100644 index 000..fbb55f2 --- /dev/null +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014 Google, Inc + * Copyright (C) 2000 Ronald G. Minnich + * + * Microcode update for Intel PIII and later CPUs This comment suggests that the code is generic for all Intel CPUs, so should we move this code to arch/x86/lib? Actually I think a lot of code is in that category, or at least I fervently hope so! We may end up with an 'intel-common' directory, I'm not sure. But I'd rather leave common discussions until we know things are common. Regards, Simon ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 32/39] x86: ivybridge: Perform Intel microcode update on boot
Hi Simon, On Fri, Nov 7, 2014 at 4:20 AM, Simon Glass s...@chromium.org wrote: Microcode updates are stored in the device tree. Work through these and apply any that are needed. Signed-off-by: Simon Glass s...@chromium.org --- arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/cpu.c| 5 + arch/x86/cpu/ivybridge/microcode_intel.c| 150 arch/x86/include/asm/arch-ivybridge/microcode.h | 20 include/fdtdec.h| 1 + lib/fdtdec.c| 1 + 6 files changed, 178 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/microcode_intel.c create mode 100644 arch/x86/include/asm/arch-ivybridge/microcode.h diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index ce16697..a3ea566 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,4 +7,5 @@ obj-y += car.o obj-y += cpu.o obj-y += lpc.o +obj-y += microcode_intel.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index e73ccb7..bd2660f 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -19,6 +19,7 @@ #include asm/post.h #include asm/processor.h #include asm/arch/model_206ax.h +#include asm/arch/microcode.h #include asm/arch/pch.h DECLARE_GLOBAL_DATA_PTR; @@ -198,6 +199,10 @@ int print_cpuinfo(void) if (ret) return ret; + ret = microcode_update_intel(); + if (ret ret != -ENOENT ret != -EEXIST) + return ret; + /* Print processor name */ name = cpu_get_name(processor_name); printf(CPU: %s\n, name); diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c new file mode 100644 index 000..fbb55f2 --- /dev/null +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014 Google, Inc + * Copyright (C) 2000 Ronald G. Minnich + * + * Microcode update for Intel PIII and later CPUs This comment suggests that the code is generic for all Intel CPUs, so should we move this code to arch/x86/lib? [snip] Regards, Bin ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
[U-Boot] [PATCH 32/39] x86: ivybridge: Perform Intel microcode update on boot
Microcode updates are stored in the device tree. Work through these and apply any that are needed. Signed-off-by: Simon Glass s...@chromium.org --- arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/cpu.c| 5 + arch/x86/cpu/ivybridge/microcode_intel.c| 150 arch/x86/include/asm/arch-ivybridge/microcode.h | 20 include/fdtdec.h| 1 + lib/fdtdec.c| 1 + 6 files changed, 178 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/microcode_intel.c create mode 100644 arch/x86/include/asm/arch-ivybridge/microcode.h diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index ce16697..a3ea566 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,4 +7,5 @@ obj-y += car.o obj-y += cpu.o obj-y += lpc.o +obj-y += microcode_intel.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index e73ccb7..bd2660f 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -19,6 +19,7 @@ #include asm/post.h #include asm/processor.h #include asm/arch/model_206ax.h +#include asm/arch/microcode.h #include asm/arch/pch.h DECLARE_GLOBAL_DATA_PTR; @@ -198,6 +199,10 @@ int print_cpuinfo(void) if (ret) return ret; + ret = microcode_update_intel(); + if (ret ret != -ENOENT ret != -EEXIST) + return ret; + /* Print processor name */ name = cpu_get_name(processor_name); printf(CPU: %s\n, name); diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c new file mode 100644 index 000..fbb55f2 --- /dev/null +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014 Google, Inc + * Copyright (C) 2000 Ronald G. Minnich + * + * Microcode update for Intel PIII and later CPUs + * + * SPDX-License-Identifier:GPL-2.0 + */ + +#include common.h +#include errno.h +#include fdtdec.h +#include libfdt.h +#include asm/msr.h +#include asm/processor.h + +/** + * struct microcode_update - standard microcode header from Intel + * + * We read this information out of the device tree and use it to determine + * whether the update is applicable or not. We also use the same structure + * to read information from the CPU. + */ +struct microcode_update { + uint header_version; + uint update_revision; + uint date_code; + uint processor_signature; + uint checksum; + uint loader_revision; + uint processor_flags; + const void *data; + int size; +}; + +static int microcode_decode_node(const void *blob, int node, +struct microcode_update *update) +{ + update-data = fdt_getprop(blob, node, data, update-size); + if (!update-data) + return -EINVAL; + + update-header_version = fdtdec_get_int(blob, node, + intel,header-version, 0); + update-update_revision = fdtdec_get_int(blob, node, +intel,update-revision, 0); + update-date_code = fdtdec_get_int(blob, node, + intel,date-code, 0); + update-processor_signature = fdtdec_get_int(blob, node, + intel.processor-signature, 0); + update-checksum = fdtdec_get_int(blob, node, intel,checksum, 0); + update-loader_revision = fdtdec_get_int(blob, node, +loader-revision, 0); + update-processor_flags = fdtdec_get_int(blob, node, +processor-flags, 0); + + return 0; +} + +static uint32_t microcode_read_rev(void) +{ + /* +* Some Intel CPUs can be very finicky about the CPUID sequence used. +* So this is implemented in assembly so that it works reliably. +*/ + uint32_t low, high; + + asm volatile ( + xorl %%eax, %%eax\n + xorl %%edx, %%edx\n + movl $0x8b, %%ecx\n + wrmsr\n + movl $0x01, %%eax\n + cpuid\n + movl $0x8b, %%ecx\n + rdmsr\n + : /* outputs */ + =a (low), =d (high) + : /* inputs */ + : /* clobbers */ +ebx, ecx + ); + + return high; +} + +static void microcode_read_cpu(struct microcode_update *cpu) +{ + /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ + unsigned int x86_model, x86_family; + struct cpuid_result result; + uint32_t low, high; + + wrmsr(0x8b, 0, 0); + result = cpuid(1); + rdmsr(0x8b, low, cpu-update_revision); + x86_model = (result.eax 4) 0x0f; +