diff options
author | Scott Soule Cheloha <cheloha@cvs.openbsd.org> | 2022-09-12 10:58:06 +0000 |
---|---|---|
committer | Scott Soule Cheloha <cheloha@cvs.openbsd.org> | 2022-09-12 10:58:06 +0000 |
commit | e9554cfa2874d6ab11f3fd3cc518cad9f7798383 (patch) | |
tree | 8cdaa90d01252bd3454d748f24a046116e63b563 /sys/dev | |
parent | b2170cf8198db9bff0e63c94394c1e924bbf7254 (diff) |
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@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/acpi/acpihpet.c | 16 |
1 files 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 <tholo@sigmasoft.com> * @@ -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 |