Skip to content

Commit 3357674

Browse files
committed
x86/apic: Always explicitly disarm TSC-deadline timer
JIRA: https://issues.redhat.com/browse/RHEL-65750 commit ffd9584 Author: Zhang Rui <[email protected]> Date: Tue Oct 15 14:15:22 2024 +0800 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 and it is not in this low power mode, 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 CPU recognizes that the local APIC timer is shut down. 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 Fixes: 279f146 ("x86: apic: Use tsc deadline for oneshot when available") Suggested-by: Dave Hansen <[email protected]> Signed-off-by: Zhang Rui <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Rafael J. Wysocki <[email protected]> Tested-by: Srinivas Pandruvada <[email protected]> Tested-by: Todd Brandt <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/all/20241015061522.25288-1-rui.zhang%40intel.com Signed-off-by: David Arcari <[email protected]>
1 parent 6c0c626 commit 3357674

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

arch/x86/kernel/apic/apic.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,19 @@ static int lapic_timer_shutdown(struct clock_event_device *evt)
440440
v = apic_read(APIC_LVTT);
441441
v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
442442
apic_write(APIC_LVTT, v);
443-
apic_write(APIC_TMICT, 0);
443+
444+
/*
445+
* Setting APIC_LVT_MASKED (above) should be enough to tell
446+
* the hardware that this timer will never fire. But AMD
447+
* erratum 411 and some Intel CPU behavior circa 2024 say
448+
* otherwise. Time for belt and suspenders programming: mask
449+
* the timer _and_ zero the counter registers:
450+
*/
451+
if (v & APIC_LVT_TIMER_TSCDEADLINE)
452+
wrmsrl(MSR_IA32_TSC_DEADLINE, 0);
453+
else
454+
apic_write(APIC_TMICT, 0);
455+
444456
return 0;
445457
}
446458

0 commit comments

Comments
 (0)