2015-07-17 18:32:49

by Laura Abbott

[permalink] [raw]
Subject: [PATCHv2] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume


MSR_IA32_ENERGY_PERF_BIAS is lost after suspend/resume:

x86_energy_perf_policy -r before

cpu0: 0x0000000000000006
cpu1: 0x0000000000000006
cpu2: 0x0000000000000006
cpu3: 0x0000000000000006
cpu4: 0x0000000000000006
cpu5: 0x0000000000000006
cpu6: 0x0000000000000006
cpu7: 0x0000000000000006

after

cpu0: 0x0000000000000000
cpu1: 0x0000000000000006
cpu2: 0x0000000000000006
cpu3: 0x0000000000000006
cpu4: 0x0000000000000006
cpu5: 0x0000000000000006
cpu6: 0x0000000000000006
cpu7: 0x0000000000000006

This register is set via init_intel at bootup. During resume, the
secondary CPUs are brought online again and init_intel is callled which
re-initializes the register. The boot cpu however never reinitializes
the register. Add a syscore callback to reinitialize the register for
the boot CPU.

Signed-off-by: Laura Abbott <[email protected]>
---
v2: Tweaked a few names to be more descriptive
---
arch/x86/kernel/cpu/common.c | 18 ++++++++++++++++++
arch/x86/kernel/cpu/cpu.h | 1 +
arch/x86/kernel/cpu/intel.c | 36 +++++++++++++++++++++---------------
3 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 922c5e0..fa95bb8 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -13,6 +13,7 @@
#include <linux/kgdb.h>
#include <linux/smp.h>
#include <linux/io.h>
+#include <linux/syscore_ops.h>

#include <asm/stackprotector.h>
#include <asm/perf_event.h>
@@ -1488,3 +1489,20 @@ inline bool __static_cpu_has_safe(u16 bit)
return boot_cpu_has(bit);
}
EXPORT_SYMBOL_GPL(__static_cpu_has_safe);
+
+static void bsp_resume(void)
+{
+ if (this_cpu->c_bsp_resume)
+ this_cpu->c_bsp_resume(&boot_cpu_data);
+}
+
+static struct syscore_ops cpu_syscore_ops = {
+ .resume = bsp_resume,
+};
+
+static int __init init_cpu_syscore(void)
+{
+ register_syscore_ops(&cpu_syscore_ops);
+ return 0;
+}
+core_initcall(init_cpu_syscore);
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index c37dc37..2584265 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -13,6 +13,7 @@ struct cpu_dev {
void (*c_init)(struct cpuinfo_x86 *);
void (*c_identify)(struct cpuinfo_x86 *);
void (*c_detect_tlb)(struct cpuinfo_x86 *);
+ void (*c_bsp_resume)(struct cpuinfo_x86 *);
int c_x86_vendor;
#ifdef CONFIG_X86_32
/* 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 50163fa..0790a8b 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -371,6 +371,25 @@ static void detect_vmx_virtcap(struct cpuinfo_x86 *c)
}
}

+static void init_intel_energy_perf(struct cpuinfo_x86 *c)
+{
+ /*
+ * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not.
+ * x86_energy_perf_policy(8) is available to change it at run-time
+ */
+ if (cpu_has(c, X86_FEATURE_EPB)) {
+ u64 epb;
+
+ rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
+ if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) {
+ pr_warn_once("ENERGY_PERF_BIAS: Set to 'normal', was 'performance'\n");
+ pr_warn_once("ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)\n");
+ epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL;
+ wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
+ }
+ }
+}
+
static void init_intel(struct cpuinfo_x86 *c)
{
unsigned int l2 = 0;
@@ -478,21 +497,7 @@ static void init_intel(struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_VMX))
detect_vmx_virtcap(c);

- /*
- * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not.
- * x86_energy_perf_policy(8) is available to change it at run-time
- */
- if (cpu_has(c, X86_FEATURE_EPB)) {
- u64 epb;
-
- rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
- if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) {
- pr_warn_once("ENERGY_PERF_BIAS: Set to 'normal', was 'performance'\n");
- pr_warn_once("ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)\n");
- epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL;
- wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
- }
- }
+ init_intel_energy_perf(c);
}

#ifdef CONFIG_X86_32
@@ -747,6 +752,7 @@ static const struct cpu_dev intel_cpu_dev = {
.c_detect_tlb = intel_detect_tlb,
.c_early_init = early_init_intel,
.c_init = init_intel,
+ .c_bsp_resume = init_intel_energy_perf,
.c_x86_vendor = X86_VENDOR_INTEL,
};

--
2.4.3


2015-07-17 20:39:44

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCHv2] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume

On Fri, 17 Jul 2015, Laura Abbott wrote:
> v2: Tweaked a few names to be more descriptive

Descriptive by some definition of descriptive. See below.

> +static void init_intel_energy_perf(struct cpuinfo_x86 *c)
> +{
> + /*
> + * Initialize MSR_IA32_ENERGY_PERF_BIAS if BIOS did not.
> + * x86_energy_perf_policy(8) is available to change it at run-time
> + */
> + if (cpu_has(c, X86_FEATURE_EPB)) {

Make this

if (!cpu_has(c, X86_FEATURE_EPB))
return;

and spare the extra indentation level.

> + u64 epb;
> + rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
> + if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) {

Ditto

> + pr_warn_once("ENERGY_PERF_BIAS: Set to 'normal', was 'performance'\n");
> + pr_warn_once("ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)\n");
> + epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL;
> + wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb);
> + }
> + }
> +}
> #ifdef CONFIG_X86_32
> @@ -747,6 +752,7 @@ static const struct cpu_dev intel_cpu_dev = {
> .c_detect_tlb = intel_detect_tlb,
> .c_early_init = early_init_intel,
> .c_init = init_intel,
> + .c_bsp_resume = init_intel_energy_perf,

Looking at the resulting code I have no idea WHY
init_intel_energy_perf is set here. So much for descriptive.

This really wants to be bsp_resume() or something like this (add the
pointless intel prefix if it makes your managers happy). That _IS_
actually descriptive.

static void bsp_resume(struct cpuinfo_x86 *c)
{
/*
* Some reasonable comment WHY we call this here.
*/
init_intel_energy_perf(c);
}

Aside of documenting what that resume thing is for and why
init_intel_energy_perf() needs to be called, I'm quite sure that this
will fill up pretty fast with other stuff which gets lost across S/R.

Thanks,

tglx

2015-07-18 05:16:36

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCHv2] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume

On Fri, Jul 17, 2015 at 10:39:25PM +0200, Thomas Gleixner wrote:
> Aside of documenting what that resume thing is for and why
> init_intel_energy_perf() needs to be called, I'm quite sure that this
> will fill up pretty fast with other stuff which gets lost across S/R.

Haha, I was thinking the same thing... So we better lay the foundations
properly, from the beginning. :-)

--
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--