summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Evans <bde@FreeBSD.org>1997-11-24 18:16:23 +0000
committerBruce Evans <bde@FreeBSD.org>1997-11-24 18:16:23 +0000
commit043e37feab38ede09a6e85c26fe7ad4048d5528d (patch)
treef3115a5f0cd25f7784188945786ebef821926ad0
parent5b76055a535370de26f15117decc2487a3e7a54f (diff)
Notes
-rw-r--r--sys/amd64/amd64/prof_machdep.c66
-rw-r--r--sys/i386/isa/prof_machdep.c66
2 files changed, 110 insertions, 22 deletions
diff --git a/sys/amd64/amd64/prof_machdep.c b/sys/amd64/amd64/prof_machdep.c
index 5f6684ddd923..63c210233beb 100644
--- a/sys/amd64/amd64/prof_machdep.c
+++ b/sys/amd64/amd64/prof_machdep.c
@@ -23,17 +23,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: prof_machdep.c,v 1.6 1997/02/22 09:36:59 peter Exp $
*/
#ifdef GUPROF
-#include "opt_cpu.h"
#include "opt_i586_guprof.h"
#include "opt_perfmon.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/gmon.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <machine/clock.h>
#include <machine/perfmon.h>
@@ -175,14 +176,14 @@ cputime()
u_char high, low;
static u_int prev_count;
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
if (cputime_clock == CPUTIME_CLOCK_I586_CTR) {
count = (u_int)rdtsc();
delta = (int)(count - prev_count);
prev_count = count;
return (delta);
}
-#ifdef I586_PMC_GUPROF
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
if (cputime_clock == CPUTIME_CLOCK_I586_PMC) {
/*
* XXX permon_read() should be inlined so that the
@@ -196,8 +197,8 @@ cputime()
prev_count = count;
return (delta);
}
-#endif /* I586_PMC_GUPROF */
-#endif /* I586_CPU or I686_CPU */
+#endif /* PERFMON && I586_PMC_GUPROF */
+#endif /* (I586_CPU || I686_CPU) && !SMP */
/*
* Read the current value of the 8254 timer counter 0.
@@ -223,6 +224,49 @@ cputime()
return (delta);
}
+static int
+sysctl_machdep_cputime_clock SYSCTL_HANDLER_ARGS
+{
+ int clock;
+ int event;
+ int error;
+ struct pmc pmc;
+
+ clock = cputime_clock;
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
+ if (clock == CPUTIME_CLOCK_I586_PMC) {
+ pmc.pmc_val = cputime_clock_pmc_conf;
+ clock += pmc.pmc_event;
+ }
+#endif
+ error = sysctl_handle_opaque(oidp, &clock, sizeof clock, req);
+ if (error == 0 && req->newptr != NULL) {
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
+ if (clock >= CPUTIME_CLOCK_I586_PMC) {
+ event = clock - CPUTIME_CLOCK_I586_PMC;
+ if (event >= 256)
+ return (EINVAL);
+ pmc.pmc_num = 0;
+ pmc.pmc_event = event;
+ pmc.pmc_unit = 0;
+ pmc.pmc_flags = PMCF_E | PMCF_OS | PMCF_USR;
+ pmc.pmc_mask = 0;
+ cputime_clock_pmc_conf = pmc.pmc_val;
+ cputime_clock = CPUTIME_CLOCK_I586_PMC;
+ } else
+#endif
+ {
+ if (clock < 0 || clock >= CPUTIME_CLOCK_I586_PMC)
+ return (EINVAL);
+ cputime_clock = clock;
+ }
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_machdep, OID_AUTO, cputime_clock, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(u_int), sysctl_machdep_cputime_clock, "I", "");
+
/*
* The start and stop routines need not be here since we turn off profiling
* before calling them. They are here for convenience.
@@ -234,16 +278,16 @@ startguprof(gp)
{
if (cputime_clock == CPUTIME_CLOCK_UNINITIALIZED) {
cputime_clock = CPUTIME_CLOCK_I8254;
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
if (i586_ctr_freq != 0)
cputime_clock = CPUTIME_CLOCK_I586_CTR;
#endif
}
gp->profrate = timer_freq << CPUTIME_CLOCK_I8254_SHIFT;
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
if (cputime_clock == CPUTIME_CLOCK_I586_CTR)
gp->profrate = i586_ctr_freq;
-#ifdef I586_PMC_GUPROF
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
else if (cputime_clock == CPUTIME_CLOCK_I586_PMC) {
if (perfmon_avail() &&
perfmon_setup(0, cputime_clock_pmc_conf) == 0) {
@@ -268,8 +312,8 @@ startguprof(gp)
}
}
}
-#endif /* I586_PMC_GUPROF */
-#endif /* I586_CPU or I686_CPU */
+#endif /* PERFMON && I586_PMC_GUPROF */
+#endif /* (I586_CPU || I686_CPU) && !SMP */
cputime_bias = 0;
cputime();
}
diff --git a/sys/i386/isa/prof_machdep.c b/sys/i386/isa/prof_machdep.c
index 5f6684ddd923..63c210233beb 100644
--- a/sys/i386/isa/prof_machdep.c
+++ b/sys/i386/isa/prof_machdep.c
@@ -23,17 +23,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: prof_machdep.c,v 1.6 1997/02/22 09:36:59 peter Exp $
*/
#ifdef GUPROF
-#include "opt_cpu.h"
#include "opt_i586_guprof.h"
#include "opt_perfmon.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/gmon.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <machine/clock.h>
#include <machine/perfmon.h>
@@ -175,14 +176,14 @@ cputime()
u_char high, low;
static u_int prev_count;
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
if (cputime_clock == CPUTIME_CLOCK_I586_CTR) {
count = (u_int)rdtsc();
delta = (int)(count - prev_count);
prev_count = count;
return (delta);
}
-#ifdef I586_PMC_GUPROF
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
if (cputime_clock == CPUTIME_CLOCK_I586_PMC) {
/*
* XXX permon_read() should be inlined so that the
@@ -196,8 +197,8 @@ cputime()
prev_count = count;
return (delta);
}
-#endif /* I586_PMC_GUPROF */
-#endif /* I586_CPU or I686_CPU */
+#endif /* PERFMON && I586_PMC_GUPROF */
+#endif /* (I586_CPU || I686_CPU) && !SMP */
/*
* Read the current value of the 8254 timer counter 0.
@@ -223,6 +224,49 @@ cputime()
return (delta);
}
+static int
+sysctl_machdep_cputime_clock SYSCTL_HANDLER_ARGS
+{
+ int clock;
+ int event;
+ int error;
+ struct pmc pmc;
+
+ clock = cputime_clock;
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
+ if (clock == CPUTIME_CLOCK_I586_PMC) {
+ pmc.pmc_val = cputime_clock_pmc_conf;
+ clock += pmc.pmc_event;
+ }
+#endif
+ error = sysctl_handle_opaque(oidp, &clock, sizeof clock, req);
+ if (error == 0 && req->newptr != NULL) {
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
+ if (clock >= CPUTIME_CLOCK_I586_PMC) {
+ event = clock - CPUTIME_CLOCK_I586_PMC;
+ if (event >= 256)
+ return (EINVAL);
+ pmc.pmc_num = 0;
+ pmc.pmc_event = event;
+ pmc.pmc_unit = 0;
+ pmc.pmc_flags = PMCF_E | PMCF_OS | PMCF_USR;
+ pmc.pmc_mask = 0;
+ cputime_clock_pmc_conf = pmc.pmc_val;
+ cputime_clock = CPUTIME_CLOCK_I586_PMC;
+ } else
+#endif
+ {
+ if (clock < 0 || clock >= CPUTIME_CLOCK_I586_PMC)
+ return (EINVAL);
+ cputime_clock = clock;
+ }
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_machdep, OID_AUTO, cputime_clock, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(u_int), sysctl_machdep_cputime_clock, "I", "");
+
/*
* The start and stop routines need not be here since we turn off profiling
* before calling them. They are here for convenience.
@@ -234,16 +278,16 @@ startguprof(gp)
{
if (cputime_clock == CPUTIME_CLOCK_UNINITIALIZED) {
cputime_clock = CPUTIME_CLOCK_I8254;
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
if (i586_ctr_freq != 0)
cputime_clock = CPUTIME_CLOCK_I586_CTR;
#endif
}
gp->profrate = timer_freq << CPUTIME_CLOCK_I8254_SHIFT;
-#if defined(I586_CPU) || defined(I686_CPU)
+#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP)
if (cputime_clock == CPUTIME_CLOCK_I586_CTR)
gp->profrate = i586_ctr_freq;
-#ifdef I586_PMC_GUPROF
+#if defined(PERFMON) && defined(I586_PMC_GUPROF)
else if (cputime_clock == CPUTIME_CLOCK_I586_PMC) {
if (perfmon_avail() &&
perfmon_setup(0, cputime_clock_pmc_conf) == 0) {
@@ -268,8 +312,8 @@ startguprof(gp)
}
}
}
-#endif /* I586_PMC_GUPROF */
-#endif /* I586_CPU or I686_CPU */
+#endif /* PERFMON && I586_PMC_GUPROF */
+#endif /* (I586_CPU || I686_CPU) && !SMP */
cputime_bias = 0;
cputime();
}