Robert,

I have applied this patch to my tree.
Thanks.

On Mon, Jul 02, 2007 at 05:58:07PM +0200, Robert Richter wrote:
> 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/

-- 

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

Reply via email to