lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1440241376-31889-1-git-send-email-yu.c.chen@intel.com>
Date:	Sat, 22 Aug 2015 19:02:56 +0800
From:	Chen Yu <yu.c.chen@...el.com>
To:	rjw@...ysocki.net, pavel@....cz, tglx@...utronix.de,
	mingo@...hat.com, hpa@...or.com
Cc:	lenb@...nel.org, rui.zhang@...el.com, marcin.kaszewski@...el.com,
	x86@...nel.org, linux-pm@...r.kernel.org,
	linux-kernel@...r.kernel.org, Chen Yu <yu.c.chen@...el.com>
Subject: [PATCH] [v3] x86, suspend: Save/restore THERM_CONTROL register for suspend

A bug is reported(https://bugzilla.redhat.com/show_bug.cgi?id=1227208)
that, after resuming from S3, CPU is working at a low speed.
After investigation, it is found that, BIOS has modified the value
of THERM_CONTROL register during S3, changes it from 0 to 0x10,
while the latter means CPU can only get 25% of the Duty Cycle,
and this caused the problem.

Simple scenario to reproduce:
1.Boot up system
2.Get MSR with address 0x19a, it should output 0
3.Put system into sleep, then wake up
4.Get MSR with address 0x19a, it should output 0(actual it outputs 0x10)

Although this is a BIOS issue, it would be more robust for linux to deal
with this situation. This patch fixes this issue by introducing a quirk
for problematic platform, thus save/restore THERM_CONTROL(now called
CLOCK_MODULATION) register on suspend/resume.

Since both 64/32-bit kernels are affected, this patch covers 64/32-bit
common code path. And because THERM_CONTROL might not be available or
readable in any situation, we use rdmsrl_safe to safely save these
MSR registers.

Tested-by: Marcin Kaszewski <marcin.kaszewski@...el.com>
Signed-off-by: Chen Yu <yu.c.chen@...el.com>
---
v3:
 - Simplify the patch to only focus on THERM_CONTROL register.
   This will make things 'just work'.
v2:
 - Cover both 64/32-bit common code path.
   Use rdmsrl_safe to safely read MSR.
   Introduce a quirk framework for save/restore specified MSR on different
   platforms.
---
 arch/x86/include/asm/suspend_32.h |  2 ++
 arch/x86/include/asm/suspend_64.h |  2 ++
 arch/x86/power/cpu.c              | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h
index d1793f0..ae2785f 100644
--- a/arch/x86/include/asm/suspend_32.h
+++ b/arch/x86/include/asm/suspend_32.h
@@ -15,6 +15,8 @@ struct saved_context {
 	unsigned long cr0, cr2, cr3, cr4;
 	u64 misc_enable;
 	bool misc_enable_saved;
+	u64 therm_control;
+	bool therm_control_saved;
 	struct desc_ptr gdt_desc;
 	struct desc_ptr idt;
 	u16 ldt;
diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h
index 7ebf0eb..b1e6fe6 100644
--- a/arch/x86/include/asm/suspend_64.h
+++ b/arch/x86/include/asm/suspend_64.h
@@ -24,6 +24,8 @@ struct saved_context {
 	unsigned long cr0, cr2, cr3, cr4, cr8;
 	u64 misc_enable;
 	bool misc_enable_saved;
+	u64 therm_control;
+	bool therm_control_saved;
 	unsigned long efer;
 	u16 gdt_pad; /* Unused */
 	struct desc_ptr gdt_desc;
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 9ab5279..7c14ced 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -23,6 +23,7 @@
 #include <asm/debugreg.h>
 #include <asm/cpu.h>
 #include <asm/mmu_context.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
@@ -111,6 +112,12 @@ static void __save_processor_state(struct saved_context *ctxt)
 #endif
 	ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE,
 					       &ctxt->misc_enable);
+
+	if (ctxt->therm_control_saved) {
+		ctxt->therm_control_saved =
+			!rdmsrl_safe(MSR_IA32_THERM_CONTROL,
+			&ctxt->therm_control);
+	}
 }
 
 /* Needed by apm.c */
@@ -229,6 +236,9 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
 	x86_platform.restore_sched_clock_state();
 	mtrr_bp_restore();
 	perf_restore_debug_store();
+
+	if (ctxt->therm_control_saved)
+		wrmsrl(MSR_IA32_THERM_CONTROL, ctxt->therm_control);
 }
 
 /* Needed by apm.c */
@@ -320,3 +330,30 @@ static int __init bsp_pm_check_init(void)
 }
 
 core_initcall(bsp_pm_check_init);
+
+static int therm_control_need_save(const struct dmi_system_id *d)
+{
+	saved_context.therm_control_saved = true;
+	return 0;
+}
+
+static struct dmi_system_id msr_save_dmi_table[] = {
+	{
+	 .callback = therm_control_need_save,
+	 .ident = "BROADWELL BDX_EP",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "GRANTLEY"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "E63448-400"),
+		},
+	},
+	{}
+};
+static int pm_check_save_msr(void)
+{
+	saved_context.therm_control_saved = false;
+	dmi_check_system(msr_save_dmi_table);
+	return 0;
+}
+
+late_initcall(pm_check_save_msr);
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ