This always happens when OpenBSD runs on FreeBSD bhyve.

Usually OpenBSD gets TSC frequency from CPUID 0x15,
but FreeBSD bhyve disables it by the following commit.

https://cgit.freebsd.org/src/commit/?id=ec048c755076befde5bf533911c70a01d59abdda

Then OpenBSD tries to measure TSC frequency by delay(9) in `measure_tsc_freq`
function. This function waits in 100ms but i8254_delay error is relatively
large in this environment. So, the difference in `tc_get_count` become bigger
than 100ms.

I could see the i8254_delay error by the following patch.

diff --git a/sys/arch/amd64/amd64/tsc.c b/sys/arch/amd64/amd64/tsc.c
index c4d3acda8c7..ab34df4463c 100644
--- a/sys/arch/amd64/amd64/tsc.c
+++ b/sys/arch/amd64/amd64/tsc.c
@@ -182,7 +182,7 @@ measure_tsc_freq(struct timecounter *tc)
                        continue;

                usec = calculate_tc_delay(tc, count1, count2);
-
+               printf("usec - delay_usec = %d\n", usec - delay_usec);
                if ((usec < (delay_usec - RECALIBRATE_DELAY_THRESHOLD)) ||
                    (usec > (delay_usec + RECALIBRATE_DELAY_THRESHOLD)))
                        continue;

This shows as follows.

```
usec - delay_usec = 98
usec - delay_usec = 98
usec - delay_usec = 100
```

These are bigger than RECALIBRATE_DELAY_THRESHOLD (= 50).

When I change the patch like this.

diff --git a/sys/arch/amd64/amd64/tsc.c b/sys/arch/amd64/amd64/tsc.c
index c4d3acda8c7..ab34df4463c 100644
--- a/sys/arch/amd64/amd64/tsc.c
+++ b/sys/arch/amd64/amd64/tsc.c
@@ -168,7 +168,7 @@ measure_tsc_freq(struct timecounter *tc)

        min_freq = ULLONG_MAX;

-       delay_usec = 100000;
+       delay_usec = 10000;
        for (i = 0; i < 3; i++) {
                s = intr_disable();

@@ -182,7 +182,7 @@ measure_tsc_freq(struct timecounter *tc)
                        continue;

                usec = calculate_tc_delay(tc, count1, count2);
-
+               printf("usec - delay_usec = %d\n", usec - delay_usec);
                if ((usec < (delay_usec - RECALIBRATE_DELAY_THRESHOLD)) ||
                    (usec > (delay_usec + RECALIBRATE_DELAY_THRESHOLD)))
                        continue;

I've got following results.

```
usec - delay_usec = 28
usec - delay_usec = 22
usec - delay_usec = 25
```

So, I want to change `delay_usec` value from 100000 to 10000.
Is it OK?

--
Yuichiro NAITO (naito.yuich...@gmail.com)

Reply via email to