Re: [patch 20/48] x86/apic: Enable TSC coupled programming mode
From: Thomas Gleixner
Date: Tue Mar 03 2026 - 09:51:19 EST
On Tue, Mar 03 2026 at 15:37, Thomas Gleixner wrote:
> On Mon, Mar 02 2026 at 18:29, Nathan Chancellor wrote:
>>
>> After this change landed in -next as commit f246ec3478cf ("x86/apic:
>> Enable TSC coupled programming mode"), two of my Intel-based test
>> machines fail to boot. Unfortunately, I do not think I have any serial
>> access on these, so I have little introspective ability. Is there any
>> information I can provide or patches I can test to try and help figure
>> out what is going on here? I have attached the output of lscpu of both
>> machines, in case there is some common thread there.
>
> Grmbl. I stared at it for a while and I have a suspicion. Can you try
> the patch below and also provide from one of the machines the output of
>
> dmesg | grep -i tsc
>
> In case that does not work, I'll send a debug patch in reply to this
> mail.
Here you go. It fails the coupled mode, but emits all relevant data via
trace_printk. Just collect it right after booting and please tell me
where the boot stops in the boot process so I can narrow down the search.
Thanks,
tglx
---
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -424,9 +424,10 @@ static int lapic_next_deadline(unsigned
* There is no weak_wrmsr_fence() required here as all of this is purely
* CPU local. Avoid the [ml]fence overhead.
*/
- u64 tsc = rdtsc();
+ u64 dl = rdtsc() + (((u64) delta) * TSC_DIVISOR);
- native_wrmsrq(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
+ native_wrmsrq(MSR_IA32_TSC_DEADLINE, dl);
+ trace_printk("APIC deadline: %16llu\n", dl);
return 0;
}
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -310,11 +310,9 @@ static inline bool clockevent_set_next_c
if (unlikely(!ktime_expiry_to_cycles(dev->cs_id, expires, &cycles)))
return false;
- if (IS_ENABLED(CONFIG_GENERIC_CLOCKEVENTS_COUPLED_INLINE))
- arch_inlined_clockevent_set_next_coupled(cycles, dev);
- else
- dev->set_next_coupled(cycles, dev);
- return true;
+ trace_printk("Coupled deadline: %16llu Exp: %16lld\n", cycles, expires);
+
+ return false;
}
#else
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -404,6 +404,7 @@ static void tk_setup_internals(struct ti
*/
clocks_calc_mult_shift(&tk->cs_ns_to_cyc_mult, &tk->cs_ns_to_cyc_shift,
NSEC_PER_MSEC, clock->freq_khz, 3600 * 1000);
+ tk->cs_ns_to_cyc_maxns = div_u64(clock->mask, tk->cs_ns_to_cyc_mult);
}
}
@@ -762,6 +763,11 @@ static inline void tk_update_ns_to_cyc(s
shift = tkrs->shift + tks->cs_ns_to_cyc_shift;
tks->cs_ns_to_cyc_mult = (u32)div_u64(1ULL << shift, tkrs->mult);
tks->cs_ns_to_cyc_maxns = div_u64(tkrs->clock->mask, tks->cs_ns_to_cyc_mult);
+ trace_printk("CSM: %8u CSS: %8u CEM: %8u CES: %8u MNS: %16llu BNS: %16lld BCY: %16llu\n",
+ tkrs->shift, tkrs->mult, tks->cs_ns_to_cyc_mult,
+ tks->cs_ns_to_cyc_shift, tks->cs_ns_to_cyc_maxns,
+ tkrs->base + (tkrs->xtime_nsec >> tkrs->shift),
+ tkrs->cycle_last);
}
/*