source: trunk/packages/xen-3.1/xen-3.1/xen/arch/ia64/linux-xen/perfmon_default_smpl.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

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