diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-19 12:18:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-19 12:18:29 -0400 |
| commit | 7067552dfb382cef040326ab6dd0b8d642af3e64 (patch) | |
| tree | f09ff2a949007da4a976e37cbad43490a0904f81 | |
| parent | e91dade52b590d821e83bb494df20c93e5384790 (diff) | |
| parent | ccb1f55e710b78e1ea1de769bcab2d1e1abe8457 (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
"Two AMD microcode loader fixes and an OLPC firmware support fix"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, microcode, AMD: Fix early microcode loading
x86, microcode, AMD: Make cpu_has_amd_erratum() use the correct struct cpuinfo_x86
x86: Don't clear olpc_ofw_header when sentinel is detected
| -rw-r--r-- | arch/x86/include/asm/bootparam_utils.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/microcode_amd.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 20 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_amd.c | 27 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_amd_early.c | 27 |
5 files changed, 34 insertions, 46 deletions
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h index 653668d140f9..4a8cb8d7cbd5 100644 --- a/arch/x86/include/asm/bootparam_utils.h +++ b/arch/x86/include/asm/bootparam_utils.h | |||
| @@ -35,9 +35,9 @@ static void sanitize_boot_params(struct boot_params *boot_params) | |||
| 35 | */ | 35 | */ |
| 36 | if (boot_params->sentinel) { | 36 | if (boot_params->sentinel) { |
| 37 | /* fields in boot_params are left uninitialized, clear them */ | 37 | /* fields in boot_params are left uninitialized, clear them */ |
| 38 | memset(&boot_params->olpc_ofw_header, 0, | 38 | memset(&boot_params->ext_ramdisk_image, 0, |
| 39 | (char *)&boot_params->efi_info - | 39 | (char *)&boot_params->efi_info - |
| 40 | (char *)&boot_params->olpc_ofw_header); | 40 | (char *)&boot_params->ext_ramdisk_image); |
| 41 | memset(&boot_params->kbd_status, 0, | 41 | memset(&boot_params->kbd_status, 0, |
| 42 | (char *)&boot_params->hdr - | 42 | (char *)&boot_params->hdr - |
| 43 | (char *)&boot_params->kbd_status); | 43 | (char *)&boot_params->kbd_status); |
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index 50e5c58ced23..4c019179a57d 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h | |||
| @@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table, | |||
| 59 | 59 | ||
| 60 | extern int __apply_microcode_amd(struct microcode_amd *mc_amd); | 60 | extern int __apply_microcode_amd(struct microcode_amd *mc_amd); |
| 61 | extern int apply_microcode_amd(int cpu); | 61 | extern int apply_microcode_amd(int cpu); |
| 62 | extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size); | 62 | extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); |
| 63 | 63 | ||
| 64 | #ifdef CONFIG_MICROCODE_AMD_EARLY | 64 | #ifdef CONFIG_MICROCODE_AMD_EARLY |
| 65 | #ifdef CONFIG_X86_32 | 65 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index f654ecefea5b..08a089043ccf 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
| @@ -512,7 +512,7 @@ static void early_init_amd(struct cpuinfo_x86 *c) | |||
| 512 | 512 | ||
| 513 | static const int amd_erratum_383[]; | 513 | static const int amd_erratum_383[]; |
| 514 | static const int amd_erratum_400[]; | 514 | static const int amd_erratum_400[]; |
| 515 | static bool cpu_has_amd_erratum(const int *erratum); | 515 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum); |
| 516 | 516 | ||
| 517 | static void init_amd(struct cpuinfo_x86 *c) | 517 | static void init_amd(struct cpuinfo_x86 *c) |
| 518 | { | 518 | { |
| @@ -729,11 +729,11 @@ static void init_amd(struct cpuinfo_x86 *c) | |||
| 729 | value &= ~(1ULL << 24); | 729 | value &= ~(1ULL << 24); |
| 730 | wrmsrl_safe(MSR_AMD64_BU_CFG2, value); | 730 | wrmsrl_safe(MSR_AMD64_BU_CFG2, value); |
| 731 | 731 | ||
| 732 | if (cpu_has_amd_erratum(amd_erratum_383)) | 732 | if (cpu_has_amd_erratum(c, amd_erratum_383)) |
| 733 | set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH); | 733 | set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH); |
| 734 | } | 734 | } |
| 735 | 735 | ||
| 736 | if (cpu_has_amd_erratum(amd_erratum_400)) | 736 | if (cpu_has_amd_erratum(c, amd_erratum_400)) |
| 737 | set_cpu_bug(c, X86_BUG_AMD_APIC_C1E); | 737 | set_cpu_bug(c, X86_BUG_AMD_APIC_C1E); |
| 738 | 738 | ||
| 739 | rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); | 739 | rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); |
| @@ -878,23 +878,13 @@ static const int amd_erratum_400[] = | |||
| 878 | static const int amd_erratum_383[] = | 878 | static const int amd_erratum_383[] = |
| 879 | AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); | 879 | AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf)); |
| 880 | 880 | ||
| 881 | static bool cpu_has_amd_erratum(const int *erratum) | 881 | |
| 882 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) | ||
| 882 | { | 883 | { |
| 883 | struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info); | ||
| 884 | int osvw_id = *erratum++; | 884 | int osvw_id = *erratum++; |
| 885 | u32 range; | 885 | u32 range; |
| 886 | u32 ms; | 886 | u32 ms; |
| 887 | 887 | ||
| 888 | /* | ||
| 889 | * If called early enough that current_cpu_data hasn't been initialized | ||
| 890 | * yet, fall back to boot_cpu_data. | ||
| 891 | */ | ||
| 892 | if (cpu->x86 == 0) | ||
| 893 | cpu = &boot_cpu_data; | ||
| 894 | |||
| 895 | if (cpu->x86_vendor != X86_VENDOR_AMD) | ||
| 896 | return false; | ||
| 897 | |||
| 898 | if (osvw_id >= 0 && osvw_id < 65536 && | 888 | if (osvw_id >= 0 && osvw_id < 65536 && |
| 899 | cpu_has(cpu, X86_FEATURE_OSVW)) { | 889 | cpu_has(cpu, X86_FEATURE_OSVW)) { |
| 900 | u64 osvw_len; | 890 | u64 osvw_len; |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 7a0adb7ee433..7123b5df479d 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
| @@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | |||
| 145 | return 0; | 145 | return 0; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static unsigned int verify_patch_size(int cpu, u32 patch_size, | 148 | static unsigned int verify_patch_size(u8 family, u32 patch_size, |
| 149 | unsigned int size) | 149 | unsigned int size) |
| 150 | { | 150 | { |
| 151 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 152 | u32 max_size; | 151 | u32 max_size; |
| 153 | 152 | ||
| 154 | #define F1XH_MPB_MAX_SIZE 2048 | 153 | #define F1XH_MPB_MAX_SIZE 2048 |
| @@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, | |||
| 156 | #define F15H_MPB_MAX_SIZE 4096 | 155 | #define F15H_MPB_MAX_SIZE 4096 |
| 157 | #define F16H_MPB_MAX_SIZE 3458 | 156 | #define F16H_MPB_MAX_SIZE 3458 |
| 158 | 157 | ||
| 159 | switch (c->x86) { | 158 | switch (family) { |
| 160 | case 0x14: | 159 | case 0x14: |
| 161 | max_size = F14H_MPB_MAX_SIZE; | 160 | max_size = F14H_MPB_MAX_SIZE; |
| 162 | break; | 161 | break; |
| @@ -277,9 +276,8 @@ static void cleanup(void) | |||
| 277 | * driver cannot continue functioning normally. In such cases, we tear | 276 | * driver cannot continue functioning normally. In such cases, we tear |
| 278 | * down everything we've used up so far and exit. | 277 | * down everything we've used up so far and exit. |
| 279 | */ | 278 | */ |
| 280 | static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) | 279 | static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover) |
| 281 | { | 280 | { |
| 282 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
| 283 | struct microcode_header_amd *mc_hdr; | 281 | struct microcode_header_amd *mc_hdr; |
| 284 | struct ucode_patch *patch; | 282 | struct ucode_patch *patch; |
| 285 | unsigned int patch_size, crnt_size, ret; | 283 | unsigned int patch_size, crnt_size, ret; |
| @@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) | |||
| 299 | 297 | ||
| 300 | /* check if patch is for the current family */ | 298 | /* check if patch is for the current family */ |
| 301 | proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); | 299 | proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); |
| 302 | if (proc_fam != c->x86) | 300 | if (proc_fam != family) |
| 303 | return crnt_size; | 301 | return crnt_size; |
| 304 | 302 | ||
| 305 | if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { | 303 | if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { |
| @@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) | |||
| 308 | return crnt_size; | 306 | return crnt_size; |
| 309 | } | 307 | } |
| 310 | 308 | ||
| 311 | ret = verify_patch_size(cpu, patch_size, leftover); | 309 | ret = verify_patch_size(family, patch_size, leftover); |
| 312 | if (!ret) { | 310 | if (!ret) { |
| 313 | pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); | 311 | pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); |
| 314 | return crnt_size; | 312 | return crnt_size; |
| @@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) | |||
| 339 | return crnt_size; | 337 | return crnt_size; |
| 340 | } | 338 | } |
| 341 | 339 | ||
| 342 | static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size) | 340 | static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, |
| 341 | size_t size) | ||
| 343 | { | 342 | { |
| 344 | enum ucode_state ret = UCODE_ERROR; | 343 | enum ucode_state ret = UCODE_ERROR; |
| 345 | unsigned int leftover; | 344 | unsigned int leftover; |
| @@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz | |||
| 362 | } | 361 | } |
| 363 | 362 | ||
| 364 | while (leftover) { | 363 | while (leftover) { |
| 365 | crnt_size = verify_and_add_patch(cpu, fw, leftover); | 364 | crnt_size = verify_and_add_patch(family, fw, leftover); |
| 366 | if (crnt_size < 0) | 365 | if (crnt_size < 0) |
| 367 | return ret; | 366 | return ret; |
| 368 | 367 | ||
| @@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz | |||
| 373 | return UCODE_OK; | 372 | return UCODE_OK; |
| 374 | } | 373 | } |
| 375 | 374 | ||
| 376 | enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) | 375 | enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) |
| 377 | { | 376 | { |
| 378 | enum ucode_state ret; | 377 | enum ucode_state ret; |
| 379 | 378 | ||
| 380 | /* free old equiv table */ | 379 | /* free old equiv table */ |
| 381 | free_equiv_cpu_table(); | 380 | free_equiv_cpu_table(); |
| 382 | 381 | ||
| 383 | ret = __load_microcode_amd(cpu, data, size); | 382 | ret = __load_microcode_amd(family, data, size); |
| 384 | 383 | ||
| 385 | if (ret != UCODE_OK) | 384 | if (ret != UCODE_OK) |
| 386 | cleanup(); | 385 | cleanup(); |
| 387 | 386 | ||
| 388 | #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32) | 387 | #if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32) |
| 389 | /* save BSP's matching patch for early load */ | 388 | /* save BSP's matching patch for early load */ |
| 390 | if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) { | 389 | if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) { |
| 391 | struct ucode_patch *p = find_patch(cpu); | 390 | struct ucode_patch *p = find_patch(smp_processor_id()); |
| 392 | if (p) { | 391 | if (p) { |
| 393 | memset(amd_bsp_mpb, 0, MPB_MAX_SIZE); | 392 | memset(amd_bsp_mpb, 0, MPB_MAX_SIZE); |
| 394 | memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data), | 393 | memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data), |
| @@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device, | |||
| 441 | goto fw_release; | 440 | goto fw_release; |
| 442 | } | 441 | } |
| 443 | 442 | ||
| 444 | ret = load_microcode_amd(cpu, fw->data, fw->size); | 443 | ret = load_microcode_amd(c->x86, fw->data, fw->size); |
| 445 | 444 | ||
| 446 | fw_release: | 445 | fw_release: |
| 447 | release_firmware(fw); | 446 | release_firmware(fw); |
diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c index 1d14ffee5749..6073104ccaa3 100644 --- a/arch/x86/kernel/microcode_amd_early.c +++ b/arch/x86/kernel/microcode_amd_early.c | |||
| @@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg) | |||
| 238 | uci->cpu_sig.sig = cpuid_eax(0x00000001); | 238 | uci->cpu_sig.sig = cpuid_eax(0x00000001); |
| 239 | } | 239 | } |
| 240 | #else | 240 | #else |
| 241 | static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c, | 241 | void load_ucode_amd_ap(void) |
| 242 | struct ucode_cpu_info *uci) | ||
| 243 | { | 242 | { |
| 243 | unsigned int cpu = smp_processor_id(); | ||
| 244 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
| 244 | u32 rev, eax; | 245 | u32 rev, eax; |
| 245 | 246 | ||
| 246 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | 247 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); |
| 247 | eax = cpuid_eax(0x00000001); | 248 | eax = cpuid_eax(0x00000001); |
| 248 | 249 | ||
| 249 | uci->cpu_sig.sig = eax; | ||
| 250 | uci->cpu_sig.rev = rev; | 250 | uci->cpu_sig.rev = rev; |
| 251 | c->microcode = rev; | 251 | uci->cpu_sig.sig = eax; |
| 252 | c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | ||
| 253 | } | ||
| 254 | |||
| 255 | void load_ucode_amd_ap(void) | ||
| 256 | { | ||
| 257 | unsigned int cpu = smp_processor_id(); | ||
| 258 | |||
| 259 | collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu); | ||
| 260 | 252 | ||
| 261 | if (cpu && !ucode_loaded) { | 253 | if (cpu && !ucode_loaded) { |
| 262 | void *ucode; | 254 | void *ucode; |
| @@ -265,8 +257,10 @@ void load_ucode_amd_ap(void) | |||
| 265 | return; | 257 | return; |
| 266 | 258 | ||
| 267 | ucode = (void *)(initrd_start + ucode_offset); | 259 | ucode = (void *)(initrd_start + ucode_offset); |
| 268 | if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK) | 260 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); |
| 261 | if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK) | ||
| 269 | return; | 262 | return; |
| 263 | |||
| 270 | ucode_loaded = true; | 264 | ucode_loaded = true; |
| 271 | } | 265 | } |
| 272 | 266 | ||
| @@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 278 | { | 272 | { |
| 279 | enum ucode_state ret; | 273 | enum ucode_state ret; |
| 280 | void *ucode; | 274 | void *ucode; |
| 275 | u32 eax; | ||
| 276 | |||
| 281 | #ifdef CONFIG_X86_32 | 277 | #ifdef CONFIG_X86_32 |
| 282 | unsigned int bsp = boot_cpu_data.cpu_index; | 278 | unsigned int bsp = boot_cpu_data.cpu_index; |
| 283 | struct ucode_cpu_info *uci = ucode_cpu_info + bsp; | 279 | struct ucode_cpu_info *uci = ucode_cpu_info + bsp; |
| @@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 293 | return 0; | 289 | return 0; |
| 294 | 290 | ||
| 295 | ucode = (void *)(initrd_start + ucode_offset); | 291 | ucode = (void *)(initrd_start + ucode_offset); |
| 296 | ret = load_microcode_amd(0, ucode, ucode_size); | 292 | eax = cpuid_eax(0x00000001); |
| 293 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | ||
| 294 | |||
| 295 | ret = load_microcode_amd(eax, ucode, ucode_size); | ||
| 297 | if (ret != UCODE_OK) | 296 | if (ret != UCODE_OK) |
| 298 | return -EINVAL; | 297 | return -EINVAL; |
| 299 | 298 | ||
