root/arch/ia64/kernel/perfmon_default_smpl.c

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

DEFINITIONS

This source file includes following definitions.
  1. default_validate
  2. default_get_size
  3. default_init
  4. default_handler
  5. default_restart
  6. default_exit
  7. pfm_default_smpl_init_module
  8. pfm_default_smpl_cleanup_module

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2002-2003 Hewlett-Packard Co
   4  *               Stephane Eranian <eranian@hpl.hp.com>
   5  *
   6  * This file implements the default sampling buffer format
   7  * for the Linux/ia64 perfmon-2 subsystem.
   8  */
   9 #include <linux/kernel.h>
  10 #include <linux/types.h>
  11 #include <linux/module.h>
  12 #include <linux/init.h>
  13 #include <asm/delay.h>
  14 #include <linux/smp.h>
  15 
  16 #include <asm/perfmon.h>
  17 #include <asm/perfmon_default_smpl.h>
  18 
  19 MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
  20 MODULE_DESCRIPTION("perfmon default sampling format");
  21 MODULE_LICENSE("GPL");
  22 
  23 #define DEFAULT_DEBUG 1
  24 
  25 #ifdef DEFAULT_DEBUG
  26 #define DPRINT(a) \
  27         do { \
  28                 if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d ", __func__, __LINE__, smp_processor_id()); printk a; } \
  29         } while (0)
  30 
  31 #define DPRINT_ovfl(a) \
  32         do { \
  33                 if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d ", __func__, __LINE__, smp_processor_id()); printk a; } \
  34         } while (0)
  35 
  36 #else
  37 #define DPRINT(a)
  38 #define DPRINT_ovfl(a)
  39 #endif
  40 
  41 static int
  42 default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data)
  43 {
  44         pfm_default_smpl_arg_t *arg = (pfm_default_smpl_arg_t*)data;
  45         int ret = 0;
  46 
  47         if (data == NULL) {
  48                 DPRINT(("[%d] no argument passed\n", task_pid_nr(task)));
  49                 return -EINVAL;
  50         }
  51 
  52         DPRINT(("[%d] validate flags=0x%x CPU%d\n", task_pid_nr(task), flags, cpu));
  53 
  54         /*
  55          * must hold at least the buffer header + one minimally sized entry
  56          */
  57         if (arg->buf_size < PFM_DEFAULT_SMPL_MIN_BUF_SIZE) return -EINVAL;
  58 
  59         DPRINT(("buf_size=%lu\n", arg->buf_size));
  60 
  61         return ret;
  62 }
  63 
  64 static int
  65 default_get_size(struct task_struct *task, unsigned int flags, int cpu, void *data, unsigned long *size)
  66 {
  67         pfm_default_smpl_arg_t *arg = (pfm_default_smpl_arg_t *)data;
  68 
  69         /*
  70          * size has been validated in default_validate
  71          */
  72         *size = arg->buf_size;
  73 
  74         return 0;
  75 }
  76 
  77 static int
  78 default_init(struct task_struct *task, void *buf, unsigned int flags, int cpu, void *data)
  79 {
  80         pfm_default_smpl_hdr_t *hdr;
  81         pfm_default_smpl_arg_t *arg = (pfm_default_smpl_arg_t *)data;
  82 
  83         hdr = (pfm_default_smpl_hdr_t *)buf;
  84 
  85         hdr->hdr_version      = PFM_DEFAULT_SMPL_VERSION;
  86         hdr->hdr_buf_size     = arg->buf_size;
  87         hdr->hdr_cur_offs     = sizeof(*hdr);
  88         hdr->hdr_overflows    = 0UL;
  89         hdr->hdr_count        = 0UL;
  90 
  91         DPRINT(("[%d] buffer=%p buf_size=%lu hdr_size=%lu hdr_version=%u cur_offs=%lu\n",
  92                 task_pid_nr(task),
  93                 buf,
  94                 hdr->hdr_buf_size,
  95                 sizeof(*hdr),
  96                 hdr->hdr_version,
  97                 hdr->hdr_cur_offs));
  98 
  99         return 0;
 100 }
 101 
 102 static int
 103 default_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg, struct pt_regs *regs, unsigned long stamp)
 104 {
 105         pfm_default_smpl_hdr_t *hdr;
 106         pfm_default_smpl_entry_t *ent;
 107         void *cur, *last;
 108         unsigned long *e, entry_size;
 109         unsigned int npmds, i;
 110         unsigned char ovfl_pmd;
 111         unsigned char ovfl_notify;
 112 
 113         if (unlikely(buf == NULL || arg == NULL|| regs == NULL || task == NULL)) {
 114                 DPRINT(("[%d] invalid arguments buf=%p arg=%p\n", task->pid, buf, arg));
 115                 return -EINVAL;
 116         }
 117 
 118         hdr         = (pfm_default_smpl_hdr_t *)buf;
 119         cur         = buf+hdr->hdr_cur_offs;
 120         last        = buf+hdr->hdr_buf_size;
 121         ovfl_pmd    = arg->ovfl_pmd;
 122         ovfl_notify = arg->ovfl_notify;
 123 
 124         /*
 125          * precheck for sanity
 126          */
 127         if ((last - cur) < PFM_DEFAULT_MAX_ENTRY_SIZE) goto full;
 128 
 129         npmds = hweight64(arg->smpl_pmds[0]);
 130 
 131         ent = (pfm_default_smpl_entry_t *)cur;
 132 
 133         prefetch(arg->smpl_pmds_values);
 134 
 135         entry_size = sizeof(*ent) + (npmds << 3);
 136 
 137         /* position for first pmd */
 138         e = (unsigned long *)(ent+1);
 139 
 140         hdr->hdr_count++;
 141 
 142         DPRINT_ovfl(("[%d] count=%lu cur=%p last=%p free_bytes=%lu ovfl_pmd=%d ovfl_notify=%d npmds=%u\n",
 143                         task->pid,
 144                         hdr->hdr_count,
 145                         cur, last,
 146                         last-cur,
 147                         ovfl_pmd,
 148                         ovfl_notify, npmds));
 149 
 150         /*
 151          * current = task running at the time of the overflow.
 152          *
 153          * per-task mode:
 154          *      - this is usually the task being monitored.
 155          *        Under certain conditions, it might be a different task
 156          *
 157          * system-wide:
 158          *      - this is not necessarily the task controlling the session
 159          */
 160         ent->pid            = current->pid;
 161         ent->ovfl_pmd       = ovfl_pmd;
 162         ent->last_reset_val = arg->pmd_last_reset; //pmd[0].reg_last_reset_val;
 163 
 164         /*
 165          * where did the fault happen (includes slot number)
 166          */
 167         ent->ip = regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3);
 168 
 169         ent->tstamp    = stamp;
 170         ent->cpu       = smp_processor_id();
 171         ent->set       = arg->active_set;
 172         ent->tgid      = current->tgid;
 173 
 174         /*
 175          * selectively store PMDs in increasing index number
 176          */
 177         if (npmds) {
 178                 unsigned long *val = arg->smpl_pmds_values;
 179                 for(i=0; i < npmds; i++) {
 180                         *e++ = *val++;
 181                 }
 182         }
 183 
 184         /*
 185          * update position for next entry
 186          */
 187         hdr->hdr_cur_offs += entry_size;
 188         cur               += entry_size;
 189 
 190         /*
 191          * post check to avoid losing the last sample
 192          */
 193         if ((last - cur) < PFM_DEFAULT_MAX_ENTRY_SIZE) goto full;
 194 
 195         /*
 196          * keep same ovfl_pmds, ovfl_notify
 197          */
 198         arg->ovfl_ctrl.bits.notify_user     = 0;
 199         arg->ovfl_ctrl.bits.block_task      = 0;
 200         arg->ovfl_ctrl.bits.mask_monitoring = 0;
 201         arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1; /* reset before returning from interrupt handler */
 202 
 203         return 0;
 204 full:
 205         DPRINT_ovfl(("sampling buffer full free=%lu, count=%lu, ovfl_notify=%d\n", last-cur, hdr->hdr_count, ovfl_notify));
 206 
 207         /*
 208          * increment number of buffer overflow.
 209          * important to detect duplicate set of samples.
 210          */
 211         hdr->hdr_overflows++;
 212 
 213         /*
 214          * if no notification requested, then we saturate the buffer
 215          */
 216         if (ovfl_notify == 0) {
 217                 arg->ovfl_ctrl.bits.notify_user     = 0;
 218                 arg->ovfl_ctrl.bits.block_task      = 0;
 219                 arg->ovfl_ctrl.bits.mask_monitoring = 1;
 220                 arg->ovfl_ctrl.bits.reset_ovfl_pmds = 0;
 221         } else {
 222                 arg->ovfl_ctrl.bits.notify_user     = 1;
 223                 arg->ovfl_ctrl.bits.block_task      = 1; /* ignored for non-blocking context */
 224                 arg->ovfl_ctrl.bits.mask_monitoring = 1;
 225                 arg->ovfl_ctrl.bits.reset_ovfl_pmds = 0; /* no reset now */
 226         }
 227         return -1; /* we are full, sorry */
 228 }
 229 
 230 static int
 231 default_restart(struct task_struct *task, pfm_ovfl_ctrl_t *ctrl, void *buf, struct pt_regs *regs)
 232 {
 233         pfm_default_smpl_hdr_t *hdr;
 234 
 235         hdr = (pfm_default_smpl_hdr_t *)buf;
 236 
 237         hdr->hdr_count    = 0UL;
 238         hdr->hdr_cur_offs = sizeof(*hdr);
 239 
 240         ctrl->bits.mask_monitoring = 0;
 241         ctrl->bits.reset_ovfl_pmds = 1; /* uses long-reset values */
 242 
 243         return 0;
 244 }
 245 
 246 static int
 247 default_exit(struct task_struct *task, void *buf, struct pt_regs *regs)
 248 {
 249         DPRINT(("[%d] exit(%p)\n", task_pid_nr(task), buf));
 250         return 0;
 251 }
 252 
 253 static pfm_buffer_fmt_t default_fmt={
 254         .fmt_name           = "default_format",
 255         .fmt_uuid           = PFM_DEFAULT_SMPL_UUID,
 256         .fmt_arg_size       = sizeof(pfm_default_smpl_arg_t),
 257         .fmt_validate       = default_validate,
 258         .fmt_getsize        = default_get_size,
 259         .fmt_init           = default_init,
 260         .fmt_handler        = default_handler,
 261         .fmt_restart        = default_restart,
 262         .fmt_restart_active = default_restart,
 263         .fmt_exit           = default_exit,
 264 };
 265 
 266 static int __init
 267 pfm_default_smpl_init_module(void)
 268 {
 269         int ret;
 270 
 271         ret = pfm_register_buffer_fmt(&default_fmt);
 272         if (ret == 0) {
 273                 printk("perfmon_default_smpl: %s v%u.%u registered\n",
 274                         default_fmt.fmt_name,
 275                         PFM_DEFAULT_SMPL_VERSION_MAJ,
 276                         PFM_DEFAULT_SMPL_VERSION_MIN);
 277         } else {
 278                 printk("perfmon_default_smpl: %s cannot register ret=%d\n",
 279                         default_fmt.fmt_name,
 280                         ret);
 281         }
 282 
 283         return ret;
 284 }
 285 
 286 static void __exit
 287 pfm_default_smpl_cleanup_module(void)
 288 {
 289         int ret;
 290         ret = pfm_unregister_buffer_fmt(default_fmt.fmt_uuid);
 291 
 292         printk("perfmon_default_smpl: unregister %s=%d\n", default_fmt.fmt_name, ret);
 293 }
 294 
 295 module_init(pfm_default_smpl_init_module);
 296 module_exit(pfm_default_smpl_cleanup_module);
 297 

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