2 * Copyright (c) 1999-2006 Hewlett-Packard Development Company, L.P.
3 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
5 * This file implements the new default sampling buffer format
6 * for the perfmon2 subsystem.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #include <linux/kernel.h>
23 #include <linux/types.h>
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/smp.h>
28 #include <linux/perfmon_kern.h>
29 #include <linux/perfmon_dfl_smpl.h>
31 MODULE_AUTHOR("Stephane Eranian <eranian@hpl.hp.com>");
32 MODULE_DESCRIPTION("new perfmon default sampling format");
33 MODULE_LICENSE("GPL");
35 static int pfm_dfl_fmt_validate(u32 ctx_flags, u16 npmds, void *data)
37 struct pfm_dfl_smpl_arg *arg = data;
41 PFM_DBG("no argument passed");
46 * sanity check in case size_t is smaller then u64
48 #if BITS_PER_LONG == 4
49 #define MAX_SIZE_T (1ULL<<(sizeof(size_t)<<3))
50 if (sizeof(size_t) < sizeof(arg->buf_size)) {
51 if (arg->buf_size >= MAX_SIZE_T)
57 * compute min buf size. npmds is the maximum number
58 * of implemented PMD registers.
60 min_buf_size = sizeof(struct pfm_dfl_smpl_hdr)
61 + (sizeof(struct pfm_dfl_smpl_entry) + (npmds*sizeof(u64)));
63 PFM_DBG("validate ctx_flags=0x%x flags=0x%x npmds=%u "
64 "min_buf_size=%llu buf_size=%llu\n",
68 (unsigned long long)min_buf_size,
69 (unsigned long long)arg->buf_size);
72 * must hold at least the buffer header + one minimally sized entry
74 if (arg->buf_size < min_buf_size)
80 static int pfm_dfl_fmt_get_size(u32 flags, void *data, size_t *size)
82 struct pfm_dfl_smpl_arg *arg = data;
85 * size has been validated in default_validate
86 * we can never loose bits from buf_size.
88 *size = (size_t)arg->buf_size;
93 static int pfm_dfl_fmt_init(struct pfm_context *ctx, void *buf, u32 ctx_flags,
94 u16 npmds, void *data)
96 struct pfm_dfl_smpl_hdr *hdr;
97 struct pfm_dfl_smpl_arg *arg = data;
101 hdr->hdr_version = PFM_DFL_SMPL_VERSION;
102 hdr->hdr_buf_size = arg->buf_size;
103 hdr->hdr_buf_flags = arg->buf_flags;
104 hdr->hdr_cur_offs = sizeof(*hdr);
105 hdr->hdr_overflows = 0;
107 hdr->hdr_min_buf_space = sizeof(struct pfm_dfl_smpl_entry) + (npmds*sizeof(u64));
109 * due to cache aliasing, it may be necessary to flush the cache
110 * on certain architectures (e.g., MIPS)
112 pfm_cacheflush(hdr, sizeof(*hdr));
114 PFM_DBG("buffer=%p buf_size=%llu hdr_size=%zu hdr_version=%u.%u "
115 "min_space=%llu npmds=%u",
117 (unsigned long long)hdr->hdr_buf_size,
119 PFM_VERSION_MAJOR(hdr->hdr_version),
120 PFM_VERSION_MINOR(hdr->hdr_version),
121 (unsigned long long)hdr->hdr_min_buf_space,
128 * called from pfm_overflow_handler() to record a new sample
130 * context is locked, interrupts are disabled (no preemption)
132 static int pfm_dfl_fmt_handler(struct pfm_context *ctx,
133 unsigned long ip, u64 tstamp, void *data)
135 struct pfm_dfl_smpl_hdr *hdr;
136 struct pfm_dfl_smpl_entry *ent;
137 struct pfm_ovfl_arg *arg;
140 size_t entry_size, min_size;
145 hdr = ctx->smpl_addr;
146 arg = &ctx->ovfl_arg;
149 cur = buf+hdr->hdr_cur_offs;
150 last = buf+hdr->hdr_buf_size;
151 ovfl_pmd = arg->ovfl_pmd;
152 min_size = hdr->hdr_min_buf_space;
155 * precheck for sanity
157 if ((last - cur) < min_size)
160 npmds = arg->num_smpl_pmds;
162 ent = (struct pfm_dfl_smpl_entry *)cur;
164 entry_size = sizeof(*ent) + (npmds << 3);
166 /* position for first pmd */
171 PFM_DBG_ovfl("count=%llu cur=%p last=%p free_bytes=%zu ovfl_pmd=%d "
173 (unsigned long long)hdr->hdr_count,
180 * current = task running at the time of the overflow.
183 * - this is usually the task being monitored.
184 * Under certain conditions, it might be a different task
187 * - this is not necessarily the task controlling the session
189 ent->pid = current->pid;
190 ent->ovfl_pmd = ovfl_pmd;
191 ent->last_reset_val = arg->pmd_last_reset;
194 * where did the fault happen (includes slot number)
198 ent->tstamp = tstamp;
199 ent->cpu = smp_processor_id();
200 ent->set = arg->active_set;
201 ent->tgid = current->tgid;
204 * selectively store PMDs in increasing index number
207 u64 *val = arg->smpl_pmds_values;
208 for (i = 0; i < npmds; i++)
213 * update position for next entry
215 hdr->hdr_cur_offs += entry_size;
218 pfm_cacheflush(hdr, sizeof(*hdr));
219 pfm_cacheflush(ent, entry_size);
222 * post check to avoid losing the last sample
224 if ((last - cur) < min_size)
227 /* reset before returning from interrupt handler */
228 arg->ovfl_ctrl = PFM_OVFL_CTRL_RESET;
232 PFM_DBG_ovfl("sampling buffer full free=%zu, count=%llu",
234 (unsigned long long)hdr->hdr_count);
237 * increment number of buffer overflows.
238 * important to detect duplicate set of samples.
240 hdr->hdr_overflows++;
243 * request notification and masking of monitoring.
244 * Notification is still subject to the overflowed
245 * register having the FL_NOTIFY flag set.
247 arg->ovfl_ctrl = PFM_OVFL_CTRL_NOTIFY | PFM_OVFL_CTRL_MASK;
249 return -ENOBUFS; /* we are full, sorry */
252 static int pfm_dfl_fmt_restart(struct pfm_context *ctx, u32 *ovfl_ctrl)
254 struct pfm_dfl_smpl_hdr *hdr;
256 hdr = ctx->smpl_addr;
259 hdr->hdr_cur_offs = sizeof(*hdr);
261 pfm_cacheflush(hdr, sizeof(*hdr));
263 *ovfl_ctrl = PFM_OVFL_CTRL_RESET;
268 static int pfm_dfl_fmt_exit(void *buf)
273 static struct pfm_smpl_fmt dfl_fmt = {
274 .fmt_name = "default",
275 .fmt_version = 0x10000,
276 .fmt_arg_size = sizeof(struct pfm_dfl_smpl_arg),
277 .fmt_validate = pfm_dfl_fmt_validate,
278 .fmt_getsize = pfm_dfl_fmt_get_size,
279 .fmt_init = pfm_dfl_fmt_init,
280 .fmt_handler = pfm_dfl_fmt_handler,
281 .fmt_restart = pfm_dfl_fmt_restart,
282 .fmt_exit = pfm_dfl_fmt_exit,
283 .fmt_flags = PFM_FMT_BUILTIN_FLAG,
287 static int pfm_dfl_fmt_init_module(void)
289 return pfm_fmt_register(&dfl_fmt);
292 static void pfm_dfl_fmt_cleanup_module(void)
294 pfm_fmt_unregister(&dfl_fmt);
297 module_init(pfm_dfl_fmt_init_module);
298 module_exit(pfm_dfl_fmt_cleanup_module);