diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/cpu.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 47 |
3 files changed, 51 insertions, 15 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 922c5e0cea4c..fa95bb8829ce 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kgdb.h> | 13 | #include <linux/kgdb.h> |
14 | #include <linux/smp.h> | 14 | #include <linux/smp.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/syscore_ops.h> | ||
16 | 17 | ||
17 | #include <asm/stackprotector.h> | 18 | #include <asm/stackprotector.h> |
18 | #include <asm/perf_event.h> | 19 | #include <asm/perf_event.h> |
@@ -1488,3 +1489,20 @@ inline bool __static_cpu_has_safe(u16 bit) | |||
1488 | return boot_cpu_has(bit); | 1489 | return boot_cpu_has(bit); |
1489 | } | 1490 | } |
1490 | EXPORT_SYMBOL_GPL(__static_cpu_has_safe); | 1491 | EXPORT_SYMBOL_GPL(__static_cpu_has_safe); |
1492 | |||
1493 | static void bsp_resume(void) | ||
1494 | { | ||
1495 | if (this_cpu->c_bsp_resume) | ||
1496 | this_cpu->c_bsp_resume(&boot_cpu_data); | ||
1497 | } | ||
1498 | |||
1499 | static struct syscore_ops cpu_syscore_ops = { | ||
1500 | .resume = bsp_resume, | ||
1501 | }; | ||
1502 | |||
1503 | static int __init init_cpu_syscore(void) | ||
1504 | { | ||
1505 | register_syscore_ops(&cpu_syscore_ops); | ||
1506 | return 0; | ||
1507 | } | ||
1508 | core_initcall(init_cpu_syscore); | ||
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h index c37dc37e8317..2584265d4745 100644 --- a/arch/x86/kernel/cpu/cpu.h +++ b/arch/x86/kernel/cpu/cpu.h | |||
@@ -13,6 +13,7 @@ struct cpu_dev { | |||
13 | void (*c_init)(struct cpuinfo_x86 *); | 13 | void (*c_init)(struct cpuinfo_x86 *); |
14 | void (*c_identify)(struct cpuinfo_x86 *); | 14 | void (*c_identify)(struct cpuinfo_x86 *); |
15 | void (*c_detect_tlb)(struct cpuinfo_x86 *); | 15 | void (*c_detect_tlb)(struct cpuinfo_x86 *); |
16 | void (*c_bsp_resume)(struct cpuinfo_x86 *); | ||
16 | int c_x86_vendor; | 17 | int c_x86_vendor; |
17 | #ifdef CONFIG_X86_32 | 18 | #ifdef CONFIG_X86_32 |
18 | /* Optional vendor specific routine to obtain the cache size. */ | 19 | /* Optional vendor specific routine to obtain the cache size. */ |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 50163fa9034f..98a13db5f4be 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -371,6 +371,36 @@ static void detect_vmx_virtcap(struct cpuinfo_x86 *c) | |||
371 | } | 371 | } |
372 | } | 372 | } |
373 | 373 | ||
374 | static void init_intel_energy_perf(struct cpuinfo_x86 *c) | ||
375 | { | ||
376 | u64 epb; | ||
377 | |||
378 | /* | ||
379 | * Initialize MSR_IA32_ENERGY_PERF_BIAS if not already initialized. | ||
380 | * (x86_energy_perf_policy(8) is available to change it at run-time.) | ||
381 | */ | ||
382 | if (!cpu_has(c, X86_FEATURE_EPB)) | ||
383 | return; | ||
384 | |||
385 | rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); | ||
386 | if ((epb & 0xF) != ENERGY_PERF_BIAS_PERFORMANCE) | ||
387 | return; | ||
388 | |||
389 | pr_warn_once("ENERGY_PERF_BIAS: Set to 'normal', was 'performance'\n"); | ||
390 | pr_warn_once("ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)\n"); | ||
391 | epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL; | ||
392 | wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); | ||
393 | } | ||
394 | |||
395 | static void intel_bsp_resume(struct cpuinfo_x86 *c) | ||
396 | { | ||
397 | /* | ||
398 | * MSR_IA32_ENERGY_PERF_BIAS is lost across suspend/resume, | ||
399 | * so reinitialize it properly like during bootup: | ||
400 | */ | ||
401 | init_intel_energy_perf(c); | ||
402 | } | ||
403 | |||
374 | static void init_intel(struct cpuinfo_x86 *c) | 404 | static void init_intel(struct cpuinfo_x86 *c) |
375 | { | 405 | { |
376 | unsigned int l2 = 0; | 406 | unsigned int l2 = 0; |
@@ -478,21 +508,7 @@ static void init_intel(struct cpuinfo_x86 *c) | |||
478 | if (cpu_has(c, X86_FEATURE_VMX)) | 508 | if (cpu_has(c, X86_FEATURE_VMX)) |
479 | detect_vmx_virtcap(c); | 509 | detect_vmx_virtcap(c); |
480 | 510 | ||
481 | /* | 511 | init_intel_energy_perf(c); |
482 | * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not. | ||
483 | * x86_energy_perf_policy(8) is available to change it at run-time | ||
484 | */ | ||
485 | if (cpu_has(c, X86_FEATURE_EPB)) { | ||
486 | u64 epb; | ||
487 | |||
488 | rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); | ||
489 | if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) { | ||
490 | pr_warn_once("ENERGY_PERF_BIAS: Set to 'normal', was 'performance'\n"); | ||
491 | pr_warn_once("ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)\n"); | ||
492 | epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL; | ||
493 | wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); | ||
494 | } | ||
495 | } | ||
496 | } | 512 | } |
497 | 513 | ||
498 | #ifdef CONFIG_X86_32 | 514 | #ifdef CONFIG_X86_32 |
@@ -747,6 +763,7 @@ static const struct cpu_dev intel_cpu_dev = { | |||
747 | .c_detect_tlb = intel_detect_tlb, | 763 | .c_detect_tlb = intel_detect_tlb, |
748 | .c_early_init = early_init_intel, | 764 | .c_early_init = early_init_intel, |
749 | .c_init = init_intel, | 765 | .c_init = init_intel, |
766 | .c_bsp_resume = intel_bsp_resume, | ||
750 | .c_x86_vendor = X86_VENDOR_INTEL, | 767 | .c_x86_vendor = X86_VENDOR_INTEL, |
751 | }; | 768 | }; |
752 | 769 | ||