Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x86/x86 The boot CPU suffers a cache miss during TS...
details: https://anonhg.NetBSD.org/src/rev/6539a9d68bce
branches: trunk
changeset: 933174:6539a9d68bce
user: ad <ad%NetBSD.org@localhost>
date: Wed May 20 20:19:02 2020 +0000
description:
The boot CPU suffers a cache miss during TSC sync, before RDTSC. Make the
secondary CPU take a miss as well to try and delay it an equal amount.
diffstat:
sys/arch/x86/x86/tsc.c | 23 ++++++++++++++++-------
1 files changed, 16 insertions(+), 7 deletions(-)
diffs (74 lines):
diff -r 3e22cf34798a -r 6539a9d68bce sys/arch/x86/x86/tsc.c
--- a/sys/arch/x86/x86/tsc.c Wed May 20 20:18:37 2020 +0000
+++ b/sys/arch/x86/x86/tsc.c Wed May 20 20:19:02 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tsc.c,v 1.46 2020/05/19 21:56:51 ad Exp $ */
+/* $NetBSD: tsc.c,v 1.47 2020/05/20 20:19:02 ad 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.46 2020/05/19 21:56:51 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.47 2020/05/20 20:19:02 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -54,6 +54,7 @@
static void tsc_delay(unsigned int);
+static uint64_t tsc_dummy_cacheline __cacheline_aligned;
uint64_t tsc_freq; /* exported for sysctl */
static int64_t tsc_drift_max = 1000; /* max cycles */
static int64_t tsc_drift_observed;
@@ -200,7 +201,7 @@
* Called during startup of APs, by the boot processor. Interrupts
* are disabled on entry.
*/
-static void
+static void __noinline
tsc_read_bp(struct cpu_info *ci, uint64_t *bptscp, uint64_t *aptscp)
{
uint64_t bptsc;
@@ -209,10 +210,13 @@
panic("tsc_sync_bp: 1");
}
- /* Flag it and read our TSC. */
+ /* Prepare a cache miss for the other side. */
+ (void)atomic_swap_uint((void *)&tsc_dummy_cacheline, 0);
+
+ /* Flag our readiness. */
atomic_or_uint(&ci->ci_flags, CPUF_SYNCTSC);
- /* Wait for remote to complete, and read ours again. */
+ /* Wait for other side then read our TSC. */
while ((ci->ci_flags & CPUF_SYNCTSC) != 0) {
__insn_barrier();
}
@@ -254,7 +258,7 @@
* Called during startup of AP, by the AP itself. Interrupts are
* disabled on entry.
*/
-static void
+static void __noinline
tsc_post_ap(struct cpu_info *ci)
{
uint64_t tsc;
@@ -266,7 +270,12 @@
/* Instruct primary to read its counter. */
atomic_and_uint(&ci->ci_flags, ~CPUF_SYNCTSC);
- tsc = rdtsc();
+
+ /* Suffer a cache miss, then read TSC. */
+ __insn_barrier();
+ tsc = tsc_dummy_cacheline;
+ __insn_barrier();
+ tsc += rdtsc();
/* Post result. Ensure the whole value goes out atomically. */
(void)atomic_swap_64(&tsc_sync_val, tsc);
Home |
Main Index |
Thread Index |
Old Index