Module Name:    src
Committed By:   maxv
Date:           Mon Oct  2 19:23:16 UTC 2017

Modified Files:
        src/sys/arch/x86/x86: tsc.c tsc.h x86_machdep.c

Log Message:
Add a machdep.tsc_user_enable sysctl, to enable/disable the rdtsc
instruction in usermode. It defaults to enabled.


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/x86/x86/tsc.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/x86/x86/tsc.h
cvs rdiff -u -r1.95 -r1.96 src/sys/arch/x86/x86/x86_machdep.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/x86/x86/tsc.c
diff -u src/sys/arch/x86/x86/tsc.c:1.36 src/sys/arch/x86/x86/tsc.c:1.37
--- src/sys/arch/x86/x86/tsc.c:1.36	Wed Dec 18 03:20:19 2013
+++ src/sys/arch/x86/x86/tsc.c	Mon Oct  2 19:23:16 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: tsc.c,v 1.36 2013/12/18 03:20:19 msaitoh Exp $	*/
+/*	$NetBSD: tsc.c,v 1.37 2017/10/02 19:23:16 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.36 2013/12/18 03:20:19 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.37 2017/10/02 19:23:16 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -37,6 +37,7 @@ __KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.36
 #include <sys/atomic.h>
 #include <sys/kernel.h>
 #include <sys/cpu.h>
+#include <sys/xcall.h>
 
 #include <machine/cpu_counter.h>
 #include <machine/cpuvar.h>
@@ -53,6 +54,8 @@ static int64_t	tsc_drift_max = 250;	/* m
 static int64_t	tsc_drift_observed;
 static bool	tsc_good;
 
+int tsc_user_enabled = 1;
+
 static volatile int64_t	tsc_sync_val;
 static volatile struct cpu_info	*tsc_sync_cpu;
 
@@ -265,6 +268,35 @@ tsc_sync_ap(struct cpu_info *ci)
 	tsc_post_ap(ci);
 }
 
+static void
+tsc_apply_cpu(void *arg1, void *arg2)
+{
+	bool enable = (bool)arg1;
+	if (enable) {
+		lcr4(rcr4() & ~CR4_TSD);
+	} else {
+		lcr4(rcr4() | CR4_TSD);
+	}
+}
+
+void
+tsc_user_enable(void)
+{
+	uint64_t xc;
+
+	xc = xc_broadcast(0, tsc_apply_cpu, (void *)true, NULL);
+	xc_wait(xc);
+}
+
+void
+tsc_user_disable(void)
+{
+	uint64_t xc;
+
+	xc = xc_broadcast(0, tsc_apply_cpu, (void *)false, NULL);
+	xc_wait(xc);
+}
+
 uint64_t
 cpu_frequency(struct cpu_info *ci)
 {

Index: src/sys/arch/x86/x86/tsc.h
diff -u src/sys/arch/x86/x86/tsc.h:1.5 src/sys/arch/x86/x86/tsc.h:1.6
--- src/sys/arch/x86/x86/tsc.h:1.5	Wed Dec 11 02:14:08 2013
+++ src/sys/arch/x86/x86/tsc.h	Mon Oct  2 19:23:16 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: tsc.h,v 1.5 2013/12/11 02:14:08 msaitoh Exp $	*/
+/*	$NetBSD: tsc.h,v 1.6 2017/10/02 19:23:16 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -31,3 +31,5 @@ void	tsc_tc_init(void);
 void	tsc_sync_ap(struct cpu_info *);
 void	tsc_sync_bp(struct cpu_info *);
 void	tsc_sync_drift(int64_t);
+void	tsc_user_enable(void);
+void	tsc_user_disable(void);

Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.95 src/sys/arch/x86/x86/x86_machdep.c:1.96
--- src/sys/arch/x86/x86/x86_machdep.c:1.95	Sat Sep 30 12:01:56 2017
+++ src/sys/arch/x86/x86/x86_machdep.c	Mon Oct  2 19:23:16 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_machdep.c,v 1.95 2017/09/30 12:01:56 maxv Exp $	*/
+/*	$NetBSD: x86_machdep.c,v 1.96 2017/10/02 19:23:16 maxv Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.95 2017/09/30 12:01:56 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.96 2017/10/02 19:23:16 maxv Exp $");
 
 #include "opt_modular.h"
 #include "opt_physmem.h"
@@ -70,6 +70,8 @@ __KERNEL_RCSID(0, "$NetBSD: x86_machdep.
 
 #include <uvm/uvm_extern.h>
 
+#include "tsc.h"
+
 #include "acpica.h"
 #if NACPICA > 0
 #include <dev/acpi/acpivar.h>
@@ -1109,6 +1111,38 @@ sysctl_machdep_diskinfo(SYSCTLFN_ARGS)
 	return sysctl_lookup(SYSCTLFN_CALL(&node));
 }
 
+#ifndef XEN
+static int
+sysctl_machdep_tsc_enable(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	int error, val;
+
+	val = *(int *)rnode->sysctl_data;
+
+	node = *rnode;
+	node.sysctl_data = &val;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error != 0 || newp == NULL)
+		return error;
+
+	if (val == 1) {
+		tsc_user_enable();
+	} else if (val == 0) {
+		tsc_user_disable();
+	} else {
+		error = EINVAL;
+	}
+	if (error)
+		return error;
+
+	*(int *)rnode->sysctl_data = val;
+
+	return 0;
+}
+#endif
+
 static void
 const_sysctl(struct sysctllog **clog, const char *name, int type,
     u_quad_t value, int tag)
@@ -1122,6 +1156,9 @@ const_sysctl(struct sysctllog **clog, co
 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
 {
 	extern uint64_t tsc_freq;
+#ifndef XEN
+	extern int tsc_user_enabled;
+#endif
 	extern int sparse_dump;
 
 	sysctl_createv(clog, 0, NULL, NULL,
@@ -1167,6 +1204,14 @@ SYSCTL_SETUP(sysctl_machdep_setup, "sysc
 		       SYSCTL_DESCR("Whether the kernel uses PAE"),
 		       NULL, 0, &use_pae, 0,
 		       CTL_MACHDEP, CTL_CREATE, CTL_EOL);
+#ifndef XEN
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "tsc_user_enable",
+		       SYSCTL_DESCR("RDTSC instruction enabled in usermode"),
+		       sysctl_machdep_tsc_enable, 0, &tsc_user_enabled, 0,
+		       CTL_MACHDEP, CTL_CREATE, CTL_EOL);
+#endif
 
 	/* None of these can ever change once the system has booted */
 	const_sysctl(clog, "fpu_present", CTLTYPE_INT, i386_fpu_present,

Reply via email to