Implement delay() using TSC
- Calculate delay using 64-bit RDTSC instruction
- Enable tsc_delay() as delay(9) backend
- Use tsc_delay() only when TSC is invariant
- Configure tsc_delay() after primary CPU is identified
- Assume all CPUs are identical
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
index df6c623..0863306 100644
--- a/sys/arch/amd64/amd64/cpu.c
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -330,6 +330,7 @@ cpu_attach(struct device *parent, struct device *self, void
*aux)
vaddr_t kstack;
struct pcb *pcb;
#endif
+ void tsc_delay_init(struct cpu_info *);
/*
* If we're an Application Processor, allocate a cpu_info
@@ -409,6 +410,7 @@ cpu_attach(struct device *parent, struct device *self, void
*aux)
#endif /* MTRR */
cpu_init(ci);
cpu_init_mwait(sc);
+ tsc_delay_init(ci);
break;
case CPU_ROLE_BP:
@@ -432,6 +434,7 @@ cpu_attach(struct device *parent, struct device *self, void
*aux)
ioapic_bsp_id = caa->cpu_number;
#endif
cpu_init_mwait(sc);
+ tsc_delay_init(ci);
break;
case CPU_ROLE_AP:
diff --git a/sys/arch/amd64/amd64/tsc.c b/sys/arch/amd64/amd64/tsc.c
new file mode 100644
index 0000000..15242ca
--- /dev/null
+++ b/sys/arch/amd64/amd64/tsc.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016 Masao Uebayashi <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/stdint.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+
+void tsc_delay_init(struct cpu_info *);
+void tsc_delay(int);
+uint64_t tsc2usec(uint64_t n);
+
+int64_t tsc_delay_mult;
+
+void
+tsc_delay_init(struct cpu_info *ci)
+{
+#ifdef DIAGNOSTIC
+ KASSERT(ci->ci_tsc_freq != 0);
+#endif
+ if ((ci->ci_flags & CPUF_CONST_TSC) == 0)
+ return;
+
+ tsc_delay_mult = ci->ci_tsc_freq / 1000000;
+ delay_func = tsc_delay;
+}
+
+void
+tsc_delay(int usec)
+{
+ int64_t n;
+ uint64_t now, prev;
+
+ n = tsc_delay_mult * usec;
+ prev = rdtsc();
+ while (n > 0) {
+ CPU_BUSY_CYCLE();
+ now = rdtsc();
+ if (now < prev)
+ n -= UINT64_MAX - (prev - now);
+ else
+ n -= now - prev;
+ prev = now;
+ }
+}
+
+uint64_t
+tsc2usec(uint64_t n)
+{
+ struct cpu_info *ci = curcpu();
+
+ return n / ci->ci_tsc_freq * 1000000;
+}
diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64
index 5d58b34..d101cf2 100644
--- a/sys/arch/amd64/conf/files.amd64
+++ b/sys/arch/amd64/conf/files.amd64
@@ -97,6 +97,7 @@ define cpu {[apid = -1]}
device cpu
attach cpu at mainbus
file arch/amd64/amd64/cpu.c cpu
+file arch/amd64/amd64/tsc.c cpu
define lapic