Module Name: src
Committed By: msaitoh
Date: Mon Jun 15 09:09:24 UTC 2020
Modified Files:
src/sys/arch/amd64/amd64: cpufunc.S
src/sys/arch/i386/i386: cpufunc.S
src/sys/arch/x86/include: cpu_counter.h cpufunc.h
src/sys/arch/x86/x86: cpu.c hyperv.c tsc.c tsc.h
src/sys/rump/librump/rumpkern/arch/x86: rump_x86_cpu_counter.c
Log Message:
Serialize rdtsc using with lfence, mfence or cpuid to read TSC more precisely.
x86/x86/tsc.c rev. 1.67 reduced cache problem and got big improvement, but it
still has room. I measured the effect of lfence, mfence, cpuid and rdtscp.
The impact to TSC skew and/or drift is:
AMD: mfence > rdtscp > cpuid > lfence-serialize > lfence = nomodify
Intel: lfence > rdtscp > cpuid > nomodify
So, mfence is the best on AMD and lfence is the best on Intel. If it has no
SSE2, we can use cpuid.
NOTE:
- An AMD's document says DE_CFG_LFENCE_SERIALIZE bit can be used for
serializing, but it's not so good.
- On Intel i386(not amd64), it seems the improvement is very little.
- rdtscp instruct can be used as serializing instruction + rdtsc, but
it's not good as [lm]fence. Both Intel and AMD's document say that
the latency of rdtscp is bigger than rdtsc, so I suspect the difference
of the result comes from it.
To generate a diff of this commit:
cvs rdiff -u -r1.60 -r1.61 src/sys/arch/amd64/amd64/cpufunc.S
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/i386/i386/cpufunc.S
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/include/cpu_counter.h
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/x86/include/cpufunc.h
cvs rdiff -u -r1.193 -r1.194 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/x86/x86/hyperv.c
cvs rdiff -u -r1.50 -r1.51 src/sys/arch/x86/x86/tsc.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/x86/tsc.h
cvs rdiff -u -r1.1 -r1.2 \
src/sys/rump/librump/rumpkern/arch/x86/rump_x86_cpu_counter.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/amd64/amd64/cpufunc.S
diff -u src/sys/arch/amd64/amd64/cpufunc.S:1.60 src/sys/arch/amd64/amd64/cpufunc.S:1.61
--- src/sys/arch/amd64/amd64/cpufunc.S:1.60 Sat Jun 13 23:58:51 2020
+++ src/sys/arch/amd64/amd64/cpufunc.S Mon Jun 15 09:09:23 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpufunc.S,v 1.60 2020/06/13 23:58:51 ad Exp $ */
+/* $NetBSD: cpufunc.S,v 1.61 2020/06/15 09:09:23 msaitoh Exp $ */
/*
* Copyright (c) 1998, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -207,38 +207,62 @@ END(x86_hotpatch)
#endif /* !XENPV */
/*
- * Could be exact same as cpu_counter, but KMSAN needs to have the correct
- * size of the return value.
+ * cpu_counter and cpu_counter32 could be exact same, but KMSAN needs to have
+ * the correct size of the return value.
*/
-ENTRY(cpu_counter32)
- movq CPUVAR(CURLWP), %rcx
-1:
- movq L_NCSW(%rcx), %rdi
- rdtsc
- addl CPUVAR(CC_SKEW), %eax
- cmpq %rdi, L_NCSW(%rcx)
- jne 2f
- KMSAN_INIT_RET(4)
- ret
-2:
- jmp 1b
-END(cpu_counter32)
+#define SERIALIZE_lfence lfence
+#define SERIALIZE_mfence mfence
-ENTRY(cpu_counter)
- movq CPUVAR(CURLWP), %rcx
-1:
- movq L_NCSW(%rcx), %rdi
- rdtsc
- shlq $32, %rdx
- orq %rdx, %rax
- addq CPUVAR(CC_SKEW), %rax
- cmpq %rdi, L_NCSW(%rcx)
- jne 2f
- KMSAN_INIT_RET(8)
- ret
-2:
- jmp 1b
-END(cpu_counter)
+#define ADD_counter32 addl CPUVAR(CC_SKEW), %eax
+#define ADD_counter shlq $32, %rdx ;\
+ orq %rdx, %rax ;\
+ addq CPUVAR(CC_SKEW), %rax
+
+#define RSIZE_counter32 4
+#define RSIZE_counter 8
+
+#define CPU_COUNTER_FENCE(counter, fence) \
+ENTRY(cpu_ ## counter ## _ ## fence) ;\
+ movq CPUVAR(CURLWP), %rcx ;\
+1: ;\
+ movq L_NCSW(%rcx), %rdi ;\
+ SERIALIZE_ ## fence ;\
+ rdtsc ;\
+ ADD_ ## counter ;\
+ cmpq %rdi, L_NCSW(%rcx) ;\
+ jne 2f ;\
+ KMSAN_INIT_RET(RSIZE_ ## counter) ;\
+ ret ;\
+2: ;\
+ jmp 1b ;\
+END(cpu_ ## counter ## _ ## fence)
+
+CPU_COUNTER_FENCE(counter, lfence)
+CPU_COUNTER_FENCE(counter, mfence)
+CPU_COUNTER_FENCE(counter32, lfence)
+CPU_COUNTER_FENCE(counter32, mfence)
+
+#define CPU_COUNTER_CPUID(counter) \
+ENTRY(cpu_ ## counter ## _cpuid) ;\
+ movq %rbx, %r9 ;\
+ movq CPUVAR(CURLWP), %r8 ;\
+1: ;\
+ movq L_NCSW(%r8), %rdi ;\
+ xor %eax, %eax ;\
+ cpuid ;\
+ rdtsc ;\
+ ADD_ ## counter ;\
+ cmpq %rdi, L_NCSW(%r8) ;\
+ jne 2f ;\
+ movq %r9, %rbx ;\
+ KMSAN_INIT_RET(RSIZE_ ## counter) ;\
+ ret ;\
+2: ;\
+ jmp 1b ;\
+END(cpu_ ## counter ## _cpuid)
+
+CPU_COUNTER_CPUID(counter)
+CPU_COUNTER_CPUID(counter32)
ENTRY(rdmsr_safe)
movq CPUVAR(CURLWP), %r8
Index: src/sys/arch/i386/i386/cpufunc.S
diff -u src/sys/arch/i386/i386/cpufunc.S:1.46 src/sys/arch/i386/i386/cpufunc.S:1.47
--- src/sys/arch/i386/i386/cpufunc.S:1.46 Sat Jun 13 23:58:52 2020
+++ src/sys/arch/i386/i386/cpufunc.S Mon Jun 15 09:09:23 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpufunc.S,v 1.46 2020/06/13 23:58:52 ad Exp $ */
+/* $NetBSD: cpufunc.S,v 1.47 2020/06/15 09:09:23 msaitoh Exp $ */
/*-
* Copyright (c) 1998, 2007, 2020 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
#include <sys/errno.h>
#include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.46 2020/06/13 23:58:52 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.47 2020/06/15 09:09:23 msaitoh Exp $");
#include "opt_xen.h"
@@ -163,23 +163,59 @@ ENTRY(msr_onfault)
ret
END(msr_onfault)
-ENTRY(cpu_counter)
- pushl %ebx
- movl CPUVAR(CURLWP), %ecx
-1:
- movl L_NCSW(%ecx), %ebx
- rdtsc
- addl CPUVAR(CC_SKEW), %eax
- adcl CPUVAR(CC_SKEW+4), %edx
- cmpl %ebx, L_NCSW(%ecx)
- jne 2f
- popl %ebx
- ret
-2:
- jmp 1b
-END(cpu_counter)
+#define ADD_counter32 addl CPUVAR(CC_SKEW), %eax
+#define ADD_counter ADD_counter32 ;\
+ adcl CPUVAR(CC_SKEW+4), %edx
+
+#define SERIALIZE_lfence lfence
+#define SERIALIZE_mfence mfence
+
+#define CPU_COUNTER_FENCE(counter, fence) \
+ENTRY(cpu_ ## counter ## _ ## fence) ;\
+ pushl %ebx ;\
+ movl CPUVAR(CURLWP), %ecx ;\
+1: ;\
+ movl L_NCSW(%ecx), %ebx ;\
+ SERIALIZE_ ## fence ;\
+ rdtsc ;\
+ ADD_ ## counter ;\
+ cmpl %ebx, L_NCSW(%ecx) ;\
+ jne 2f ;\
+ popl %ebx ;\
+ ret ;\
+2: ;\
+ jmp 1b ;\
+END(cpu_ ## counter ## _ ## fence)
+
+CPU_COUNTER_FENCE(counter, lfence)
+CPU_COUNTER_FENCE(counter, mfence)
+CPU_COUNTER_FENCE(counter32, lfence)
+CPU_COUNTER_FENCE(counter32, mfence)
+
+#define CPU_COUNTER_CPUID(counter) \
+ENTRY(cpu_ ## counter ## _cpuid) ;\
+ pushl %ebx ;\
+ pushl %esi ;\
+ movl CPUVAR(CURLWP), %ecx ;\
+1: ;\
+ movl L_NCSW(%ecx), %esi ;\
+ pushl %ecx ;\
+ xor %eax, %eax ;\
+ cpuid ;\
+ rdtsc ;\
+ ADD_ ## counter ;\
+ popl %ecx ;\
+ cmpl %esi, L_NCSW(%ecx) ;\
+ jne 2f ;\
+ popl %esi ;\
+ popl %ebx ;\
+ ret ;\
+2: ;\
+ jmp 1b ;\
+END(cpu_ ## counter ##_cpuid)
-STRONG_ALIAS(cpu_counter32, cpu_counter)
+CPU_COUNTER_CPUID(counter)
+CPU_COUNTER_CPUID(counter32)
ENTRY(breakpoint)
pushl %ebp
Index: src/sys/arch/x86/include/cpu_counter.h
diff -u src/sys/arch/x86/include/cpu_counter.h:1.6 src/sys/arch/x86/include/cpu_counter.h:1.7
--- src/sys/arch/x86/include/cpu_counter.h:1.6 Fri May 8 22:01:54 2020
+++ src/sys/arch/x86/include/cpu_counter.h Mon Jun 15 09:09:23 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_counter.h,v 1.6 2020/05/08 22:01:54 ad Exp $ */
+/* $NetBSD: cpu_counter.h,v 1.7 2020/06/15 09:09:23 msaitoh Exp $ */
/*-
* Copyright (c) 2000, 2008 The NetBSD Foundation, Inc.
@@ -34,10 +34,19 @@
#ifdef _KERNEL
-uint64_t cpu_counter(void);
-uint32_t cpu_counter32(void);
-uint64_t cpu_frequency(struct cpu_info *);
-int cpu_hascounter(void);
+#include <sys/lwp.h>
+
+extern uint64_t cpu_frequency(struct cpu_info *);
+extern int cpu_hascounter(void);
+extern uint64_t (*cpu_counter)(void);
+extern uint32_t (*cpu_counter32)(void);
+
+extern uint64_t cpu_counter_cpuid(void);
+extern uint64_t cpu_counter_lfence(void);
+extern uint64_t cpu_counter_mfence(void);
+extern uint32_t cpu_counter32_cpuid(void);
+extern uint32_t cpu_counter32_lfence(void);
+extern uint32_t cpu_counter32_mfence(void);
#endif /* _KERNEL */
Index: src/sys/arch/x86/include/cpufunc.h
diff -u src/sys/arch/x86/include/cpufunc.h:1.40 src/sys/arch/x86/include/cpufunc.h:1.41
--- src/sys/arch/x86/include/cpufunc.h:1.40 Sun Jun 14 16:12:05 2020
+++ src/sys/arch/x86/include/cpufunc.h Mon Jun 15 09:09:23 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpufunc.h,v 1.40 2020/06/14 16:12:05 riastradh Exp $ */
+/* $NetBSD: cpufunc.h,v 1.41 2020/06/15 09:09:23 msaitoh Exp $ */
/*
* Copyright (c) 1998, 2007, 2019 The NetBSD Foundation, Inc.
@@ -89,19 +89,37 @@ invpcid(register_t op, uint64_t pcid, va
);
}
-static inline uint64_t
-rdtsc(void)
-{
- uint32_t low, high;
+extern uint64_t (*rdtsc)(void);
- __asm volatile (
- "rdtsc"
- : "=a" (low), "=d" (high)
- :
- );
+#define _SERIALIZE_lfence __asm volatile ("lfence")
+#define _SERIALIZE_mfence __asm volatile ("mfence")
+#define _SERIALIZE_cpuid __asm volatile ("xor %%eax, %%eax;cpuid" ::: \
+ "eax", "ebx", "ecx", "edx");
+
+#define RDTSCFUNC(fence) \
+static inline uint64_t \
+rdtsc_##fence(void) \
+{ \
+ uint32_t low, high; \
+ \
+ _SERIALIZE_##fence; \
+ __asm volatile ( \
+ "rdtsc" \
+ : "=a" (low), "=d" (high) \
+ : \
+ ); \
+ \
+ return (low | ((uint64_t)high << 32)); \
+}
+
+RDTSCFUNC(lfence)
+RDTSCFUNC(mfence)
+RDTSCFUNC(cpuid)
+
+#undef _SERIALIZE_LFENCE
+#undef _SERIALIZE_MFENCE
+#undef _SERIALIZE_CPUID
- return (low | ((uint64_t)high << 32));
-}
#ifndef XENPV
struct x86_hotpatch_source {
Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.193 src/sys/arch/x86/x86/cpu.c:1.194
--- src/sys/arch/x86/x86/cpu.c:1.193 Sat Jun 13 20:01:27 2020
+++ src/sys/arch/x86/x86/cpu.c Mon Jun 15 09:09:24 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.193 2020/06/13 20:01:27 ad Exp $ */
+/* $NetBSD: cpu.c,v 1.194 2020/06/15 09:09:24 msaitoh Exp $ */
/*
* Copyright (c) 2000-2020 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.193 2020/06/13 20:01:27 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.194 2020/06/15 09:09:24 msaitoh Exp $");
#include "opt_ddb.h"
#include "opt_mpbios.h" /* for MPDEBUG */
@@ -444,6 +444,7 @@ cpu_attach(device_t parent, device_t sel
*/
atomic_or_32(&ci->ci_flags, CPUF_PRESENT | CPUF_PRIMARY);
cpu_intr_init(ci);
+ tsc_setfunc(ci);
cpu_get_tsc_freq(ci);
cpu_init(ci);
#ifdef i386
Index: src/sys/arch/x86/x86/hyperv.c
diff -u src/sys/arch/x86/x86/hyperv.c:1.9 src/sys/arch/x86/x86/hyperv.c:1.10
--- src/sys/arch/x86/x86/hyperv.c:1.9 Sun May 17 11:54:39 2020
+++ src/sys/arch/x86/x86/hyperv.c Mon Jun 15 09:09:24 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: hyperv.c,v 1.9 2020/05/17 11:54:39 nonaka Exp $ */
+/* $NetBSD: hyperv.c,v 1.10 2020/06/15 09:09:24 msaitoh Exp $ */
/*-
* Copyright (c) 2009-2012,2016-2017 Microsoft Corp.
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
#ifdef __KERNEL_RCSID
-__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.9 2020/05/17 11:54:39 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hyperv.c,v 1.10 2020/06/15 09:09:24 msaitoh Exp $");
#endif
#ifdef __FBSDID
__FBSDID("$FreeBSD: head/sys/dev/hyperv/vmbus/hyperv.c 331757 2018-03-30 02:25:12Z emaste $");
@@ -178,8 +178,10 @@ struct hyperv_ref_tsc {
static struct hyperv_ref_tsc hyperv_ref_tsc;
+static u_int hyperv_tsc_timecount(struct timecounter *);
+
static struct timecounter hyperv_tsc_timecounter = {
- .tc_get_timecount = NULL, /* based on CPU vendor. */
+ .tc_get_timecount = hyperv_tsc_timecount,
.tc_counter_mask = 0xffffffff,
.tc_frequency = HYPERV_TIMER_FREQ,
.tc_name = "Hyper-V-TSC",
@@ -194,51 +196,45 @@ atomic_load_acq_int(volatile u_int *p)
return r;
}
-#define HYPERV_TSC_TIMECOUNT(fence) \
-static uint64_t \
-hyperv_tc64_tsc_##fence(void) \
-{ \
- struct hyperv_reftsc *tsc_ref = hyperv_ref_tsc.tsc_ref; \
- uint32_t seq; \
- \
- while ((seq = atomic_load_acq_int(&tsc_ref->tsc_seq)) != 0) { \
- uint64_t disc, ret, tsc; \
- uint64_t scale = tsc_ref->tsc_scale; \
- int64_t ofs = tsc_ref->tsc_ofs; \
- \
- x86_##fence(); \
- tsc = cpu_counter(); \
- \
- /* ret = ((tsc * scale) >> 64) + ofs */ \
- __asm__ __volatile__ ("mulq %3" : \
- "=d" (ret), "=a" (disc) : \
- "a" (tsc), "r" (scale)); \
- ret += ofs; \
- \
- __insn_barrier(); \
- if (tsc_ref->tsc_seq == seq) \
- return ret; \
- \
- /* Sequence changed; re-sync. */ \
- } \
- /* Fallback to the generic timecounter, i.e. rdmsr. */ \
- return rdmsr(MSR_HV_TIME_REF_COUNT); \
-} \
- \
-static u_int \
-hyperv_tsc_timecount_##fence(struct timecounter *tc __unused) \
-{ \
- \
- return hyperv_tc64_tsc_##fence(); \
+static uint64_t
+hyperv_tc64_tsc(void)
+{
+ struct hyperv_reftsc *tsc_ref = hyperv_ref_tsc.tsc_ref;
+ uint32_t seq;
+
+ while ((seq = atomic_load_acq_int(&tsc_ref->tsc_seq)) != 0) {
+ uint64_t disc, ret, tsc;
+ uint64_t scale = tsc_ref->tsc_scale;
+ int64_t ofs = tsc_ref->tsc_ofs;
+
+ tsc = cpu_counter();
+
+ /* ret = ((tsc * scale) >> 64) + ofs */
+ __asm__ __volatile__ ("mulq %3" :
+ "=d" (ret), "=a" (disc) :
+ "a" (tsc), "r" (scale));
+ ret += ofs;
+
+ __insn_barrier();
+ if (tsc_ref->tsc_seq == seq)
+ return ret;
+
+ /* Sequence changed; re-sync. */
+ }
+ /* Fallback to the generic timecounter, i.e. rdmsr. */
+ return rdmsr(MSR_HV_TIME_REF_COUNT);
}
-HYPERV_TSC_TIMECOUNT(lfence);
-HYPERV_TSC_TIMECOUNT(mfence);
+static u_int
+hyperv_tsc_timecount(struct timecounter *tc __unused)
+{
+
+ return hyperv_tc64_tsc();
+}
static bool
hyperv_tsc_tcinit(void)
{
- hyperv_tc64_t tc64 = NULL;
uint64_t orig_msr, msr;
if ((hyperv_features &
@@ -247,24 +243,6 @@ hyperv_tsc_tcinit(void)
(cpu_feature[0] & CPUID_SSE2) == 0) /* SSE2 for mfence/lfence */
return false;
- switch (cpu_vendor) {
- case CPUVENDOR_AMD:
- hyperv_tsc_timecounter.tc_get_timecount =
- hyperv_tsc_timecount_mfence;
- tc64 = hyperv_tc64_tsc_mfence;
- break;
-
- case CPUVENDOR_INTEL:
- hyperv_tsc_timecounter.tc_get_timecount =
- hyperv_tsc_timecount_lfence;
- tc64 = hyperv_tc64_tsc_lfence;
- break;
-
- default:
- /* Unsupport CPU vendors. */
- return false;
- }
-
hyperv_ref_tsc.tsc_ref = (void *)uvm_km_alloc(kernel_map,
PAGE_SIZE, PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_ZERO);
if (hyperv_ref_tsc.tsc_ref == NULL) {
@@ -287,14 +265,14 @@ hyperv_tsc_tcinit(void)
wrmsr(MSR_HV_REFERENCE_TSC, msr);
/* Install 64 bits timecounter method for other modules to use. */
- hyperv_tc64 = tc64;
+ hyperv_tc64 = hyperv_tc64_tsc;
/* Register "enlightened" timecounter. */
tc_init(&hyperv_tsc_timecounter);
return true;
}
-#endif
+#endif /* __amd64__ */
static void
delay_tc(unsigned int n)
Index: src/sys/arch/x86/x86/tsc.c
diff -u src/sys/arch/x86/x86/tsc.c:1.50 src/sys/arch/x86/x86/tsc.c:1.51
--- src/sys/arch/x86/x86/tsc.c:1.50 Sun Jun 14 23:24:20 2020
+++ src/sys/arch/x86/x86/tsc.c Mon Jun 15 09:09:24 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: tsc.c,v 1.50 2020/06/14 23:24:20 ad Exp $ */
+/* $NetBSD: tsc.c,v 1.51 2020/06/15 09:09:24 msaitoh Exp $ */
/*-
* Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.50 2020/06/14 23:24:20 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.51 2020/06/15 09:09:24 msaitoh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -59,6 +59,9 @@ static uint64_t tsc_dummy_cacheline __ca
uint64_t tsc_freq __read_mostly; /* exported for sysctl */
static int64_t tsc_drift_max = 1000; /* max cycles */
static int64_t tsc_drift_observed;
+uint64_t (*rdtsc)(void) = rdtsc_cpuid;
+uint64_t (*cpu_counter)(void) = cpu_counter_cpuid;
+uint32_t (*cpu_counter32)(void) = cpu_counter32_cpuid;
int tsc_user_enabled = 1;
@@ -148,6 +151,51 @@ tsc_is_invariant(void)
return invariant;
}
+/* Setup function porniters for rdtsc() and timecounter(9). */
+void
+tsc_setfunc(struct cpu_info *ci)
+{
+ bool use_lfence, use_mfence;
+
+ use_lfence = use_mfence = false;
+
+ /*
+ * XXX On AMD, we might be able to use lfence for some cases:
+ * a) if MSR_DE_CFG exist and the bit 1 is set.
+ * b) family == 0x0f or 0x11. Those have no MSR_DE_CFG and
+ * lfence is always serializing.
+ *
+ * We don't use it because the test result showed mfence was better
+ * than lfence with MSR_DE_CFG.
+ */
+ if (cpu_vendor == CPUVENDOR_AMD)
+ use_mfence = true;
+ else if (cpu_vendor == CPUVENDOR_INTEL)
+ use_lfence = true;
+
+ /* LFENCE and MFENCE are applicable if SSE2 is set. */
+ if ((ci->ci_feat_val[0] & CPUID_SSE2) == 0)
+ use_lfence = use_mfence = false;
+
+#define TSC_SETFUNC(fence) \
+ do { \
+ rdtsc = rdtsc_##fence; \
+ cpu_counter = cpu_counter_##fence; \
+ cpu_counter32 = cpu_counter32_##fence; \
+ } while (/* CONSTCOND */ 0)
+
+
+ if (use_lfence)
+ TSC_SETFUNC(lfence);
+ else if (use_mfence)
+ TSC_SETFUNC(mfence);
+ else
+ TSC_SETFUNC(cpuid);
+
+ aprint_verbose_dev(ci->ci_dev, "Use %s to serialize rdtsc\n",
+ use_lfence ? "lfence" : (use_mfence ? "mfence" : "cpuid"));
+}
+
/*
* Initialize timecounter(9) and DELAY() function of TSC.
*
Index: src/sys/arch/x86/x86/tsc.h
diff -u src/sys/arch/x86/x86/tsc.h:1.6 src/sys/arch/x86/x86/tsc.h:1.7
--- src/sys/arch/x86/x86/tsc.h:1.6 Mon Oct 2 19:23:16 2017
+++ src/sys/arch/x86/x86/tsc.h Mon Jun 15 09:09:24 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: tsc.h,v 1.6 2017/10/02 19:23:16 maxv Exp $ */
+/* $NetBSD: tsc.h,v 1.7 2020/06/15 09:09:24 msaitoh Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -27,6 +27,7 @@
*/
bool tsc_is_invariant(void);
+void tsc_setfunc(struct cpu_info *);
void tsc_tc_init(void);
void tsc_sync_ap(struct cpu_info *);
void tsc_sync_bp(struct cpu_info *);
Index: src/sys/rump/librump/rumpkern/arch/x86/rump_x86_cpu_counter.c
diff -u src/sys/rump/librump/rumpkern/arch/x86/rump_x86_cpu_counter.c:1.1 src/sys/rump/librump/rumpkern/arch/x86/rump_x86_cpu_counter.c:1.2
--- src/sys/rump/librump/rumpkern/arch/x86/rump_x86_cpu_counter.c:1.1 Wed Feb 12 22:28:43 2014
+++ src/sys/rump/librump/rumpkern/arch/x86/rump_x86_cpu_counter.c Mon Jun 15 09:09:24 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: rump_x86_cpu_counter.c,v 1.1 2014/02/12 22:28:43 pooka Exp $ */
+/* $NetBSD: rump_x86_cpu_counter.c,v 1.2 2020/06/15 09:09:24 msaitoh Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump_x86_cpu_counter.c,v 1.1 2014/02/12 22:28:43 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump_x86_cpu_counter.c,v 1.2 2020/06/15 09:09:24 msaitoh Exp $");
#include <sys/param.h>
@@ -45,22 +45,23 @@ cpu_hascounter(void)
}
uint64_t
-cpu_counter(void)
+cpu_frequency(struct cpu_info *ci)
{
return 0;
}
-uint32_t
-cpu_counter32(void)
+static uint64_t
+nullfunc64(void)
{
-
return 0;
}
-uint64_t
-cpu_frequency(struct cpu_info *ci)
+static uint32_t
+nullfunc32(void)
{
-
return 0;
}
+
+uint64_t (*cpu_counter)(void) = nullfunc64;
+uint32_t (*cpu_counter32)(void) = nullfunc32;