From 81ef01623ab77afbddf61dd8700a4241cbda76d9 Mon Sep 17 00:00:00 2001 From: cheloha Date: Mon, 12 Sep 2022 10:58:05 +0000 Subject: [PATCH] acpihpet(4): acpihpet_delay: only use lower 32 bits of counter We can't use acpihpet_r() to implement acpihpet_delay(). Even if we made acpihpet_r() atomic on amd64, i386 would still be incapable of doing atomic 8-byte reads. As-is, the code does a split read on all platforms, which may or may not already be causing problems with TSC calibration: https://marc.info/?l=openbsd-tech&m=166220561709496&w=2 Switch from acpihpet_r() to bus_space_read_4() and only use the lower 32 bits of the counter. This makes acpihpet_delay() slightly larger, but unless we want two acpihpet_delay() implementations we have no choice. Link: https://marc.info/?l=openbsd-tech&m=166165347220077&w=2 ok jsg@ --- sys/dev/acpi/acpihpet.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sys/dev/acpi/acpihpet.c b/sys/dev/acpi/acpihpet.c index bb1e6c56947..7b7898ff185 100644 --- a/sys/dev/acpi/acpihpet.c +++ b/sys/dev/acpi/acpihpet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpihpet.c,v 1.28 2022/08/25 18:01:54 cheloha Exp $ */ +/* $OpenBSD: acpihpet.c,v 1.29 2022/09/12 10:58:05 cheloha Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * @@ -281,13 +281,19 @@ acpihpet_attach(struct device *parent, struct device *self, void *aux) void acpihpet_delay(int usecs) { - uint64_t c, s; + uint64_t count = 0, cycles; struct acpihpet_softc *sc = hpet_timecounter.tc_priv; + uint32_t val1, val2; - s = acpihpet_r(sc->sc_iot, sc->sc_ioh, HPET_MAIN_COUNTER); - c = usecs * hpet_timecounter.tc_frequency / 1000000; - while (acpihpet_r(sc->sc_iot, sc->sc_ioh, HPET_MAIN_COUNTER) - s < c) + val2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, HPET_MAIN_COUNTER); + cycles = usecs * hpet_timecounter.tc_frequency / 1000000; + while (count < cycles) { CPU_BUSY_CYCLE(); + val1 = val2; + val2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + HPET_MAIN_COUNTER); + count += val2 - val1; + } } u_int -- 2.20.1