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>] [day] [month] [year] [list]
Message-Id: <20241015061522.25288-1-rui.zhang@intel.com>
Date: Tue, 15 Oct 2024 14:15:22 +0800
From: Zhang Rui <rui.zhang@...el.com>
To: tglx@...utronix.de,
	mingo@...hat.com,
	bp@...en8.de,
	dave.hansen@...ux.intel.com,
	rafael.j.wysocki@...el.com,
	x86@...nel.org,
	linux-pm@...r.kernel.org
Cc: hpa@...or.com,
	peterz@...radead.org,
	thorsten.blum@...lux.com,
	yuntao.wang@...ux.dev,
	tony.luck@...el.com,
	len.brown@...el.com,
	srinivas.pandruvada@...el.com,
	linux-kernel@...r.kernel.org,
	stable@...r.kernel.org
Subject: [PATCH V4] x86/apic: Always explicitly disarm TSC-deadline timer

New processors have become pickier about the local APIC timer state
before entering low power modes. These low power modes are used (for
example) when you close your laptop lid and suspend. If you put your
laptop in a bag in this unnecessarily-high-power state, it is likely
to get quite toasty while it quickly sucks the battery dry.

The problem boils down to some CPUs' inability to power down until the
kernel fully disables the local APIC timer. The current kernel code
works in one-shot and periodic modes but does not work for deadline
mode. Deadline mode has been the supported and preferred mode on
Intel CPUs for over a decade and uses an MSR to drive the timer
instead of an APIC register.

Disable the TSC Deadline timer in lapic_timer_shutdown() by writing to
MSR_IA32_TSC_DEADLINE when in TSC-deadline mode. Also avoid writing
to the initial-count register (APIC_TMICT) which is ignored in
TSC-deadline mode.

Note: The APIC_LVTT|=APIC_LVT_MASKED operation should theoretically be
enough to tell the hardware that the timer will not fire in any of the
timer modes. But mitigating AMD erratum 411[1] also requires clearing
out APIC_TMICT. Solely setting APIC_LVT_MASKED is also ineffective in
practice on Intel Lunar Lake systems, which is the motivation for this
change.

1. 411 Processor May Exit Message-Triggered C1E State Without an Interrupt if Local APIC Timer Reaches Zero - https://www.amd.com/content/dam/amd/en/documents/archived-tech-docs/revision-guides/41322_10h_Rev_Gd.pdf

Cc: stable@...r.kernel.org
Fixes: 279f1461432c ("x86: apic: Use tsc deadline for oneshot when available")
Suggested-by: Dave Hansen <dave.hansen@...el.com>
Signed-off-by: Zhang Rui <rui.zhang@...el.com>
Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@...el.com>
Tested-by: Srinivas Pandruvada <srinivas.pandruvada@...ux.intel.com>
Tested-by: Todd Brandt <todd.e.brandt@...el.com>
---
V2
- Improve changelog
V3
- Subject and changelog rewrite
- Check LAPIC Timer mode using APIC_LVTT value instead of extra CPU feature flag check
- Avoid APIC_TMICT write which is ignored in TSC-deadline mode
V4
- Add back Fixes tag and stable tag which was missing in V3
- Update patch recipients
---
 arch/x86/kernel/apic/apic.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 6513c53c9459..5436a4083065 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -440,7 +440,19 @@ static int lapic_timer_shutdown(struct clock_event_device *evt)
 	v = apic_read(APIC_LVTT);
 	v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
 	apic_write(APIC_LVTT, v);
-	apic_write(APIC_TMICT, 0);
+
+	/*
+	 * Setting APIC_LVT_MASKED should be enough to tell the
+	 * hardware that this timer will never fire. But AMD
+	 * erratum 411 and some Intel CPU behavior circa 2024
+	 * say otherwise. Time for belt and suspenders programming,
+	 * mask the timer and zero the counter registers:
+	 */
+	if (v & APIC_LVT_TIMER_TSCDEADLINE)
+		wrmsrl(MSR_IA32_TSC_DEADLINE, 0);
+	else
+		apic_write(APIC_TMICT, 0);
+
 	return 0;
 }
 
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ