Signed-off-by: Robert Richter <[EMAIL PROTECTED]>

---
 arch/i386/perfmon/Kconfig           |    2 
 arch/i386/perfmon/Makefile          |    4 
 arch/i386/perfmon/perfmon.c         |    4 
 arch/x86_64/perfmon/Kconfig         |    2 
 arch/x86_64/perfmon/Makefile        |    2 
 arch/x86_64/perfmon/perfmon_amd64.c |  341 ++++++++++++++++++++++++++++++++++++
 arch/x86_64/perfmon/perfmon_k8.c    |  341 ------------------------------------
 7 files changed, 348 insertions(+), 348 deletions(-)

Index: linux-2.6.22-rc4/arch/i386/perfmon/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/arch/i386/perfmon/Kconfig
+++ linux-2.6.22-rc4/arch/i386/perfmon/Kconfig
@@ -55,7 +55,7 @@ config  I386_PERFMON_INTEL_ARCH
        Enables 32-bit support for Intel architectural performance counters. 
This
        architecture was introduced by Intel Core Solo/Core Duo processors.
 
-config I386_PERFMON_K8
+config I386_PERFMON_AMD64
        tristate "Support 32-bit mode AMD Athlon64/Opteron64 hardware 
performance counters"
        depends on PERFMON
        default n
Index: linux-2.6.22-rc4/arch/i386/perfmon/Makefile
===================================================================
--- linux-2.6.22-rc4.orig/arch/i386/perfmon/Makefile
+++ linux-2.6.22-rc4/arch/i386/perfmon/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_I386_PERFMON_P4)           += perfmo
 obj-$(CONFIG_I386_PERFMON_CORE)                += perfmon_core.o
 obj-$(CONFIG_I386_PERFMON_INTEL_ARCH)  += perfmon_intel_arch.o
 obj-$(CONFIG_I386_PERFMON_PEBS)                += perfmon_pebs_smpl.o
-obj-$(CONFIG_I386_PERFMON_K8)          += perfmon_k8.o
+obj-$(CONFIG_I386_PERFMON_AMD64)       += perfmon_amd64.o
 
-perfmon_k8-$(subst m,y,$(CONFIG_I386_PERFMON_K8)) += 
../../x86_64/perfmon/perfmon_k8.o
+perfmon_amd64-$(subst m,y,$(CONFIG_I386_PERFMON_AMD64)) += 
../../x86_64/perfmon/perfmon_amd64.o
 perfmon_core-$(subst m,y,$(CONFIG_I386_PERFMON_CORE)) += 
../../x86_64/perfmon/perfmon_core.o
Index: linux-2.6.22-rc4/arch/i386/perfmon/perfmon.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/i386/perfmon/perfmon.c
+++ linux-2.6.22-rc4/arch/i386/perfmon/perfmon.c
@@ -810,7 +810,7 @@ fastcall void smp_pmu_interrupt(struct p
  *     0 : no overflow
  *     1 : at least one overflow
  *
- * used by AMD K8 and Intel architectural PMU
+ * used by AMD64 and Intel architectural PMU
  */
 static int __kprobes pfm_has_ovfl_p6(struct pfm_context *ctx)
 {
@@ -1117,7 +1117,7 @@ char *pfm_arch_get_pmu_module_name(void)
        case 16:
                /* All Opteron processors */
                if (cpu_data->x86_vendor == X86_VENDOR_AMD)
-                       return "perfmon_k8";
+                       return "perfmon_amd64";
 
                switch(cpu_data->x86_model) {
                case 0 ... 6:
Index: linux-2.6.22-rc4/arch/x86_64/perfmon/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/arch/x86_64/perfmon/Kconfig
+++ linux-2.6.22-rc4/arch/x86_64/perfmon/Kconfig
@@ -14,7 +14,7 @@ config PERFMON_DEBUG
        help
        Enables perfmon debugging support
 
-config X86_64_PERFMON_K8
+config X86_64_PERFMON_AMD64
        tristate "Support 64-bit mode AMD Athlon64 and Opteron64 hardware 
performance counters"
        depends on PERFMON
        default n
Index: linux-2.6.22-rc4/arch/x86_64/perfmon/Makefile
===================================================================
--- linux-2.6.22-rc4.orig/arch/x86_64/perfmon/Makefile
+++ linux-2.6.22-rc4/arch/x86_64/perfmon/Makefile
@@ -4,7 +4,7 @@
 #
 
 obj-$(CONFIG_PERFMON)                  += perfmon.o
-obj-$(CONFIG_X86_64_PERFMON_K8)                += perfmon_k8.o
+obj-$(CONFIG_X86_64_PERFMON_AMD64)     += perfmon_amd64.o
 obj-$(CONFIG_X86_64_PERFMON_P4)                += perfmon_p4.o
 obj-$(CONFIG_X86_64_PERFMON_CORE)      += perfmon_core.o
 obj-$(CONFIG_X86_64_PERFMON_INTEL_ARCH)        += perfmon_intel_arch.o
Index: linux-2.6.22-rc4/arch/x86_64/perfmon/perfmon_amd64.c
===================================================================
--- /dev/null
+++ linux-2.6.22-rc4/arch/x86_64/perfmon/perfmon_amd64.c
@@ -0,0 +1,341 @@
+/*
+ * This file contains the PMU description for the Athlon64 and Opteron64
+ * processors. It supports 32 and 64-bit modes.
+ *
+ * Copyright (c) 2005-2007 Hewlett-Packard Development Company, L.P.
+ * Contributed by Stephane Eranian <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA
+  */
+#include <linux/module.h>
+#include <linux/perfmon.h>
+#include <linux/vmalloc.h>
+#include <asm/nmi.h>
+
+MODULE_AUTHOR("Stephane Eranian <[EMAIL PROTECTED]>");
+MODULE_DESCRIPTION("AMD64 PMU description table");
+MODULE_LICENSE("GPL");
+
+static int force_nmi;
+MODULE_PARM_DESC(force_nmi, "bool: force use of NMI for PMU interrupt");
+module_param(force_nmi, bool, 0600);
+
+static struct pfm_arch_pmu_info pfm_amd64_pmu_info = {
+       .pmc_addrs = {
+/* pmc0  */    {{MSR_K7_EVNTSEL0, 0}, 0, PFM_REGT_EN},
+/* pmc1  */    {{MSR_K7_EVNTSEL1, 0}, 1, PFM_REGT_EN},
+/* pmc2  */    {{MSR_K7_EVNTSEL2, 0}, 2, PFM_REGT_EN},
+/* pmc3  */    {{MSR_K7_EVNTSEL3, 0}, 3, PFM_REGT_EN},
+       },
+       .pmd_addrs = {
+/* pmd0  */    {{MSR_K7_PERFCTR0, 0}, 0, PFM_REGT_CTR},
+/* pmd1  */    {{MSR_K7_PERFCTR1, 0}, 0, PFM_REGT_CTR},
+/* pmd2  */    {{MSR_K7_PERFCTR2, 0}, 0, PFM_REGT_CTR},
+/* pmd3  */    {{MSR_K7_PERFCTR3, 0}, 0, PFM_REGT_CTR},
+       },
+       .pmu_style = PFM_X86_PMU_AMD64
+};
+
+/*
+ * force Local APIC interrupt on overflow
+ */
+#define PFM_K8_VAL     (1ULL<<20)
+#define PFM_K8_NO64    (1ULL<<20)
+
+/*
+ * reserved bits must be zero
+ *
+ * - upper 32 bits are reserved
+ * - APIC enable bit is reserved (forced to 1)
+ * - bit 21 is reserved
+ */
+#define PFM_K8_RSVD    ((~((1ULL<<32)-1)) \
+                       | (1ULL<<20)       \
+                       | (1ULL<<21))
+
+static struct pfm_regmap_desc pfm_amd64_pmc_desc[] = {
+/* pmc0  */ PMC_D(PFM_REG_I64, "PERFSEL0", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL0),
+/* pmc1  */ PMC_D(PFM_REG_I64, "PERFSEL1", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL1),
+/* pmc2  */ PMC_D(PFM_REG_I64, "PERFSEL2", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL2),
+/* pmc3  */ PMC_D(PFM_REG_I64, "PERFSEL3", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL3),
+};
+#define PFM_AMD_NUM_PMCS ARRAY_SIZE(pfm_amd64_pmc_desc)
+
+static struct pfm_regmap_desc pfm_amd64_pmd_desc[] = {
+/* pmd0  */ PMD_D(PFM_REG_C,   "PERFCTR0",     MSR_K7_PERFCTR0),
+/* pmd1  */ PMD_D(PFM_REG_C,   "PERFCTR1",     MSR_K7_PERFCTR1),
+/* pmd2  */ PMD_D(PFM_REG_C,   "PERFCTR2",     MSR_K7_PERFCTR2),
+/* pmd3  */ PMD_D(PFM_REG_C,   "PERFCTR3",     MSR_K7_PERFCTR3)
+};
+#define PFM_AMD_NUM_PMDS ARRAY_SIZE(pfm_amd64_pmd_desc)
+
+static struct pfm_context **pfm_nb_sys_owners;
+static struct pfm_context *pfm_nb_task_owner;
+
+static struct pfm_pmu_config pfm_amd64_pmu_conf;
+
+/*
+ * There can only be one user per socket for the Northbridge (NB) events,
+ * so we enforce mutual exclusion as follows:
+ *     - per-thread : only one context machine-wide can use NB events
+ *     - system-wide: only one context per processor socket
+ *
+ * Exclusion is enforced at:
+ *     - pfm_load_context()
+ *     - pfm_write_pmcs() for attached contexts
+ *
+ * Exclusion is released at:
+ *     - pfm_unload_context() or any calls that implicitely uses it
+ *
+ * return:
+ *     0  : successfully acquire NB access
+ *     < 0:  errno, failed to acquire NB access
+ */
+static int pfm_amd64_acquire_nb(struct pfm_context *ctx)
+{
+       struct pfm_context **entry, *old;
+       int proc_id;
+
+#ifdef CONFIG_SMP
+       proc_id = topology_physical_package_id(smp_processor_id());
+#else
+       proc_id = 0;
+#endif
+
+       if (ctx->flags.system)
+               entry = &pfm_nb_sys_owners[proc_id];
+       else
+               entry = &pfm_nb_task_owner;
+
+       old = cmpxchg(entry, NULL, ctx);
+       if (!old) {
+               if (ctx->flags.system)
+                       PFM_DBG("acquired Northbridge event access on socket 
%u", proc_id);
+               else
+                       PFM_DBG("acquired Northbridge event access globally");
+       } else if (old != ctx) {
+               if (ctx->flags.system)
+                       PFM_DBG("NorthBridge event conflict on socket %u", 
proc_id);
+               else
+                       PFM_DBG("global NorthBridge event conflict");
+               return -EBUSY;
+       }
+       return 0;
+}
+
+/*
+ * invoked from pfm_write_pmcs() when pfm_nb_sys_owners is not NULL,i.e.,
+ * when we have detected a multi-core processor.
+ *
+ * context is locked, interrupts are masked
+ */
+static int pfm_amd64_pmc_write_check(struct pfm_context *ctx,
+                            struct pfm_event_set *set,
+                            struct pfarg_pmc *req)
+{
+       unsigned int event;
+       /*
+        * delay checking NB event until we load the context
+        */
+       if (ctx->state == PFM_CTX_UNLOADED)
+               return 0;
+
+       /*
+        * check event is NB event
+        */
+       event = (unsigned int)(req->reg_value & 0xff);
+       if (event < 0xee)
+               return 0;
+
+       return pfm_amd64_acquire_nb(ctx);
+}
+
+/*
+ * invoked on pfm_load_context().
+ * context is locked, interrupts are masked
+ */
+static int pfm_amd64_load_context(struct pfm_context *ctx)
+{
+       struct pfm_event_set *set;
+       unsigned int i, n;
+
+       /*
+        * scan all sets for NB events
+        */
+       list_for_each_entry(set, &ctx->list, list) {
+               n = set->nused_pmcs;
+               for (i = 0; n; i++) {
+                       if (!test_bit(i, cast_ulp(set->used_pmcs)))
+                               continue;
+                       if ((set->pmcs[i] & 0xff) >= 0xee)
+                               goto found;
+                       n--;
+               }
+       }
+       return 0;
+found:
+       return pfm_amd64_acquire_nb(ctx);
+}
+
+/*
+ * invoked on pfm_unload_context()
+ */
+static int pfm_amd64_unload_context(struct pfm_context *ctx)
+{
+       struct pfm_context **entry, *old;
+       int proc_id;
+
+#ifdef CONFIG_SMP
+       proc_id = topology_physical_package_id(smp_processor_id());
+#else
+       proc_id = 0;
+#endif
+
+       /*
+        * unload always happens on the monitored CPU in system-wide
+        */
+       if (ctx->flags.system)
+               entry = &pfm_nb_sys_owners[proc_id];
+       else
+               entry = &pfm_nb_task_owner;
+
+       old = cmpxchg(entry, ctx, NULL);
+       if (old == ctx) {
+               if (ctx->flags.system)
+                       PFM_DBG("released NorthBridge on socket %u", proc_id);
+               else
+                       PFM_DBG("released NorthBridge events globally");
+       }
+       return 0;
+}
+
+/*
+ * detect if we need to active NorthBridge event access control
+ */
+static int pfm_amd64_setup_nb_event_control(void)
+{
+       unsigned int c, n = 0;
+       unsigned int max_phys = 0;
+
+#ifdef CONFIG_SMP
+       for_each_possible_cpu(c) {
+               if (cpu_data[c].phys_proc_id > max_phys)
+                       max_phys = cpu_data[c].phys_proc_id;
+       }
+#else
+       max_phys = 0;
+#endif
+       if (max_phys > 255) {
+               PFM_INFO("socket id %d is too big to handle", max_phys);
+               return -ENOMEM;
+       }
+
+       n = max_phys + 1;
+       if (n < 2)
+               return 0;
+
+       pfm_nb_sys_owners = vmalloc(n * sizeof(*pfm_nb_sys_owners));
+       if (!pfm_nb_sys_owners)
+               return -ENOMEM;
+
+       memset(pfm_nb_sys_owners, 0, n * sizeof(*pfm_nb_sys_owners));
+       pfm_nb_task_owner = NULL;
+
+       /*
+        * activate write-checker for PMC registers
+        */
+       for (c = 0; c < PFM_AMD_NUM_PMCS; c++) {
+               pfm_amd64_pmc_desc[c].type |= PFM_REG_WC;
+       }
+
+       pfm_amd64_pmu_info.load_context = pfm_amd64_load_context;
+       pfm_amd64_pmu_info.unload_context = pfm_amd64_unload_context;
+
+       pfm_amd64_pmu_conf.pmc_write_check = pfm_amd64_pmc_write_check;
+
+       PFM_INFO("NorthBridge event access control enabled");
+
+       return 0;
+}
+
+static int pfm_amd64_probe_pmu(void)
+{
+       if (current_cpu_data.x86_vendor != X86_VENDOR_AMD) {
+               PFM_INFO("not an AMD processor");
+               return -1;
+       }
+
+       switch (current_cpu_data.x86) {
+       case 15:
+       case 16:
+               PFM_INFO("found family=%d", current_cpu_data.x86);
+               break;
+       default:
+               PFM_INFO("unsupported family=%d", current_cpu_data.x86);
+               return -1;
+       }
+
+       /*
+        * check for local APIC (required)
+        */
+       if (!cpu_has_apic) {
+               PFM_INFO("no local APIC, unsupported");
+               return -1;
+       }
+
+       if (current_cpu_data.x86_max_cores > 1)
+               return pfm_amd64_setup_nb_event_control();
+
+       PFM_INFO("nmi_watchdog=%d nmi_active=%d force_nmi=%d",
+               nmi_watchdog, atomic_read(&nmi_active), force_nmi);
+       /*
+        * NMI using PMU?
+        * Actual removal of NMI counter is done by pfm_pmu_acquire()
+        */
+       if (nmi_watchdog == NMI_LOCAL_APIC || force_nmi)
+               pfm_amd64_pmu_info.flags |= PFM_X86_FL_USE_NMI;
+
+       return 0;
+}
+
+static struct pfm_pmu_config pfm_amd64_pmu_conf = {
+       .pmu_name = "AMD64",
+       .counter_width = 47,
+       .pmd_desc = pfm_amd64_pmd_desc,
+       .pmc_desc = pfm_amd64_pmc_desc,
+       .num_pmc_entries = PFM_AMD_NUM_PMCS,
+       .num_pmd_entries = PFM_AMD_NUM_PMDS,
+       .probe_pmu = pfm_amd64_probe_pmu,
+       .version = "1.1",
+       .arch_info = &pfm_amd64_pmu_info,
+       .flags = PFM_PMU_BUILTIN_FLAG,
+       .owner = THIS_MODULE
+};
+
+static int __init pfm_amd64_pmu_init_module(void)
+{
+       return pfm_pmu_register(&pfm_amd64_pmu_conf);
+}
+
+static void __exit pfm_amd64_pmu_cleanup_module(void)
+{
+       if (pfm_nb_sys_owners)
+               vfree(pfm_nb_sys_owners);
+
+       pfm_pmu_unregister(&pfm_amd64_pmu_conf);
+}
+
+module_init(pfm_amd64_pmu_init_module);
+module_exit(pfm_amd64_pmu_cleanup_module);
Index: linux-2.6.22-rc4/arch/x86_64/perfmon/perfmon_k8.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/x86_64/perfmon/perfmon_k8.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * This file contains the PMU description for the Athlon64 and Opteron64
- * processors. It supports 32 and 64-bit modes.
- *
- * Copyright (c) 2005-2007 Hewlett-Packard Development Company, L.P.
- * Contributed by Stephane Eranian <[EMAIL PROTECTED]>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307 USA
-  */
-#include <linux/module.h>
-#include <linux/perfmon.h>
-#include <linux/vmalloc.h>
-#include <asm/nmi.h>
-
-MODULE_AUTHOR("Stephane Eranian <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION("AMD64 PMU description table");
-MODULE_LICENSE("GPL");
-
-static int force_nmi;
-MODULE_PARM_DESC(force_nmi, "bool: force use of NMI for PMU interrupt");
-module_param(force_nmi, bool, 0600);
-
-static struct pfm_arch_pmu_info pfm_amd64_pmu_info = {
-       .pmc_addrs = {
-/* pmc0  */    {{MSR_K7_EVNTSEL0, 0}, 0, PFM_REGT_EN},
-/* pmc1  */    {{MSR_K7_EVNTSEL1, 0}, 1, PFM_REGT_EN},
-/* pmc2  */    {{MSR_K7_EVNTSEL2, 0}, 2, PFM_REGT_EN},
-/* pmc3  */    {{MSR_K7_EVNTSEL3, 0}, 3, PFM_REGT_EN},
-       },
-       .pmd_addrs = {
-/* pmd0  */    {{MSR_K7_PERFCTR0, 0}, 0, PFM_REGT_CTR},
-/* pmd1  */    {{MSR_K7_PERFCTR1, 0}, 0, PFM_REGT_CTR},
-/* pmd2  */    {{MSR_K7_PERFCTR2, 0}, 0, PFM_REGT_CTR},
-/* pmd3  */    {{MSR_K7_PERFCTR3, 0}, 0, PFM_REGT_CTR},
-       },
-       .pmu_style = PFM_X86_PMU_AMD64
-};
-
-/*
- * force Local APIC interrupt on overflow
- */
-#define PFM_K8_VAL     (1ULL<<20)
-#define PFM_K8_NO64    (1ULL<<20)
-
-/*
- * reserved bits must be zero
- *
- * - upper 32 bits are reserved
- * - APIC enable bit is reserved (forced to 1)
- * - bit 21 is reserved
- */
-#define PFM_K8_RSVD    ((~((1ULL<<32)-1)) \
-                       | (1ULL<<20)       \
-                       | (1ULL<<21))
-
-static struct pfm_regmap_desc pfm_amd64_pmc_desc[] = {
-/* pmc0  */ PMC_D(PFM_REG_I64, "PERFSEL0", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL0),
-/* pmc1  */ PMC_D(PFM_REG_I64, "PERFSEL1", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL1),
-/* pmc2  */ PMC_D(PFM_REG_I64, "PERFSEL2", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL2),
-/* pmc3  */ PMC_D(PFM_REG_I64, "PERFSEL3", PFM_K8_VAL, PFM_K8_RSVD, 
PFM_K8_NO64, MSR_K7_EVNTSEL3),
-};
-#define PFM_AMD_NUM_PMCS ARRAY_SIZE(pfm_amd64_pmc_desc)
-
-static struct pfm_regmap_desc pfm_amd64_pmd_desc[] = {
-/* pmd0  */ PMD_D(PFM_REG_C,   "PERFCTR0",     MSR_K7_PERFCTR0),
-/* pmd1  */ PMD_D(PFM_REG_C,   "PERFCTR1",     MSR_K7_PERFCTR1),
-/* pmd2  */ PMD_D(PFM_REG_C,   "PERFCTR2",     MSR_K7_PERFCTR2),
-/* pmd3  */ PMD_D(PFM_REG_C,   "PERFCTR3",     MSR_K7_PERFCTR3)
-};
-#define PFM_AMD_NUM_PMDS ARRAY_SIZE(pfm_amd64_pmd_desc)
-
-static struct pfm_context **pfm_nb_sys_owners;
-static struct pfm_context *pfm_nb_task_owner;
-
-static struct pfm_pmu_config pfm_amd64_pmu_conf;
-
-/*
- * There can only be one user per socket for the Northbridge (NB) events,
- * so we enforce mutual exclusion as follows:
- *     - per-thread : only one context machine-wide can use NB events
- *     - system-wide: only one context per processor socket
- *
- * Exclusion is enforced at:
- *     - pfm_load_context()
- *     - pfm_write_pmcs() for attached contexts
- *
- * Exclusion is released at:
- *     - pfm_unload_context() or any calls that implicitely uses it
- *
- * return:
- *     0  : successfully acquire NB access
- *     < 0:  errno, failed to acquire NB access
- */
-static int pfm_amd64_acquire_nb(struct pfm_context *ctx)
-{
-       struct pfm_context **entry, *old;
-       int proc_id;
-
-#ifdef CONFIG_SMP
-       proc_id = topology_physical_package_id(smp_processor_id());
-#else
-       proc_id = 0;
-#endif
-
-       if (ctx->flags.system)
-               entry = &pfm_nb_sys_owners[proc_id];
-       else
-               entry = &pfm_nb_task_owner;
-
-       old = cmpxchg(entry, NULL, ctx);
-       if (!old) {
-               if (ctx->flags.system)
-                       PFM_DBG("acquired Northbridge event access on socket 
%u", proc_id);
-               else
-                       PFM_DBG("acquired Northbridge event access globally");
-       } else if (old != ctx) {
-               if (ctx->flags.system)
-                       PFM_DBG("NorthBridge event conflict on socket %u", 
proc_id);
-               else
-                       PFM_DBG("global NorthBridge event conflict");
-               return -EBUSY;
-       }
-       return 0;
-}
-
-/*
- * invoked from pfm_write_pmcs() when pfm_nb_sys_owners is not NULL,i.e.,
- * when we have detected a multi-core processor.
- *
- * context is locked, interrupts are masked
- */
-static int pfm_amd64_pmc_write_check(struct pfm_context *ctx,
-                            struct pfm_event_set *set,
-                            struct pfarg_pmc *req)
-{
-       unsigned int event;
-       /*
-        * delay checking NB event until we load the context
-        */
-       if (ctx->state == PFM_CTX_UNLOADED)
-               return 0;
-
-       /*
-        * check event is NB event
-        */
-       event = (unsigned int)(req->reg_value & 0xff);
-       if (event < 0xee)
-               return 0;
-
-       return pfm_amd64_acquire_nb(ctx);
-}
-
-/*
- * invoked on pfm_load_context().
- * context is locked, interrupts are masked
- */
-static int pfm_amd64_load_context(struct pfm_context *ctx)
-{
-       struct pfm_event_set *set;
-       unsigned int i, n;
-
-       /*
-        * scan all sets for NB events
-        */
-       list_for_each_entry(set, &ctx->list, list) {
-               n = set->nused_pmcs;
-               for (i = 0; n; i++) {
-                       if (!test_bit(i, cast_ulp(set->used_pmcs)))
-                               continue;
-                       if ((set->pmcs[i] & 0xff) >= 0xee)
-                               goto found;
-                       n--;
-               }
-       }
-       return 0;
-found:
-       return pfm_amd64_acquire_nb(ctx);
-}
-
-/*
- * invoked on pfm_unload_context()
- */
-static int pfm_amd64_unload_context(struct pfm_context *ctx)
-{
-       struct pfm_context **entry, *old;
-       int proc_id;
-
-#ifdef CONFIG_SMP
-       proc_id = topology_physical_package_id(smp_processor_id());
-#else
-       proc_id = 0;
-#endif
-
-       /*
-        * unload always happens on the monitored CPU in system-wide
-        */
-       if (ctx->flags.system)
-               entry = &pfm_nb_sys_owners[proc_id];
-       else
-               entry = &pfm_nb_task_owner;
-
-       old = cmpxchg(entry, ctx, NULL);
-       if (old == ctx) {
-               if (ctx->flags.system)
-                       PFM_DBG("released NorthBridge on socket %u", proc_id);
-               else
-                       PFM_DBG("released NorthBridge events globally");
-       }
-       return 0;
-}
-
-/*
- * detect if we need to active NorthBridge event access control
- */
-static int pfm_amd64_setup_nb_event_control(void)
-{
-       unsigned int c, n = 0;
-       unsigned int max_phys = 0;
-
-#ifdef CONFIG_SMP
-       for_each_possible_cpu(c) {
-               if (cpu_data[c].phys_proc_id > max_phys)
-                       max_phys = cpu_data[c].phys_proc_id;
-       }
-#else
-       max_phys = 0;
-#endif
-       if (max_phys > 255) {
-               PFM_INFO("socket id %d is too big to handle", max_phys);
-               return -ENOMEM;
-       }
-
-       n = max_phys + 1;
-       if (n < 2)
-               return 0;
-
-       pfm_nb_sys_owners = vmalloc(n * sizeof(*pfm_nb_sys_owners));
-       if (!pfm_nb_sys_owners)
-               return -ENOMEM;
-
-       memset(pfm_nb_sys_owners, 0, n * sizeof(*pfm_nb_sys_owners));
-       pfm_nb_task_owner = NULL;
-
-       /*
-        * activate write-checker for PMC registers
-        */
-       for (c = 0; c < PFM_AMD_NUM_PMCS; c++) {
-               pfm_amd64_pmc_desc[c].type |= PFM_REG_WC;
-       }
-
-       pfm_amd64_pmu_info.load_context = pfm_amd64_load_context;
-       pfm_amd64_pmu_info.unload_context = pfm_amd64_unload_context;
-
-       pfm_amd64_pmu_conf.pmc_write_check = pfm_amd64_pmc_write_check;
-
-       PFM_INFO("NorthBridge event access control enabled");
-
-       return 0;
-}
-
-static int pfm_amd64_probe_pmu(void)
-{
-       if (current_cpu_data.x86_vendor != X86_VENDOR_AMD) {
-               PFM_INFO("not an AMD processor");
-               return -1;
-       }
-
-       switch (current_cpu_data.x86) {
-       case 15:
-       case 16:
-               PFM_INFO("found family=%d", current_cpu_data.x86);
-               break;
-       default:
-               PFM_INFO("unsupported family=%d", current_cpu_data.x86);
-               return -1;
-       }
-
-       /*
-        * check for local APIC (required)
-        */
-       if (!cpu_has_apic) {
-               PFM_INFO("no local APIC, unsupported");
-               return -1;
-       }
-
-       if (current_cpu_data.x86_max_cores > 1)
-               return pfm_amd64_setup_nb_event_control();
-
-       PFM_INFO("nmi_watchdog=%d nmi_active=%d force_nmi=%d",
-               nmi_watchdog, atomic_read(&nmi_active), force_nmi);
-       /*
-        * NMI using PMU?
-        * Actual removal of NMI counter is done by pfm_pmu_acquire()
-        */
-       if (nmi_watchdog == NMI_LOCAL_APIC || force_nmi)
-               pfm_amd64_pmu_info.flags |= PFM_X86_FL_USE_NMI;
-
-       return 0;
-}
-
-static struct pfm_pmu_config pfm_amd64_pmu_conf = {
-       .pmu_name = "AMD64",
-       .counter_width = 47,
-       .pmd_desc = pfm_amd64_pmd_desc,
-       .pmc_desc = pfm_amd64_pmc_desc,
-       .num_pmc_entries = PFM_AMD_NUM_PMCS,
-       .num_pmd_entries = PFM_AMD_NUM_PMDS,
-       .probe_pmu = pfm_amd64_probe_pmu,
-       .version = "1.1",
-       .arch_info = &pfm_amd64_pmu_info,
-       .flags = PFM_PMU_BUILTIN_FLAG,
-       .owner = THIS_MODULE
-};
-
-static int __init pfm_amd64_pmu_init_module(void)
-{
-       return pfm_pmu_register(&pfm_amd64_pmu_conf);
-}
-
-static void __exit pfm_amd64_pmu_cleanup_module(void)
-{
-       if (pfm_nb_sys_owners)
-               vfree(pfm_nb_sys_owners);
-
-       pfm_pmu_unregister(&pfm_amd64_pmu_conf);
-}
-
-module_init(pfm_amd64_pmu_init_module);
-module_exit(pfm_amd64_pmu_cleanup_module);

-- 
AMD Saxony, Dresden, Germany
Operating System Research Center
email: [EMAIL PROTECTED]



_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

Reply via email to