Re: Detecting x86 LAPIC timer frequency from CPUID data
On Fri, 19 Apr 2019 22:52:01 +0200 (CEST) Thomas Gleixner wrote: > On Fri, 19 Apr 2019, Jacob Pan wrote: > > On Fri, 19 Apr 2019 10:57:10 +0200 (CEST) > > Thomas Gleixner wrote: > > > On Fri, 19 Apr 2019, Daniel Drake wrote: > > > > 0x7F vs 0x7FFF, is that intentional? > > > > > > I don't think so. Looks like a failed copy and paste. Cc'ed > > > Jacob, he might know. > > > > > At the time of v2.6.35 both places use 0x7F. But later this > > patch increased the latter to 0x7FFF but forgot the first part. > > So I guess it is not exactly a failed copy and paste. > > > > commit 4aed89d6b515b9185351706ca95cd712c9d8d6a3 > > Author: Pierre Tardy > > Date: Thu Jan 6 16:23:29 2011 +0100 > > > > x86, lapic-timer: Increase the max_delta to 31 bits > > Indeed. Thanks for digging that up! > > tglx How about a fix like this? I should have taken your advice 9 years ago to avoid duplicated code :) https://lkml.org/lkml/2010/5/11/499 >From 18450bb67e09f5b472f1ed313d7f87a983cb0ac1 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 19 Apr 2019 15:56:06 -0700 Subject: [PATCH] x86/apic: Fix duplicated lapic timer calculation Local APIC timer clockevent parameters can be calculated based on platform specific methods. However the code is mostly duplicated with the interrupt based calibration. This causes further updates prone to mistakes. Fixes: 4aed89d ("x86, lapic-timer: Increase the max_delta to 31 bits") Signed-off-by: Jacob Pan --- arch/x86/kernel/apic/apic.c | 46 ++--- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index b7bcdd7..b2ef91c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -802,6 +802,24 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) return 0; } +static int __init calculate_lapic_clockevent(void) +{ + if (!lapic_timer_frequency) + return -1; + + /* Calculate the scaled math multiplication factor */ + lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR, + TICK_NSEC, lapic_clockevent.shift); + lapic_clockevent.max_delta_ns = + clockevent_delta2ns(0x7FFF, _clockevent); + lapic_clockevent.max_delta_ticks = 0x7FFF; + lapic_clockevent.min_delta_ns = + clockevent_delta2ns(0xF, _clockevent); + lapic_clockevent.min_delta_ticks = 0xF; + + return 0; +} + static int __init calibrate_APIC_clock(void) { struct clock_event_device *levt = this_cpu_ptr(_events); @@ -818,18 +836,17 @@ static int __init calibrate_APIC_clock(void) if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) { return 0; - } else if (lapic_timer_frequency) { + } + + if (!calculate_lapic_clockevent()) { apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n", lapic_timer_frequency); - lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR, - TICK_NSEC, lapic_clockevent.shift); - lapic_clockevent.max_delta_ns = - clockevent_delta2ns(0x7F, _clockevent); - lapic_clockevent.max_delta_ticks = 0x7F; - lapic_clockevent.min_delta_ns = - clockevent_delta2ns(0xF, _clockevent); - lapic_clockevent.min_delta_ticks = 0xF; + /* +* Newer platforms provide early calibration methods must have always +* running local APIC timers, no need for boradcast timer. +*/ lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; + return 0; } @@ -869,17 +886,8 @@ static int __init calibrate_APIC_clock(void) pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, , ); - /* Calculate the scaled math multiplication factor */ - lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, - lapic_clockevent.shift); - lapic_clockevent.max_delta_ns = - clockevent_delta2ns(0x7FFF, _clockevent); - lapic_clockevent.max_delta_ticks = 0x7FFF; - lapic_clockevent.min_delta_ns = - clockevent_delta2ns(0xF, _clockevent); - lapic_clockevent.min_delta_ticks = 0xF; - lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; + calculate_lapic_clockevent(); apic_printk(APIC_VERBOSE, ". delta %ld\n", delta); apic_printk(APIC_VERBOSE, ". mult: %u\n", lapic_clockevent.mult); -- 2.7.4
Re: Detecting x86 LAPIC timer frequency from CPUID data
On Fri, 19 Apr 2019, Jacob Pan wrote: > On Fri, 19 Apr 2019 10:57:10 +0200 (CEST) > Thomas Gleixner wrote: > > On Fri, 19 Apr 2019, Daniel Drake wrote: > > > 0x7F vs 0x7FFF, is that intentional? > > > > I don't think so. Looks like a failed copy and paste. Cc'ed Jacob, he > > might know. > > > At the time of v2.6.35 both places use 0x7F. But later this patch > increased the latter to 0x7FFF but forgot the first part. So I > guess it is not exactly a failed copy and paste. > > commit 4aed89d6b515b9185351706ca95cd712c9d8d6a3 > Author: Pierre Tardy > Date: Thu Jan 6 16:23:29 2011 +0100 > > x86, lapic-timer: Increase the max_delta to 31 bits Indeed. Thanks for digging that up! tglx
Re: Detecting x86 LAPIC timer frequency from CPUID data
On Fri, 19 Apr 2019 10:57:10 +0200 (CEST) Thomas Gleixner wrote: > On Fri, 19 Apr 2019, Daniel Drake wrote: > > On Fri, Apr 19, 2019 at 6:30 AM Thomas Gleixner > > wrote: > > >Time Stamp Counter/Core Crystal Clock Information (0x15): > > > TSC/clock ratio = 168/2 > > > nominal core crystal clock = 0 Hz > > > > > >Processor Frequency Information (0x16): > > > Core Base Frequency (MHz) = 0x834 (2100) > > > Core Maximum Frequency (MHz) = 0xed8 (3800) > > > Bus (Reference) Frequency (MHz) = 0x64 (100) > > > > > > Assuming that TSC and local APIC timer run from the same > > > frequency on these modern machines. > > > > > >2100MHz * 2 / 168 = 25MHz > > > > > > and disabling the tsc deadline timer tells me: > > > > > > . calibration result: 24999 > > > > > > Close enough. > > > > I tested all the Intel SoC generations we have on hand. The > > assumption that the core crystal clock feeds the APIC seems to be > > consistently true. > > > > (Please note that all the following results are done with > > CONFIG_HZ=250, which is why the "calibration result" is 4x higher > > than HZ=1000 as used in previous mails) > > > > In the easy case, the low cost platforms do not support CPUID.0x16 > > (so no CPU frequency reporting), but they do tell us the core > > crystal clock, which is consistent with the APIC calibration > > result: > > ... > > > And the 4 higher-end SoCs that we have available for testing all > > report crystal clock 0Hz from CPUID 0x15, but by combining the > > CPUID.0x16 base frequency with the CPUID.0x15 TSC/clock ratio, the > > crystal frequency can be calculated as you describe, and it > > consistently matches the APIC timer calibration result. > > ... > > > Is this data convincing enough or should we additionally wait for > > some comments from Intel? > > For me it's pretty convincing, but having some confirmation from Intel > wouldn't be a bad thing. > > > I came up with the patch below. However, upon testing, I realised > > that, at least for the platforms I have in hand, only the first > > hunk is really needed. We don't need to use your magic calculation > > to find the crystal frequency because Intel already told us! > > native_calibrate_tsc() already hardcodes the crystal frequency for > > Kabylake, and Amber/Whiskey/Coffee also report the 0x8e/0x9e > > Kabylake model codes. > > I'd rather replace these model checks with math. These tables are > horrible to maintain. > > > Plus ApolloLake/GeminiLake do report the crystal frequency in > > CPUID.0x15 so that is covered too. > > > While looking around this code I also spotted something curious. > > In calibrate_APIC_clock() for the case where lapic_timer_frequency > > has been externally provided, we have: > > lapic_clockevent.max_delta_ns = > > clockevent_delta2ns(0x7F, > > _clockevent); lapic_clockevent.max_delta_ticks = 0x7F; > > > > But in the case where we calibrate, we have: > > lapic_clockevent.max_delta_ns = > > clockevent_delta2ns(0x7FFF, _clockevent); > > lapic_clockevent.max_delta_ticks = 0x7FFF; > > > > 0x7F vs 0x7FFF, is that intentional? > > I don't think so. Looks like a failed copy and paste. Cc'ed Jacob, he > might know. > At the time of v2.6.35 both places use 0x7F. But later this patch increased the latter to 0x7FFF but forgot the first part. So I guess it is not exactly a failed copy and paste. commit 4aed89d6b515b9185351706ca95cd712c9d8d6a3 Author: Pierre Tardy Date: Thu Jan 6 16:23:29 2011 +0100 x86, lapic-timer: Increase the max_delta to 31 bits > Thanks, > > tglx [Jacob Pan]
Re: Detecting x86 LAPIC timer frequency from CPUID data
On Fri, Apr 19, 2019 at 6:30 AM Thomas Gleixner wrote: >Time Stamp Counter/Core Crystal Clock Information (0x15): > TSC/clock ratio = 168/2 > nominal core crystal clock = 0 Hz > >Processor Frequency Information (0x16): > Core Base Frequency (MHz) = 0x834 (2100) > Core Maximum Frequency (MHz) = 0xed8 (3800) > Bus (Reference) Frequency (MHz) = 0x64 (100) > > Assuming that TSC and local APIC timer run from the same frequency on these > modern machines. > >2100MHz * 2 / 168 = 25MHz > > and disabling the tsc deadline timer tells me: > > . calibration result: 24999 > > Close enough. I tested all the Intel SoC generations we have on hand. The assumption that the core crystal clock feeds the APIC seems to be consistently true. (Please note that all the following results are done with CONFIG_HZ=250, which is why the "calibration result" is 4x higher than HZ=1000 as used in previous mails) In the easy case, the low cost platforms do not support CPUID.0x16 (so no CPU frequency reporting), but they do tell us the core crystal clock, which is consistent with the APIC calibration result: N5000 (Gemini Lake) [0.122948] ... lapic delta = 11 [0.122948] ... PM-Timer delta = 357950 [0.122948] ... PM-Timer result ok [0.122948] . delta 11 [0.122948] . mult: 5153917 [0.122948] . calibration result: 76799 [0.122948] . CPU clock speed is 1094.1542 MHz. [0.122948] . host bus clock speed is 19.0799 MHz. Time Stamp Counter/Core Crystal Clock Information (0x15): TSC/clock ratio = 171/3 nominal core crystal clock = 1920 Hz Processor Frequency Information (0x16): Core Base Frequency (MHz) = 0x0 (0) Core Maximum Frequency (MHz) = 0x0 (0) Bus (Reference) Frequency (MHz) = 0x0 (0) N3350 (Apollo Lake) [0.248894] ... lapic delta = 11 [0.248894] ... PM-Timer delta = 357949 [0.248894] ... PM-Timer result ok [0.248894] . delta 11 [0.248894] . mult: 5153917 [0.248894] . calibration result: 76799 [0.248894] . CPU clock speed is 1094.1540 MHz. [0.248894] . host bus clock speed is 19.0799 MHz. Time Stamp Counter/Core Crystal Clock Information (0x15): TSC/clock ratio = 171/3 nominal core crystal clock = 1920 Hz (CPUID 0x16 not supported at all) And the 4 higher-end SoCs that we have available for testing all report crystal clock 0Hz from CPUID 0x15, but by combining the CPUID.0x16 base frequency with the CPUID.0x15 TSC/clock ratio, the crystal frequency can be calculated as you describe, and it consistently matches the APIC timer calibration result. i9-9980HK (Coffee Lake HR) [0.379421] ... lapic delta = 149998 [0.379421] ... PM-Timer delta = 357950 [0.379421] ... PM-Timer result ok [0.379421] . delta 149998 [0.379421] . mult: 6442365 [0.379421] . calibration result: 95998 [0.379421] . CPU clock speed is 2399.3902 MHz. [0.379421] . host bus clock speed is 23.3998 MHz. Time Stamp Counter/Core Crystal Clock Information (0x15): TSC/clock ratio = 200/2 nominal core crystal clock = 0 Hz Processor Frequency Information (0x16): Core Base Frequency (MHz) = 0x960 (2400) Core Maximum Frequency (MHz) = 0x1388 (5000) Bus (Reference) Frequency (MHz) = 0x64 (100) i7-8565U (Whiskey Lake) [0.173776] ... lapic delta = 149998 [0.173776] ... PM-Timer delta = 357950 [0.173776] ... PM-Timer result ok [0.173776] . delta 149998 [0.173776] . mult: 6442365 [0.173776] . calibration result: 95998 [0.173776] . CPU clock speed is 1991.3903 MHz. [0.173776] . host bus clock speed is 23.3998 MHz. Time Stamp Counter/Core Crystal Clock Information (0x15): TSC/clock ratio = 166/2 nominal core crystal clock = 0 Hz Processor Frequency Information (0x16): Core Base Frequency (MHz) = 0x7d0 (2000) Core Maximum Frequency (MHz) = 0x11f8 (4600) Bus (Reference) Frequency (MHz) = 0x64 (100) i5-7200U (Kabylake) [0.219142] ... lapic delta = 149998 [0.219142] ... PM-Timer delta = 357951 [0.219142] ... PM-Timer result ok [0.219142] . delta 149998 [0.219142] . mult: 6442365 [0.219142] . calibration result: 95998 [0.219142] . CPU clock speed is 2711.3880 MHz. [0.219142] . host bus clock speed is 23.3998 MHz. Time Stamp Counter/Core Crystal Clock Information (0x15): TSC/clock ratio = 226/2 nominal core crystal clock = 0 Hz Processor Frequency Information (0x16): Core Base Frequency (MHz) = 0xa8c (2700) Core Maximum Frequency (MHz) = 0xc1c (3100) Bus (Reference) Frequency (MHz) = 0x64 (100) m3-8110Y (Amber Lake) [0.102289] ... lapic delta = 149998 [0.102289] ... PM-Timer delta = 357951 [0.102289] ... PM-Timer result ok [0.102289] . delta 149998 [0.102289] . mult: 6442365 [
Re: Detecting x86 LAPIC timer frequency from CPUID data
On Fri, 19 Apr 2019, Daniel Drake wrote: > On Fri, Apr 19, 2019 at 6:30 AM Thomas Gleixner wrote: > >Time Stamp Counter/Core Crystal Clock Information (0x15): > > TSC/clock ratio = 168/2 > > nominal core crystal clock = 0 Hz > > > >Processor Frequency Information (0x16): > > Core Base Frequency (MHz) = 0x834 (2100) > > Core Maximum Frequency (MHz) = 0xed8 (3800) > > Bus (Reference) Frequency (MHz) = 0x64 (100) > > > > Assuming that TSC and local APIC timer run from the same frequency on these > > modern machines. > > > >2100MHz * 2 / 168 = 25MHz > > > > and disabling the tsc deadline timer tells me: > > > > . calibration result: 24999 > > > > Close enough. > > I tested all the Intel SoC generations we have on hand. The assumption that > the core crystal clock feeds the APIC seems to be consistently true. > > (Please note that all the following results are done with CONFIG_HZ=250, > which is why the "calibration result" is 4x higher than HZ=1000 as used > in previous mails) > > In the easy case, the low cost platforms do not support CPUID.0x16 (so no > CPU frequency reporting), but they do tell us the core crystal clock, which > is consistent with the APIC calibration result: ... > And the 4 higher-end SoCs that we have available for testing all report > crystal clock 0Hz from CPUID 0x15, but by combining the CPUID.0x16 base > frequency with the CPUID.0x15 TSC/clock ratio, the crystal frequency can > be calculated as you describe, and it consistently matches the APIC timer > calibration result. ... > Is this data convincing enough or should we additionally wait for some > comments from Intel? For me it's pretty convincing, but having some confirmation from Intel wouldn't be a bad thing. > I came up with the patch below. However, upon testing, I realised that, at > least for the platforms I have in hand, only the first hunk is really needed. > We don't need to use your magic calculation to find the crystal frequency > because Intel already told us! native_calibrate_tsc() already hardcodes the > crystal frequency for Kabylake, and Amber/Whiskey/Coffee also report the > 0x8e/0x9e Kabylake model codes. I'd rather replace these model checks with math. These tables are horrible to maintain. > Plus ApolloLake/GeminiLake do report the crystal frequency in CPUID.0x15 > so that is covered too. > While looking around this code I also spotted something curious. > In calibrate_APIC_clock() for the case where lapic_timer_frequency has been > externally provided, we have: > lapic_clockevent.max_delta_ns = > clockevent_delta2ns(0x7F, _clockevent); > lapic_clockevent.max_delta_ticks = 0x7F; > > But in the case where we calibrate, we have: > lapic_clockevent.max_delta_ns = > clockevent_delta2ns(0x7FFF, _clockevent); > lapic_clockevent.max_delta_ticks = 0x7FFF; > > 0x7F vs 0x7FFF, is that intentional? I don't think so. Looks like a failed copy and paste. Cc'ed Jacob, he might know. Thanks, tglx
Re: Detecting x86 LAPIC timer frequency from CPUID data
On Thu, 18 Apr 2019, Thomas Gleixner wrote: > On Wed, 17 Apr 2019, Daniel Drake wrote: > > > The CPUID.0x16 leaf provides "Bus (Reference) Frequency (in MHz)". > > > > In the thread "No 8254 PIT & no HPET on new Intel N3350 platforms > > causes kernel panic during early boot" we are exploring ways to have > > the kernel avoid using the PIT/HPET IRQ0 timer in more cases, and > > Thomas Gleixner suggested that we could use this CPUID data to set > > lapic_timer_frequency, avoiding the need for calibrate_APIC_clock() > > to measure the APIC clock against the IRQ0 timer. > > > > I'm thinking of the the following code change, however I get > > unexpected results on Intel i7-8565U (Whiskey Lake). When > > booting without this change, and with apic=notscdeadline (so that > > APIC clock gets calibrated and used), the bus speed is detected as > > 23MHz: > > > > ... lapic delta = 149994 > > ... PM-Timer delta = 357939 > > ... PM-Timer result ok > > . delta 149994 > > . mult: 6442193 > > . calibration result: 23999 That's 24MHZ which is the nominal clock for these machines. > > . CPU clock speed is 1991.0916 MHz. > > . host bus clock speed is 23.0999 MHz. I think that printout is wrong in two aspects. First it should be 23.Mhz, second it should be 100MHz. This stuff comes from old systems which had completely different clock setups. > > However the CPUID.0x16 ECX reports a 100MHz bus speed on this device, > > so this code change would produce a significantly different calibration. Yes. > > Am I doing anything obviously wrong? > > It's probably just my fault sending you down the wrong path. What's the > content of CPUUD.0x15 on that box? I bet that CPUID.0x15 ECX says 24Mhz or it just says 0 like on my machine. But then interestingly enough on that box I see: Time Stamp Counter/Core Crystal Clock Information (0x15): TSC/clock ratio = 168/2 nominal core crystal clock = 0 Hz Processor Frequency Information (0x16): Core Base Frequency (MHz) = 0x834 (2100) Core Maximum Frequency (MHz) = 0xed8 (3800) Bus (Reference) Frequency (MHz) = 0x64 (100) Assuming that TSC and local APIC timer run from the same frequency on these modern machines. 2100MHz * 2 / 168 = 25MHz and disabling the tsc deadline timer tells me: . calibration result: 24999 Close enough. Thinking about it - that makes a lot of sense. With TSC deadline timer available it would be pretty silly if there is yet another clock feeding into local APIC. And the 0x15 -> 0x16 correlation is clear as well. The TSC runs at the nominal CPU frequency, in this case 2100MHz. So the nominator/denominator pair from 0x15 allows to deduce the nominal core crystal clock which seems to be exactly the clock which is fed into the local APIC timer. If someone from Intel could confirm that, then we could make that work for any modern system. Thanks, tglx
Re: Detecting x86 LAPIC timer frequency from CPUID data
On Wed, 17 Apr 2019, Daniel Drake wrote: > The CPUID.0x16 leaf provides "Bus (Reference) Frequency (in MHz)". > > In the thread "No 8254 PIT & no HPET on new Intel N3350 platforms > causes kernel panic during early boot" we are exploring ways to have > the kernel avoid using the PIT/HPET IRQ0 timer in more cases, and > Thomas Gleixner suggested that we could use this CPUID data to set > lapic_timer_frequency, avoiding the need for calibrate_APIC_clock() > to measure the APIC clock against the IRQ0 timer. > > I'm thinking of the the following code change, however I get > unexpected results on Intel i7-8565U (Whiskey Lake). When > booting without this change, and with apic=notscdeadline (so that > APIC clock gets calibrated and used), the bus speed is detected as > 23MHz: > > ... lapic delta = 149994 > ... PM-Timer delta = 357939 > ... PM-Timer result ok > . delta 149994 > . mult: 6442193 > . calibration result: 23999 > . CPU clock speed is 1991.0916 MHz. > . host bus clock speed is 23.0999 MHz. > > However the CPUID.0x16 ECX reports a 100MHz bus speed on this device, > so this code change would produce a significantly different calibration. > > Am I doing anything obviously wrong? It's probably just my fault sending you down the wrong path. What's the content of CPUUD.0x15 on that box? Thanks, tglx
Detecting x86 LAPIC timer frequency from CPUID data
The CPUID.0x16 leaf provides "Bus (Reference) Frequency (in MHz)". In the thread "No 8254 PIT & no HPET on new Intel N3350 platforms causes kernel panic during early boot" we are exploring ways to have the kernel avoid using the PIT/HPET IRQ0 timer in more cases, and Thomas Gleixner suggested that we could use this CPUID data to set lapic_timer_frequency, avoiding the need for calibrate_APIC_clock() to measure the APIC clock against the IRQ0 timer. I'm thinking of the the following code change, however I get unexpected results on Intel i7-8565U (Whiskey Lake). When booting without this change, and with apic=notscdeadline (so that APIC clock gets calibrated and used), the bus speed is detected as 23MHz: ... lapic delta = 149994 ... PM-Timer delta = 357939 ... PM-Timer result ok . delta 149994 . mult: 6442193 . calibration result: 23999 . CPU clock speed is 1991.0916 MHz. . host bus clock speed is 23.0999 MHz. However the CPUID.0x16 ECX reports a 100MHz bus speed on this device, so this code change would produce a significantly different calibration. Am I doing anything obviously wrong? diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 3fae23834069..6c51ce842f86 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -679,6 +679,16 @@ static unsigned long cpu_khz_from_cpuid(void) cpuid(0x16, _base_mhz, _max_mhz, _bus_mhz, ); +#ifdef CONFIG_X86_LOCAL_APIC + /* +* If bus frequency is provided in CPUID data, set +* global lapic_timer_frequency to bus_clock_cycles/jiffy. +* This avoids having to calibrate the APIC timer later. +*/ + if (ecx_bus_mhz) + lapic_timer_frequency = (ecx_bus_mhz * 100) / HZ; +#endif + return eax_base_mhz * 1000; } -- 2.19.1