tsc: configure LFENCE to serialize dispatch before testing TSC sync
authorcheloha <cheloha@openbsd.org>
Thu, 15 Sep 2022 19:30:51 +0000 (19:30 +0000)
committercheloha <cheloha@openbsd.org>
Thu, 15 Sep 2022 19:30:51 +0000 (19:30 +0000)
commit024d4e74c5087d49565e08031bf85b11a9000cc6
tree2e1f4aa8090ff2639d26db7426cc579ff4d1529d
parent74edc71ccae4051eda11fa3fb27de52f69e7512e
tsc: configure LFENCE to serialize dispatch before testing TSC sync

On AMD CPUs, LFENCE does not serialize instruction dispatch until MSR
C001_1029[1] is properly configured.  We do this in identifycpu(); see
amd64/identcpu.c,v 1.103.

The upshot is that the first TSC synchronization test is currently
invalid on most AMD CPUs because the LFENCE in the test loop does not
ensure that the AP loads the BP's latest TSC value before executing
RDTSC.  So the synchronization test is yielding false positives on AMD
CPUs where the TSCs are actually synchronized.

The simplest fix is to wait until after the secondary CPU runs
identifycpu() in cpu_hatch() to test TSC synchronization.

Moving the TSC sync test after CPU identification means that we can
remove the CPUID() calls from tsc.c: the CPU feature flags are set in
identifycpu() so we no longer need to test for IA32_TSC_ADJUST support
by hand.

While we are at it, we should also pass the correct cpu_info pointer
to tsc_test_sync_bp().  It was unused before, so the bug was harmless,
but we definitely need the BP's cpu_info pointer, not the AP's pointer.

Unfortunately, this change does not fix the TSC sync problems we've
been seeing on e.g. dv@'s and jmc@'s Ryzen 5 machines.  Hopefully the
problem on those machines is buggy firmware and not another
architectural misunderstanding on my part.

Prompted by robert@.  Problem diagnosed by brynet@.  With input from
robert@, brynet@, and deraadt@.  Tested by robert@, brynet@, dv@,
phessler@, and jmc@.

ok robert@ brynet@ sthen@
sys/arch/amd64/amd64/cpu.c
sys/arch/amd64/amd64/tsc.c