remarkable-linux/drivers/oprofile/timer_int.c
Heinz Graalfs 997dbb4967 oprofile, s390: Enhance OProfile to support System zs hardware sampling feature
OProfile is enhanced to export all files for controlling System z's
hardware sampling, and to invoke hwsampler exported functions to
initialize and use System z's hardware sampling.

The patch invokes hwsampler_setup() during oprofile init and exports
following hwsampler files under oprofilefs if hwsampler's setup
succeeded:

A new directory for hardware sampling based files

 /dev/oprofile/hwsampling/

The userland daemon must explicitly write to the following files
to disable (or enable) hardware based sampling

 /dev/oprofile/hwsampling/hwsampler

to modify the actual sampling rate

 /dev/oprofile/hwsampling/hw_interval

to modify the amount of sampling memory (measured in 4K pages)

 /dev/oprofile/hwsampling/hw_sdbt_blocks

The following files are read only and show
the possible minimum sampling rate

 /dev/oprofile/hwsampling/hw_min_interval

the possible maximum sampling rate

 /dev/oprofile/hwsampling/hw_max_interval

The patch splits the oprofile_timer_[init/exit] function so that it
can be also called through user context (oprofilefs) to avoid kernel
oops.

Applied with following changes:
* whitespace changes in Makefile and timer_int.c

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Maran Pakkirisamy <maranp@linux.vnet.ibm.com>
Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Robert Richter <robert.richter@amd.com>
2011-02-15 11:08:50 +01:00

129 lines
2.6 KiB
C

/**
* @file timer_int.c
*
* @remark Copyright 2002 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
*/
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/smp.h>
#include <linux/oprofile.h>
#include <linux/profile.h>
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/hrtimer.h>
#include <asm/irq_regs.h>
#include <asm/ptrace.h>
#include "oprof.h"
static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer);
static int ctr_running;
static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer)
{
oprofile_add_sample(get_irq_regs(), 0);
hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC));
return HRTIMER_RESTART;
}
static void __oprofile_hrtimer_start(void *unused)
{
struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer);
if (!ctr_running)
return;
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer->function = oprofile_hrtimer_notify;
hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC),
HRTIMER_MODE_REL_PINNED);
}
static int oprofile_hrtimer_start(void)
{
get_online_cpus();
ctr_running = 1;
on_each_cpu(__oprofile_hrtimer_start, NULL, 1);
put_online_cpus();
return 0;
}
static void __oprofile_hrtimer_stop(int cpu)
{
struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu);
if (!ctr_running)
return;
hrtimer_cancel(hrtimer);
}
static void oprofile_hrtimer_stop(void)
{
int cpu;
get_online_cpus();
for_each_online_cpu(cpu)
__oprofile_hrtimer_stop(cpu);
ctr_running = 0;
put_online_cpus();
}
static int __cpuinit oprofile_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
long cpu = (long) hcpu;
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
smp_call_function_single(cpu, __oprofile_hrtimer_start,
NULL, 1);
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
__oprofile_hrtimer_stop(cpu);
break;
}
return NOTIFY_OK;
}
static struct notifier_block __refdata oprofile_cpu_notifier = {
.notifier_call = oprofile_cpu_notify,
};
int __oprofile_timer_init(struct oprofile_operations *ops)
{
int rc;
rc = register_hotcpu_notifier(&oprofile_cpu_notifier);
if (rc)
return rc;
ops->setup = NULL;
ops->shutdown = NULL;
ops->start = oprofile_hrtimer_start;
ops->stop = oprofile_hrtimer_stop;
ops->cpu_type = "timer";
return 0;
}
int __init oprofile_timer_init(struct oprofile_operations *ops)
{
return __oprofile_timer_init(ops);
}
void __oprofile_timer_exit(void)
{
unregister_hotcpu_notifier(&oprofile_cpu_notifier);
}
void __exit oprofile_timer_exit(void)
{
__oprofile_timer_exit();
}