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)