From: Fenghua Yu <fenghua...@intel.com> Define interfaces load_ucode_bsp() and load_ucode_ap() to load ucode on BSP and AP in early boot time. These are generic interfaces. Internally they call vendor specific implementations.
Signed-off-by: Fenghua Yu <fenghua...@intel.com> --- arch/x86/include/asm/microcode.h | 23 ++++++++++ arch/x86/kernel/microcode_core_early.c | 74 ++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 0 deletions(-) create mode 100644 arch/x86/kernel/microcode_core_early.c diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 4ebe157..080ea77 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -63,4 +63,27 @@ static inline struct microcode_ops * __init init_amd_microcode(void) static inline void __exit exit_amd_microcode(void) {} #endif +struct mc_saved_data { + unsigned int mc_saved_count; + struct microcode_intel **mc_saved; + struct ucode_cpu_info *ucode_cpu_info; +}; +#ifdef CONFIG_MICROCODE_EARLY +#define MAX_UCODE_COUNT 128 +extern struct ucode_cpu_info ucode_cpu_info_early[NR_CPUS]; +extern struct microcode_intel __initdata *mc_saved_in_initrd[MAX_UCODE_COUNT]; +extern struct mc_saved_data mc_saved_data; +extern void __init load_ucode_bsp(char *real_mode_data); +extern __init void load_ucode_ap(void); +extern void __init +save_microcode_in_initrd(struct mc_saved_data *mc_saved_data, + struct microcode_intel **mc_saved_in_initrd); +#else +static inline void __init load_ucode_bsp(char *real_mode_data) {} +static inline __init void load_ucode_ap(void) {} +static inline void __init +save_microcode_in_initrd(struct mc_saved_data *mc_saved_data, + struct microcode_intel **mc_saved_in_initrd) {} +#endif + #endif /* _ASM_X86_MICROCODE_H */ diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c new file mode 100644 index 0000000..5bcc6f8 --- /dev/null +++ b/arch/x86/kernel/microcode_core_early.c @@ -0,0 +1,74 @@ +/* + * X86 CPU microcode early update for Linux + * + * Copyright (C) 2012 Fenghua Yu <fenghua...@intel.com> + * H Peter Anvin" <h...@zytor.com> + * + * This driver allows to early upgrade microcode on Intel processors + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. + * + * Reference: Section 9.11 of Volume 3, IA-32 Intel Architecture + * Software Developer's Manual. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/module.h> +#include <linux/mm.h> +#include <asm/microcode_intel.h> +#include <asm/processor.h> +#include <asm/cpio.h> + +struct ucode_cpu_info ucode_cpu_info_early[NR_CPUS]; +EXPORT_SYMBOL_GPL(ucode_cpu_info_early); + +static __init enum ucode_state +find_ucode_intel(unsigned long start, unsigned long end) +{ + unsigned int size = end - start + 1; + struct cpio_data cd = { 0, 0 }; + char ucode_name[] = "kernel/x86/microcode/GenuineIntel/microcode.hex"; + + cd = find_cpio_data(ucode_name, (void *)start, size); + if (cd.data) + return UCODE_OK; + + return UCODE_ERROR; +} + +void __init load_ucode_bsp(char *real_mode_data) +{ + u64 ramdisk_image, ramdisk_size, ramdisk_end; + unsigned long initrd_start, initrd_end; + struct boot_params *boot_params; + + boot_params = (struct boot_params *)real_mode_data; + ramdisk_image = boot_params->hdr.ramdisk_image; + ramdisk_size = boot_params->hdr.ramdisk_size; + +#ifdef CONFIG_X86_64 + ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); + initrd_start = ramdisk_image + PAGE_OFFSET; +#else + ramdisk_end = ramdisk_image + ramdisk_size; + initrd_start = ramdisk_image; +#endif + initrd_end = initrd_start + ramdisk_size; + + /* + * It's early to get CPU vendor info at this point. + * By searching initrd to find right name for vendor's microcode, + * it's relative easier to get CPU vendor info. + */ + if (find_ucode_intel(initrd_start, initrd_end) == UCODE_OK) + load_ucode_intel_bsp(real_mode_data); +} + +void __cpuinit load_ucode_ap(void) +{ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) + load_ucode_intel_ap(); +} -- 1.7.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/