public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume
@ 2015-07-16 22:09 Laura Abbott
  2015-07-17  8:39 ` Borislav Petkov
  0 siblings, 1 reply; 3+ messages in thread
From: Laura Abbott @ 2015-07-16 22:09 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
  Cc: Laura Abbott, x86, linux-kernel, Peter Zijlstra, Borislav Petkov,
	Andy Lutomirski

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 <labbott@fedoraproject.org>
---
RFC because I'm not that familiar with x86 suspend/resume inner workings.
---
 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..dc9f1e5 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 cpu_custom_resume(void)
+{
+	if (this_cpu->c_resume)
+		this_cpu->c_resume(&boot_cpu_data);
+}
+
+static struct syscore_ops cpu_syscore_ops = {
+	.resume		= cpu_custom_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..5143d0f 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_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..9a22474 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_resume	= init_intel_energy_perf,
 	.c_x86_vendor	= X86_VENDOR_INTEL,
 };
 
-- 
2.4.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [RFC][PATCH] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume
  2015-07-16 22:09 [RFC][PATCH] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume Laura Abbott
@ 2015-07-17  8:39 ` Borislav Petkov
  2015-07-17 12:14   ` Ingo Molnar
  0 siblings, 1 reply; 3+ messages in thread
From: Borislav Petkov @ 2015-07-17  8:39 UTC (permalink / raw)
  To: Laura Abbott
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, linux-kernel,
	Peter Zijlstra, Andy Lutomirski

On Thu, Jul 16, 2015 at 03:09:21PM -0700, Laura Abbott wrote:
> 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

Yap, I see it here too on an IVB laptop when doing s2r.

> 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 <labbott@fedoraproject.org>
> ---
> RFC because I'm not that familiar with x86 suspend/resume inner workings.
> ---
>  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..dc9f1e5 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 cpu_custom_resume(void)

Let's call this bsp_resume() as it is run only on the boot CPU.

> +{
> +	if (this_cpu->c_resume)
> +		this_cpu->c_resume(&boot_cpu_data);
> +}

So giving boot_cpu_data means, this is the boot CPU but you're assigning
it to c_resume() which means, every CPU. What you could do is call the
function ptr ->c_bsp_resume like the ->c_bsp_init which we already have
so that it is clear that it is run only on the BSP.

Rest looks ok to me, unless tip guys have a better idea...

-- 
Regards/Gruss,
    Boris.

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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC][PATCH] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume
  2015-07-17  8:39 ` Borislav Petkov
@ 2015-07-17 12:14   ` Ingo Molnar
  0 siblings, 0 replies; 3+ messages in thread
From: Ingo Molnar @ 2015-07-17 12:14 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Laura Abbott, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86,
	linux-kernel, Peter Zijlstra, Andy Lutomirski


* Borislav Petkov <bp@alien8.de> wrote:

> >  EXPORT_SYMBOL_GPL(__static_cpu_has_safe);
> > +
> > +static void cpu_custom_resume(void)
> 
> Let's call this bsp_resume() as it is run only on the boot CPU.
> 
> > +{
> > +	if (this_cpu->c_resume)
> > +		this_cpu->c_resume(&boot_cpu_data);
> > +}
> 
> So giving boot_cpu_data means, this is the boot CPU but you're assigning it to 
> c_resume() which means, every CPU. What you could do is call the function ptr 
> ->c_bsp_resume like the ->c_bsp_init which we already have so that it is clear 
> that it is run only on the BSP.
> 
> Rest looks ok to me, unless tip guys have a better idea...

Looks good to me!

	Ingo

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-07-17 12:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-16 22:09 [RFC][PATCH] x86, CPU: Restore MSR_IA32_ENERGY_PERF_BIAS after resume Laura Abbott
2015-07-17  8:39 ` Borislav Petkov
2015-07-17 12:14   ` Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox