On Sat, Feb 13, 2016 at 03:46:16PM +0000, Mark Dixon
wrote:> I don't think I can clock it down, although the UEFI bios screens are
> massively confusing so I could be wrong.
>
> Verbose dmesg:
Might be, try the following (mostly debugging) change.
diff --git a/sys/boot/i386/libi386/time.c b/sys/boot/i386/libi386/time.c
index c27dcf6..592d64a 100644
--- a/sys/boot/i386/libi386/time.c
+++ b/sys/boot/i386/libi386/time.c
@@ -97,8 +97,8 @@ time(time_t *t)
* Resolution of this function is variable, but typically around
* 1ms.
*/
-void
-delay(int period)
+static void
+delay_bios(int period)
{
v86.ctl = 0;
v86.addr = 0x15; /* int 0x15, function 0x86 */
@@ -107,3 +107,53 @@ delay(int period)
v86.edx = period & 0xffff;
v86int();
}
+
+static uint64_t rd;
+
+static __inline uint64_t
+rdtsc(void)
+{
+ uint64_t rv;
+
+ __asm __volatile("rdtsc" : "=A" (rv));
+ return (rv);
+}
+
+static void
+delay_rdtsc_calibrate(void)
+{
+ int x1, x2;
+ uint64_t s, f;
+
+ for (x1 = bios_seconds(); x1 == (x2 = bios_seconds());)
+ ;
+ s = rdtsc();
+ for (; x2 == (x1 = bios_seconds());)
+ ;
+ f = rdtsc();
+ rd = f - s;
+ printf("rd %llx\n", rd);
+}
+
+static void
+delay_rdtsc(int period)
+{
+ uint64_t x;
+
+ x = rdtsc() + rd / 1000000;
+ while (rdtsc() < x)
+ ;
+}
+
+void
+delay(int period)
+{
+
+ if (0) {
+ delay_bios(period);
+ } else {
+ if (rd == 0)
+ delay_rdtsc_calibrate();
+ delay_rdtsc(period);
+ }
+}