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