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