blob: 2a0eeb4e0243797af01ea748af2fdb0dac66c603 [file] [log] [blame]
/*
* perfmon.c: perfmon2 global initialization functions
*
* This file implements the perfmon2 interface which
* provides access to the hardware performance counters
* of the host processor.
*
*
* The initial version of perfmon.c was written by
* Ganesh Venkitachalam, IBM Corp.
*
* Then it was modified for perfmon-1.x by Stephane Eranian and
* David Mosberger, Hewlett Packard Co.
*
* Version Perfmon-2.x is a complete rewrite of perfmon-1.x
* by Stephane Eranian, Hewlett Packard Co.
*
* Copyright (c) 1999-2006 Hewlett-Packard Development Company, L.P.
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* More information about perfmon available at:
* http://perfmon2.sf.net
*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/perfmon_kern.h>
#include "perfmon_priv.h"
/*
* external variables
*/
DEFINE_PER_CPU(struct task_struct *, pmu_owner);
DEFINE_PER_CPU(struct pfm_context *, pmu_ctx);
DEFINE_PER_CPU(u64, pmu_activation_number);
DEFINE_PER_CPU(struct pfm_stats, pfm_stats);
DEFINE_PER_CPU(struct hrtimer, pfm_hrtimer);
EXPORT_PER_CPU_SYMBOL(pmu_ctx);
int perfmon_disabled; /* >0 if perfmon is disabled */
/*
* called from cpu_init() and pfm_pmu_register()
*/
void __pfm_init_percpu(void *dummy)
{
struct hrtimer *h;
h = &__get_cpu_var(pfm_hrtimer);
pfm_arch_init_percpu();
/*
* initialize per-cpu high res timer
*/
hrtimer_init(h, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
#ifdef CONFIG_HIGH_RES_TIMERS
/*
* avoid potential deadlock on the runqueue lock
* during context switch when multiplexing. Situation
* arises on architectures which run switch_to() with
* the runqueue lock held, e.g., x86. On others, e.g.,
* IA-64, the problem does not exist.
* Setting the callback mode to HRTIMER_CB_IRQSAFE_UNOCKED
* such that the callback routine is only called on hardirq
* context not on softirq, thus the context switch will not
* end up trying to wakeup the softirqd
*/
//h->cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
#endif
h->function = pfm_handle_switch_timeout;
}
/*
* global initialization routine, executed only once
*/
int __init pfm_init(void)
{
PFM_LOG("version %u.%u", PFM_VERSION_MAJ, PFM_VERSION_MIN);
if (pfm_init_ctx())
goto error_disable;
if (pfm_init_sets())
goto error_disable;
if (pfm_init_sysfs())
goto error_disable;
if (pfm_init_control())
goto error_disable;
/* not critical, so no error checking */
pfm_init_debugfs();
/*
* one time, arch-specific global initialization
*/
if (pfm_arch_init())
goto error_disable;
if (pfm_init_hotplug())
goto error_disable;
return 0;
error_disable:
PFM_ERR("perfmon is disabled due to initialization error");
perfmon_disabled = 1;
return -1;
}
/*
* must use subsys_initcall() to ensure that the perfmon2 core
* is initialized before any PMU description module when they are
* compiled in.
*/
subsys_initcall(pfm_init);