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