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,