Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/sommerfeld_i386mp_1]: src/sys/arch/i386 Support Athlon performance count...
details: https://anonhg.NetBSD.org/src/rev/e702b65f45ab
branches: sommerfeld_i386mp_1
changeset: 482542:e702b65f45ab
user: gmcgarry <gmcgarry%NetBSD.org@localhost>
date: Fri Jun 07 04:04:48 2002 +0000
description:
Support Athlon performance counters.
diffstat:
sys/arch/i386/i386/pmc.c | 262 ++++++++++++++++++++++++++++++++++++++++
sys/arch/i386/include/sysarch.h | 105 ++++++++++++++++
2 files changed, 367 insertions(+), 0 deletions(-)
diffs (truncated from 375 to 300 lines):
diff -r fb2e562e7f83 -r e702b65f45ab sys/arch/i386/i386/pmc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/i386/i386/pmc.c Fri Jun 07 04:04:48 2002 +0000
@@ -0,0 +1,262 @@
+/* $NetBSD: pmc.c,v 1.4.2.2 2002/06/07 04:04:48 gmcgarry Exp $ */
+
+/*-
+ * Copyright (c) 2000 Zembu Labs, Inc.
+ * All rights reserved.
+ *
+ * Author: Jason R. Thorpe <thorpej%zembu.com@localhost>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Zembu Labs, Inc.
+ * 4. Neither the name of Zembu Labs nor the names of its employees may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR-
+ * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS-
+ * CLAIMED. IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Interface to x86 CPU Performance Counters.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.4.2.2 2002/06/07 04:04:48 gmcgarry Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+#include <machine/sysarch.h>
+#include <machine/pmc.h>
+
+static int pmc_initialized;
+static int pmc_ncounters;
+static int pmc_type;
+static int pmc_flags;
+
+static struct pmc_state {
+ u_int64_t pmcs_val;
+ u_int64_t pmcs_tsc;
+ u_int64_t pmcs_control;
+ u_int32_t pmcs_ctrmsr;
+} pmc_state[PMC_NCOUNTERS];
+
+static int pmc_running;
+
+static void
+pmc_init(void)
+{
+
+ if (pmc_initialized)
+ return;
+
+ pmc_type = PMC_TYPE_NONE;
+
+ switch (cpu_class) {
+ case CPUCLASS_586:
+ if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
+ pmc_type = PMC_TYPE_I586;
+ pmc_ncounters = 2;
+ pmc_state[0].pmcs_ctrmsr = MSR_CTR0;
+ pmc_state[1].pmcs_ctrmsr = MSR_CTR1;
+ break;
+ }
+
+ case CPUCLASS_686:
+ if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
+ pmc_type = PMC_TYPE_I686;
+ pmc_ncounters = 2;
+ pmc_state[0].pmcs_ctrmsr = MSR_PERFCTR0;
+ pmc_state[1].pmcs_ctrmsr = MSR_PERFCTR1;
+ } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+ pmc_type = PMC_TYPE_K7;
+ pmc_ncounters = 4;
+ pmc_state[0].pmcs_ctrmsr = MSR_K7_PERFCTR0;
+ pmc_state[1].pmcs_ctrmsr = MSR_K7_PERFCTR1;
+ pmc_state[2].pmcs_ctrmsr = MSR_K7_PERFCTR2;
+ pmc_state[3].pmcs_ctrmsr = MSR_K7_PERFCTR3;
+ }
+ break;
+ }
+
+ if (pmc_type != PMC_TYPE_NONE && (cpu_feature & CPUID_TSC) != 0)
+ pmc_flags |= PMC_INFO_HASTSC;
+
+ pmc_initialized = 1;
+}
+
+int
+pmc_info(struct proc *p, struct i386_pmc_info_args *uargs, register_t *retval)
+{
+ struct i386_pmc_info_args rv;
+
+ memset(&rv, 0, sizeof(rv));
+
+ if (pmc_initialized == 0)
+ pmc_init();
+
+ rv.type = pmc_type;
+ rv.flags = pmc_flags;
+
+ return (copyout(&rv, uargs, sizeof(rv)));
+}
+
+int
+pmc_startstop(struct proc *p, struct i386_pmc_startstop_args *uargs,
+ register_t *retval)
+{
+ struct i386_pmc_startstop_args args;
+ int error, mask, start;
+
+ if (pmc_initialized == 0)
+ pmc_init();
+ if (pmc_type == PMC_TYPE_NONE)
+ return (ENODEV);
+
+ error = copyin(uargs, &args, sizeof(args));
+ if (error)
+ return (error);
+
+ if (args.counter < 0 || args.counter >= pmc_ncounters)
+ return (EINVAL);
+
+ mask = 1 << args.counter;
+ start = (args.flags & (PMC_SETUP_KERNEL|PMC_SETUP_USER)) != 0;
+
+ if ((pmc_running & mask) != 0 && start != 0)
+ return (EBUSY);
+ else if ((pmc_running & mask) == 0 && start == 0)
+ return (0);
+
+ if (start) {
+ pmc_running |= mask;
+ pmc_state[args.counter].pmcs_val = args.val;
+ switch (pmc_type) {
+ case PMC_TYPE_I586:
+ pmc_state[args.counter].pmcs_control = args.event |
+ ((args.flags & PMC_SETUP_KERNEL) ?
+ PMC5_CESR_OS : 0) |
+ ((args.flags & PMC_SETUP_USER) ?
+ PMC5_CESR_USR : 0) |
+ ((args.flags & PMC_SETUP_EDGE) ?
+ PMC5_CESR_E : 0);
+ break;
+
+ case PMC_TYPE_I686:
+ pmc_state[args.counter].pmcs_control = args.event |
+ (args.unit << PMC6_EVTSEL_UNIT_SHIFT) |
+ ((args.flags & PMC_SETUP_KERNEL) ?
+ PMC6_EVTSEL_OS : 0) |
+ ((args.flags & PMC_SETUP_USER) ?
+ PMC6_EVTSEL_USR : 0) |
+ ((args.flags & PMC_SETUP_EDGE) ?
+ PMC6_EVTSEL_E : 0) |
+ ((args.flags & PMC_SETUP_INV) ?
+ PMC6_EVTSEL_INV : 0) |
+ (args.compare << PMC6_EVTSEL_COUNTER_MASK_SHIFT);
+ break;
+
+ case PMC_TYPE_K7:
+ pmc_state[args.counter].pmcs_control = args.event |
+ (args.unit << K7_EVTSEL_UNIT_SHIFT) |
+ ((args.flags & PMC_SETUP_KERNEL) ?
+ K7_EVTSEL_OS : 0) |
+ ((args.flags & PMC_SETUP_USER) ?
+ K7_EVTSEL_USR : 0) |
+ ((args.flags & PMC_SETUP_EDGE) ?
+ K7_EVTSEL_E : 0) |
+ ((args.flags & PMC_SETUP_INV) ?
+ K7_EVTSEL_INV : 0) |
+ (args.compare << PMC6_EVTSEL_COUNTER_MASK_SHIFT);
+ break;
+ }
+ disable_intr();
+ wrmsr(pmc_state[args.counter].pmcs_ctrmsr,
+ pmc_state[args.counter].pmcs_val);
+ enable_intr();
+ } else {
+ pmc_running &= ~mask;
+ pmc_state[args.counter].pmcs_control = 0;
+ }
+
+ switch (pmc_type) {
+ case PMC_TYPE_I586:
+ disable_intr();
+ wrmsr(MSR_CESR, pmc_state[0].pmcs_control |
+ (pmc_state[1].pmcs_control << 16));
+ enable_intr();
+ break;
+
+ case PMC_TYPE_I686:
+ disable_intr();
+ if (args.counter == 1)
+ wrmsr(MSR_EVNTSEL1, pmc_state[1].pmcs_control);
+ wrmsr(MSR_EVNTSEL0, pmc_state[0].pmcs_control |
+ (pmc_running ? PMC6_EVTSEL_EN : 0));
+ enable_intr();
+ break;
+
+ case PMC_TYPE_K7:
+ disable_intr();
+ if (args.counter == 1)
+ wrmsr(MSR_K7_EVNTSEL1, pmc_state[1].pmcs_control);
+ wrmsr(MSR_K7_EVNTSEL0, pmc_state[0].pmcs_control |
+ (pmc_running ? K7_EVTSEL_EN : 0));
+ enable_intr();
+ break;
+ }
+
+ return (0);
+}
+
+int
+pmc_read(struct proc *p, struct i386_pmc_read_args *uargs, register_t *retval)
+{
+ struct i386_pmc_read_args args;
+ int error;
+
+ if (pmc_initialized == 0)
+ pmc_init();
+ if (pmc_type == PMC_TYPE_NONE)
+ return (ENODEV);
+
+ error = copyin(uargs, &args, sizeof(args));
+ if (error)
+ return (error);
+
+ if (args.counter < 0 || args.counter >= pmc_ncounters)
+ return (EINVAL);
+
+ if (pmc_running & (1 << args.counter)) {
+ pmc_state[args.counter].pmcs_val =
+ rdmsr(pmc_state[args.counter].pmcs_ctrmsr) &
+ 0xffffffffffULL;
+ if (pmc_flags & PMC_INFO_HASTSC)
+ pmc_state[args.counter].pmcs_tsc = rdtsc();
+ }
+
+ args.val = pmc_state[args.counter].pmcs_val;
+ args.time = pmc_state[args.counter].pmcs_tsc;
+
+ return (copyout(&args, uargs, sizeof(args)));
+}
diff -r fb2e562e7f83 -r e702b65f45ab sys/arch/i386/include/sysarch.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/i386/include/sysarch.h Fri Jun 07 04:04:48 2002 +0000
@@ -0,0 +1,105 @@
+/* $NetBSD: sysarch.h,v 1.12.2.2 2002/06/07 04:04:48 gmcgarry Exp $ */
+
+#ifndef _I386_SYSARCH_H_
+#define _I386_SYSARCH_H_
+
+/*
+ * Architecture specific syscalls (i386)
+ */
+#define I386_GET_LDT 0
+#define I386_SET_LDT 1
+#define I386_IOPL 2
+#define I386_GET_IOPERM 3
+#define I386_SET_IOPERM 4
+#define I386_VM86 5
+#define I386_PMC_INFO 8
+#define I386_PMC_STARTSTOP 9
+#define I386_PMC_READ 10
+#define I386_GET_MTRR 11
+#define I386_SET_MTRR 12
+
+struct i386_get_ldt_args {
+ int start;
+ union descriptor *desc;
+ int num;
+};
+
+struct i386_set_ldt_args {
+ int start;
+ union descriptor *desc;
+ int num;
Home |
Main Index |
Thread Index |
Old Index