root/arch/powerpc/oprofile/common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. op_handle_interrupt
  2. op_powerpc_cpu_setup
  3. op_powerpc_setup
  4. op_powerpc_shutdown
  5. op_powerpc_cpu_start
  6. op_powerpc_start
  7. op_powerpc_cpu_stop
  8. op_powerpc_stop
  9. op_powerpc_create_files
  10. oprofile_arch_init
  11. oprofile_arch_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * PPC 64 oprofile support:
   4  * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
   5  * PPC 32 oprofile support: (based on PPC 64 support)
   6  * Copyright (C) Freescale Semiconductor, Inc 2004
   7  *      Author: Andy Fleming
   8  *
   9  * Based on alpha version.
  10  */
  11 
  12 #include <linux/oprofile.h>
  13 #include <linux/init.h>
  14 #include <linux/smp.h>
  15 #include <linux/errno.h>
  16 #include <asm/ptrace.h>
  17 #include <asm/pmc.h>
  18 #include <asm/cputable.h>
  19 #include <asm/oprofile_impl.h>
  20 #include <asm/firmware.h>
  21 
  22 static struct op_powerpc_model *model;
  23 
  24 static struct op_counter_config ctr[OP_MAX_COUNTER];
  25 static struct op_system_config sys;
  26 
  27 static int op_per_cpu_rc;
  28 
  29 static void op_handle_interrupt(struct pt_regs *regs)
  30 {
  31         model->handle_interrupt(regs, ctr);
  32 }
  33 
  34 static void op_powerpc_cpu_setup(void *dummy)
  35 {
  36         int ret;
  37 
  38         ret = model->cpu_setup(ctr);
  39 
  40         if (ret != 0)
  41                 op_per_cpu_rc = ret;
  42 }
  43 
  44 static int op_powerpc_setup(void)
  45 {
  46         int err;
  47 
  48         op_per_cpu_rc = 0;
  49 
  50         /* Grab the hardware */
  51         err = reserve_pmc_hardware(op_handle_interrupt);
  52         if (err)
  53                 return err;
  54 
  55         /* Pre-compute the values to stuff in the hardware registers.  */
  56         op_per_cpu_rc = model->reg_setup(ctr, &sys, model->num_counters);
  57 
  58         if (op_per_cpu_rc)
  59                 goto out;
  60 
  61         /* Configure the registers on all cpus.  If an error occurs on one
  62          * of the cpus, op_per_cpu_rc will be set to the error */
  63         on_each_cpu(op_powerpc_cpu_setup, NULL, 1);
  64 
  65 out:    if (op_per_cpu_rc) {
  66                 /* error on setup release the performance counter hardware */
  67                 release_pmc_hardware();
  68         }
  69 
  70         return op_per_cpu_rc;
  71 }
  72 
  73 static void op_powerpc_shutdown(void)
  74 {
  75         release_pmc_hardware();
  76 }
  77 
  78 static void op_powerpc_cpu_start(void *dummy)
  79 {
  80         /* If any of the cpus have return an error, set the
  81          * global flag to the error so it can be returned
  82          * to the generic OProfile caller.
  83          */
  84         int ret;
  85 
  86         ret = model->start(ctr);
  87         if (ret != 0)
  88                 op_per_cpu_rc = ret;
  89 }
  90 
  91 static int op_powerpc_start(void)
  92 {
  93         op_per_cpu_rc = 0;
  94 
  95         if (model->global_start)
  96                 return model->global_start(ctr);
  97         if (model->start) {
  98                 on_each_cpu(op_powerpc_cpu_start, NULL, 1);
  99                 return op_per_cpu_rc;
 100         }
 101         return -EIO; /* No start function is defined for this
 102                         power architecture */
 103 }
 104 
 105 static inline void op_powerpc_cpu_stop(void *dummy)
 106 {
 107         model->stop();
 108 }
 109 
 110 static void op_powerpc_stop(void)
 111 {
 112         if (model->stop)
 113                 on_each_cpu(op_powerpc_cpu_stop, NULL, 1);
 114         if (model->global_stop)
 115                 model->global_stop();
 116 }
 117 
 118 static int op_powerpc_create_files(struct dentry *root)
 119 {
 120         int i;
 121 
 122 #ifdef CONFIG_PPC64
 123         /*
 124          * There is one mmcr0, mmcr1 and mmcra for setting the events for
 125          * all of the counters.
 126          */
 127         oprofilefs_create_ulong(root, "mmcr0", &sys.mmcr0);
 128         oprofilefs_create_ulong(root, "mmcr1", &sys.mmcr1);
 129         oprofilefs_create_ulong(root, "mmcra", &sys.mmcra);
 130 #ifdef CONFIG_OPROFILE_CELL
 131         /* create a file the user tool can check to see what level of profiling
 132          * support exits with this kernel. Initialize bit mask to indicate
 133          * what support the kernel has:
 134          * bit 0      -  Supports SPU event profiling in addition to PPU
 135          *               event and cycles; and SPU cycle profiling
 136          * bits 1-31  -  Currently unused.
 137          *
 138          * If the file does not exist, then the kernel only supports SPU
 139          * cycle profiling, PPU event and cycle profiling.
 140          */
 141         oprofilefs_create_ulong(root, "cell_support", &sys.cell_support);
 142         sys.cell_support = 0x1; /* Note, the user OProfile tool must check
 143                                  * that this bit is set before attempting to
 144                                  * user SPU event profiling.  Older kernels
 145                                  * will not have this file, hence the user
 146                                  * tool is not allowed to do SPU event
 147                                  * profiling on older kernels.  Older kernels
 148                                  * will accept SPU events but collected data
 149                                  * is garbage.
 150                                  */
 151 #endif
 152 #endif
 153 
 154         for (i = 0; i < model->num_counters; ++i) {
 155                 struct dentry *dir;
 156                 char buf[4];
 157 
 158                 snprintf(buf, sizeof buf, "%d", i);
 159                 dir = oprofilefs_mkdir(root, buf);
 160 
 161                 oprofilefs_create_ulong(dir, "enabled", &ctr[i].enabled);
 162                 oprofilefs_create_ulong(dir, "event", &ctr[i].event);
 163                 oprofilefs_create_ulong(dir, "count", &ctr[i].count);
 164 
 165                 /*
 166                  * Classic PowerPC doesn't support per-counter
 167                  * control like this, but the options are
 168                  * expected, so they remain.  For Freescale
 169                  * Book-E style performance monitors, we do
 170                  * support them.
 171                  */
 172                 oprofilefs_create_ulong(dir, "kernel", &ctr[i].kernel);
 173                 oprofilefs_create_ulong(dir, "user", &ctr[i].user);
 174 
 175                 oprofilefs_create_ulong(dir, "unit_mask", &ctr[i].unit_mask);
 176         }
 177 
 178         oprofilefs_create_ulong(root, "enable_kernel", &sys.enable_kernel);
 179         oprofilefs_create_ulong(root, "enable_user", &sys.enable_user);
 180 
 181         /* Default to tracing both kernel and user */
 182         sys.enable_kernel = 1;
 183         sys.enable_user = 1;
 184 
 185         return 0;
 186 }
 187 
 188 int __init oprofile_arch_init(struct oprofile_operations *ops)
 189 {
 190         if (!cur_cpu_spec->oprofile_cpu_type)
 191                 return -ENODEV;
 192 
 193         switch (cur_cpu_spec->oprofile_type) {
 194 #ifdef CONFIG_PPC_BOOK3S_64
 195 #ifdef CONFIG_OPROFILE_CELL
 196                 case PPC_OPROFILE_CELL:
 197                         if (firmware_has_feature(FW_FEATURE_LPAR))
 198                                 return -ENODEV;
 199                         model = &op_model_cell;
 200                         ops->sync_start = model->sync_start;
 201                         ops->sync_stop = model->sync_stop;
 202                         break;
 203 #endif
 204                 case PPC_OPROFILE_POWER4:
 205                         model = &op_model_power4;
 206                         break;
 207                 case PPC_OPROFILE_PA6T:
 208                         model = &op_model_pa6t;
 209                         break;
 210 #endif
 211 #ifdef CONFIG_PPC_BOOK3S_32
 212                 case PPC_OPROFILE_G4:
 213                         model = &op_model_7450;
 214                         break;
 215 #endif
 216 #if defined(CONFIG_FSL_EMB_PERFMON)
 217                 case PPC_OPROFILE_FSL_EMB:
 218                         model = &op_model_fsl_emb;
 219                         break;
 220 #endif
 221                 default:
 222                         return -ENODEV;
 223         }
 224 
 225         model->num_counters = cur_cpu_spec->num_pmcs;
 226 
 227         ops->cpu_type = cur_cpu_spec->oprofile_cpu_type;
 228         ops->create_files = op_powerpc_create_files;
 229         ops->setup = op_powerpc_setup;
 230         ops->shutdown = op_powerpc_shutdown;
 231         ops->start = op_powerpc_start;
 232         ops->stop = op_powerpc_stop;
 233         ops->backtrace = op_powerpc_backtrace;
 234 
 235         printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n",
 236                ops->cpu_type);
 237 
 238         return 0;
 239 }
 240 
 241 void oprofile_arch_exit(void)
 242 {
 243 }

/* [<][>][^][v][top][bottom][index][help] */