linux-bk/arch/ppc/oprofile/common.c
<<
>>
Prefs
   1/*
   2 * PPC 32 oprofile support
   3 * Based on PPC64 oprofile support
   4 * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
   5 *
   6 * Copyright (C) Freescale Semiconductor, Inc 2004
   7 *
   8 * Author: Andy Fleming
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License
  12 * as published by the Free Software Foundation; either version
  13 * 2 of the License, or (at your option) any later version.
  14 */
  15
  16#include <linux/oprofile.h>
  17#include <linux/slab.h>
  18#include <linux/init.h>
  19#include <linux/smp.h>
  20#include <linux/errno.h>
  21#include <asm/ptrace.h>
  22#include <asm/system.h>
  23#include <asm/perfmon.h>
  24#include <asm/cputable.h>
  25
  26#include "op_impl.h"
  27
  28static struct op_ppc32_model *model;
  29
  30static struct op_counter_config ctr[OP_MAX_COUNTER];
  31static struct op_system_config sys;
  32
  33static void op_handle_interrupt(struct pt_regs *regs)
  34{
  35        model->handle_interrupt(regs, ctr);
  36}
  37
  38static int op_ppc32_setup(void)
  39{
  40        /* Install our interrupt handler into the existing hook.  */
  41        if(request_perfmon_irq(&op_handle_interrupt))
  42                return -EBUSY;
  43
  44        mb();
  45
  46        /* Pre-compute the values to stuff in the hardware registers.  */
  47        model->reg_setup(ctr, &sys, model->num_counters);
  48
  49#if 0
  50        /* FIXME: Make multi-cpu work */
  51        /* Configure the registers on all cpus.  */
  52        on_each_cpu(model->reg_setup, NULL, 0, 1);
  53#endif
  54
  55        return 0;
  56}
  57
  58static void op_ppc32_shutdown(void)
  59{
  60        mb();
  61
  62        /* Remove our interrupt handler. We may be removing this module. */
  63        free_perfmon_irq();
  64}
  65
  66static void op_ppc32_cpu_start(void *dummy)
  67{
  68        model->start(ctr);
  69}
  70
  71static int op_ppc32_start(void)
  72{
  73        on_each_cpu(op_ppc32_cpu_start, NULL, 0, 1);
  74        return 0;
  75}
  76
  77static inline void op_ppc32_cpu_stop(void *dummy)
  78{
  79        model->stop();
  80}
  81
  82static void op_ppc32_stop(void)
  83{
  84        on_each_cpu(op_ppc32_cpu_stop, NULL, 0, 1);
  85}
  86
  87static int op_ppc32_create_files(struct super_block *sb, struct dentry *root)
  88{
  89        int i;
  90
  91        for (i = 0; i < model->num_counters; ++i) {
  92                struct dentry *dir;
  93                char buf[3];
  94
  95                snprintf(buf, sizeof buf, "%d", i);
  96                dir = oprofilefs_mkdir(sb, root, buf);
  97
  98                oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
  99                oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
 100                oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
 101                oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
 102                oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
 103
 104                /* FIXME: Not sure if this is used */
 105                oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
 106        }
 107
 108        oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
 109        oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
 110
 111        /* Default to tracing both kernel and user */
 112        sys.enable_kernel = 1;
 113        sys.enable_user = 1;
 114
 115        return 0;
 116}
 117
 118static struct oprofile_operations oprof_ppc32_ops = {
 119        .create_files   = op_ppc32_create_files,
 120        .setup          = op_ppc32_setup,
 121        .shutdown       = op_ppc32_shutdown,
 122        .start          = op_ppc32_start,
 123        .stop           = op_ppc32_stop,
 124        .cpu_type       = NULL          /* To be filled in below. */
 125};
 126
 127int __init oprofile_arch_init(struct oprofile_operations *ops)
 128{
 129        char *name;
 130        int cpu_id = smp_processor_id();
 131
 132#ifdef CONFIG_FSL_BOOKE
 133        model = &op_model_fsl_booke;
 134#else
 135        return -ENODEV;
 136#endif
 137
 138        name = kmalloc(32, GFP_KERNEL);
 139
 140        if (NULL == name)
 141                return -ENOMEM;
 142
 143        sprintf(name, "ppc/%s", cur_cpu_spec[cpu_id]->cpu_name);
 144
 145        oprof_ppc32_ops.cpu_type = name;
 146
 147        model->num_counters = cur_cpu_spec[cpu_id]->num_pmcs;
 148
 149        *ops = oprof_ppc32_ops;
 150
 151        printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
 152               oprof_ppc32_ops.cpu_type);
 153
 154        return 0;
 155}
 156
 157void oprofile_arch_exit(void)
 158{
 159        kfree(oprof_ppc32_ops.cpu_type);
 160        oprof_ppc32_ops.cpu_type = NULL;
 161}
 162
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.