On Sun, Aug 14, 2022 at 11:24:37PM -0500, Scott Cheloha wrote:
> Hi,
> 
> In the future when the LAPIC timer is run in oneshot mode there will
> be no lapic_delay().
> 
> This is fine if you have a constant TSC, because we have tsc_delay().
> 
> This is *very* bad for older amd64 machines, because you are left with
> i8254_delay().
> 
> I would like to offer a less awful delay(9) implementation for this
> class of hardware.  Otherwise we may trip over bizarre phantom bugs on
> MP kernels because only one CPU can read the i8254 at a time.

i8254 is often gated on Intel since around Comet Lake
which is why we started replacing delay_func with tsc_delay earlier

when delay was still 8254 in early boot the cpu_freq_ctr() which
gets the cpu speed with performance counter msrs and delay gave
a wrong result as delay didn't work as expected

sys/arch/amd64/amd64/identcpu.c
revision 1.119
date: 2021/08/31 15:11:54;  author: kettenis;  state: Exp;  lines: +4 -1;  
commitid: fyhbiR533m0v3XO9;
Use the TSC delay(9) backend earlier on machines where we can.  Also use
the TSC for delays even if there is a skew between the TSCs of the cores
as this doesn't matter for delay(9).

Gets rid of te unreasonable clock speed reports on Intel Tiget Lake CPUs
where the i8254 behaves in weird ways.

ok patrick@, deraadt@, mlarkin@
----------------------------

sys/arch/amd64/amd64/lapic.c
revision 1.55
date: 2019/08/03 14:57:51;  author: jcs;  state: Exp;  lines: +8 -4;  commitid: 
NTF41FCHEhE2NllV;
If the CPU frequency is available during TSC init, make it available
for lapic timer init to avoid calibrating against the 8254 clock.
Some newer machines are shipping with the 8254 clock gated for power
saving, so it may not be usable.

ok mlarkin
discussed with deraadt
----------------------------

On some Intel hardware getting the frequency out of cpuid for the tsc
isn't possible.  tsc.c 1.22 describes some of the mess

> 
> I think patrick@ was struggling with some version of that problem last
> year, but in a VM.

patrick moved pvbus probing so hv_delay would be used earlier

sys/arch/amd64/amd64/mainbus.c
----------------------------
revision 1.51
date: 2021/08/31 15:52:59;  author: patrick;  state: Exp;  lines: +1 -7;  
commitid: reA7Lsk1mKRhapKD;
Identify the paravirtual bus earlier, as we need to make sure that we have
a working delay func ready before the first occurence of delay().  This is
necessary on Hyper-V Gen 2 VMs where we don't use the TSC.

Discussed with the hackroom
ok kettenis@
----------------------------

> 
> Real i386 hardware should be fine.  Later models with an ACPI PM timer
> will be fine using acpitimer_delay() instead of i8254_delay().
> 
> If this seems reasonable to people I will come back with a cleaned up
> patch for testing.
> 
> Thoughts?  Preferences?
> 
> -Scott
> 
> Here are the sample measurements from my 2017 laptop (kaby lake
> refresh) running the attached patch.  It takes longer than a
> microsecond to read either of the ACPI timers.  The PM timer is better
> than the HPET.  The HPET is a bit better than the i8254.  I hope the
> numbers are a little better on older hardware.
> 
> acpitimer_test_delay:  expected  0.000001000  actual  0.000010638  error  
> 0.000009638
> acpitimer_test_delay:  expected  0.000010000  actual  0.000015464  error  
> 0.000005464
> acpitimer_test_delay:  expected  0.000100000  actual  0.000107619  error  
> 0.000007619
> acpitimer_test_delay:  expected  0.001000000  actual  0.001007275  error  
> 0.000007275
> acpitimer_test_delay:  expected  0.010000000  actual  0.010007891  error  
> 0.000007891
> 
> acpihpet_test_delay:   expected  0.000001000  actual  0.000022208  error  
> 0.000021208
> acpihpet_test_delay:   expected  0.000010000  actual  0.000031690  error  
> 0.000021690
> acpihpet_test_delay:   expected  0.000100000  actual  0.000112647  error  
> 0.000012647
> acpihpet_test_delay:   expected  0.001000000  actual  0.001021480  error  
> 0.000021480
> acpihpet_test_delay:   expected  0.010000000  actual  0.010013736  error  
> 0.000013736
> 
> i8254_test_delay:      expected  0.000001000  actual  0.000040110  error  
> 0.000039110
> i8254_test_delay:      expected  0.000010000  actual  0.000039471  error  
> 0.000029471
> i8254_test_delay:      expected  0.000100000  actual  0.000128031  error  
> 0.000028031
> i8254_test_delay:      expected  0.001000000  actual  0.001024586  error  
> 0.000024586
> i8254_test_delay:      expected  0.010000000  actual  0.010021859  error  
> 0.000021859

cpu0: Intel(R) Core(TM)2 Duo CPU T7250 @ 2.00GHz, 2194.88 MHz, 06-0f-0d
cpu0: apic clock running at 199MHz
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpihpet0 at acpi0: 14318179 Hz
acpitimer_test_delay: expected 0.000001000 actual 0.000010267 error 0.000009267
acpitimer_test_delay: expected 0.000010000 actual 0.000018648 error 0.000008648
acpitimer_test_delay: expected 0.000100000 actual 0.000108254 error 0.000008254
acpitimer_test_delay: expected 0.001000000 actual 0.001009486 error 0.000009486
acpitimer_test_delay: expected 0.010000000 actual 0.010008186 error 0.000008186
acpihpet_test_delay: expected 0.000001000 actual 0.000003561 error 0.000002561
acpihpet_test_delay: expected 0.000010000 actual 0.000012781 error 0.000002781
acpihpet_test_delay: expected 0.000100000 actual 0.000102457 error 0.000002457
acpihpet_test_delay: expected 0.001000000 actual 0.001002641 error 0.000002641
acpihpet_test_delay: expected 0.010000000 actual 0.010004694 error 0.000004694
i8254_test_delay: expected 0.000001000 actual 0.000011245 error 0.000010245
i8254_test_delay: expected 0.000010000 actual 0.000018508 error 0.000008508
i8254_test_delay: expected 0.000100000 actual 0.000107625 error 0.000007625
i8254_test_delay: expected 0.001000000 actual 0.001010044 error 0.000010044
i8254_test_delay: expected 0.010000000 actual 0.027472138 error 0.017472138
kern.timecounter.hardware=acpihpet0
kern.timecounter.choice=i8254(0) acpihpet0(1000) acpitimer0(1000)

cpu0: 12th Gen Intel(R) Core(TM) i7-1260P, 1995.56 MHz, 06-9a-03
cpu0: apic clock running at 38MHz
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpihpet0 at acpi0: 19200000 Hz
acpitimer_test_delay: expected 0.000001000 actual 0.000005399 error 0.000004399
acpitimer_test_delay: expected 0.000010000 actual 0.000013089 error 0.000003089
acpitimer_test_delay: expected 0.000100000 actual 0.000104628 error 0.000004628
acpitimer_test_delay: expected 0.001000000 actual 0.001003442 error 0.000003442
acpitimer_test_delay: expected 0.010000000 actual 0.010002604 error 0.000002604
acpihpet_test_delay: expected 0.000001000 actual 0.000096019 error 0.000095019
acpihpet_test_delay: expected 0.000010000 actual 0.000096768 error 0.000086768
acpihpet_test_delay: expected 0.000100000 actual 0.000176536 error 0.000076536
acpihpet_test_delay: expected 0.001000000 actual 0.001096278 error 0.000096278
acpihpet_test_delay: expected 0.010000000 actual 0.010094748 error 0.000094748
i8254_test_delay: expected 0.000001000 actual 0.000165339 error 0.000164339
i8254_test_delay: expected 0.000010000 actual 0.000238166 error 0.000228166
i8254_test_delay: expected 0.000100000 actual 0.001575191 error 0.001475191
i8254_test_delay: expected 0.001000000 actual 0.014816185 error 0.013816185
i8254_test_delay: expected 0.010000000 actual 0.147270681 error 0.137270681
kern.timecounter.hardware=tsc
kern.timecounter.choice=i8254(0) tsc(2000) acpihpet0(1000) acpitimer0(1000)

cpu0: AMD Ryzen 5 2600X Six-Core Processor, 3593.93 MHz, 17-08-02
cpu0: apic clock running at 99MHz
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpihpet0 at acpi0: 14318180 Hz
acpitimer_test_delay: expected 0.000001000 actual 0.000017600 error 0.000016600
acpitimer_test_delay: expected 0.000010000 actual 0.000025143 error 0.000015143
acpitimer_test_delay: expected 0.000100000 actual 0.000114540 error 0.000014540
acpitimer_test_delay: expected 0.001000000 actual 0.001009696 error 0.000009696
acpitimer_test_delay: expected 0.010000000 actual 0.010013494 error 0.000013494
acpihpet_test_delay: expected 0.000001000 actual 0.000012432 error 0.000011432
acpihpet_test_delay: expected 0.000010000 actual 0.000017600 error 0.000007600
acpihpet_test_delay: expected 0.000100000 actual 0.000112374 error 0.000012374
acpihpet_test_delay: expected 0.001000000 actual 0.001009137 error 0.000009137
acpihpet_test_delay: expected 0.010000000 actual 0.010011188 error 0.000011188
i8254_test_delay: expected 0.000001000 actual 0.000017530 error 0.000016530
i8254_test_delay: expected 0.000010000 actual 0.000024934 error 0.000014934
i8254_test_delay: expected 0.000100000 actual 0.000114400 error 0.000014400
i8254_test_delay: expected 0.001000000 actual 0.001010673 error 0.000010673
i8254_test_delay: expected 0.010000000 actual 0.010016078 error 0.000016078
kern.timecounter.hardware=acpihpet0
kern.timecounter.choice=i8254(0) acpihpet0(1000) tsc(2000) acpitimer0(1000)

Reply via email to