According to Intel SDM, for the local APIC timer, 1. "The initial-count register is a read-write register. A write of 0 to the initial-count register effectively stops the local APIC timer, in both one-shot and periodic mode." 2. "In TSC deadline mode, writes to the initial-count register are ignored; and current-count register always reads 0. Instead, timer behavior is controlled using the IA32_TSC_DEADLINE MSR." "In TSC-deadline mode, writing 0 to the IA32_TSC_DEADLINE MSR disarms the local-APIC timer."
Current code in lapic_timer_shutdown() writes 0 to the initial-count register. This stops the local APIC timer for one-shot and periodic mode only. In TSC deadline mode, the timer is not properly stopped.
Some CPUs are affected by this and they are woke up by the armed timer in s2idle in TSC deadline mode.
Stop the TSC deadline timer in lapic_timer_shutdown() by writing 0 to MSR_IA32_TSC_DEADLINE.
Cc: stable@vger.kernel.org Fixes: 279f1461432c ("x86: apic: Use tsc deadline for oneshot when available") Signed-off-by: Zhang Rui rui.zhang@intel.com --- arch/x86/kernel/apic/apic.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 6513c53c9459..d1006531729a 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -441,6 +441,10 @@ static int lapic_timer_shutdown(struct clock_event_device *evt) v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); apic_write(APIC_LVTT, v); apic_write(APIC_TMICT, 0); + + if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) + wrmsrl(MSR_IA32_TSC_DEADLINE, 0); + return 0; }