]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/perfmon2-add_ioctl_interface.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / perfmon2-add_ioctl_interface.patch
1 From: Tony Jones <tonyj@suse.de>
2 Subject: switch to ioctl interface for perfmon2
3 Patch-mainline: never
4
5 Patch accepted from SGI (bnc#430298, FATE #303968) added 12 new syscalls.
6 Since these have not been accepted upstream, we don't want to have to
7 support them. Decision was made to switch to a ioctl based interface.
8
9 Signed-off-by: Tony Jones <tonyj@suse.de>
10
11 ---
12 include/linux/syscalls.h | 23 ---
13 perfmon/Makefile | 3
14 perfmon/perfmon_control.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++
15 perfmon/perfmon_init.c | 3
16 perfmon/perfmon_priv.h | 25 +++
17 5 files changed, 340 insertions(+), 24 deletions(-)
18
19 --- a/include/linux/syscalls.h
20 +++ b/include/linux/syscalls.h
21 @@ -697,27 +697,4 @@ asmlinkage long sys_pipe(int __user *);
22
23 int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
24
25 -asmlinkage long sys_pfm_create_context(struct pfarg_ctx __user *ureq,
26 - void __user *uarg, size_t smpl_size);
27 -asmlinkage long sys_pfm_write_pmcs(int fd, struct pfarg_pmc __user *ureq,
28 - int count);
29 -asmlinkage long sys_pfm_write_pmds(int fd, struct pfarg_pmd __user *ureq,
30 - int count);
31 -asmlinkage long sys_pfm_read_pmds(int fd, struct pfarg_pmd __user *ureq,
32 - int count);
33 -asmlinkage long sys_pfm_restart(int fd);
34 -asmlinkage long sys_pfm_stop(int fd);
35 -asmlinkage long sys_pfm_start(int fd, struct pfarg_start __user *ureq);
36 -asmlinkage long sys_pfm_load_context(int fd, struct pfarg_load __user *ureq);
37 -asmlinkage long sys_pfm_unload_context(int fd);
38 -asmlinkage long sys_pfm_delete_evtsets(int fd,
39 - struct pfarg_setinfo __user *ureq,
40 - int count);
41 -asmlinkage long sys_pfm_create_evtsets(int fd,
42 - struct pfarg_setdesc __user *ureq,
43 - int count);
44 -asmlinkage long sys_pfm_getinfo_evtsets(int fd,
45 - struct pfarg_setinfo __user *ureq,
46 - int count);
47 -
48 #endif
49 --- a/perfmon/Makefile
50 +++ b/perfmon/Makefile
51 @@ -7,6 +7,7 @@ obj-y = perfmon_init.o perfmon_rw.o perf
52 perfmon_file.o perfmon_ctxsw.o perfmon_intr.o \
53 perfmon_dfl_smpl.o perfmon_sets.o perfmon_hotplug.o \
54 perfmon_msg.o perfmon_smpl.o perfmon_attach.o \
55 - perfmon_activate.o perfmon_ctx.o perfmon_fmt.o
56 + perfmon_activate.o perfmon_ctx.o perfmon_fmt.o \
57 + perfmon_control.o
58
59 obj-$(CONFIG_PERFMON_DEBUG_FS) += perfmon_debugfs.o
60 --- /dev/null
61 +++ b/perfmon/perfmon_control.c
62 @@ -0,0 +1,310 @@
63 +/*
64 + * perfmon_control.c: perfmon2 ioctl interface
65 + *
66 + * This file implements an ioctl interface alternative replacing the
67 + * following syscalls:
68 + *
69 + * sys_pfm_create_context
70 + * sys_pfm_write_pmcs
71 + * sys_pfm_write_pmds
72 + * sys_pfm_read_pmds
73 + * sys_pfm_load_context
74 + * sys_pfm_start
75 + * sys_pfm_stop
76 + * sys_pfm_restart
77 + * sys_pfm_create_evtsets
78 + * sys_pfm_getinfo_evtsets
79 + * sys_pfm_delete_evtsets
80 + * sys_pfm_unload_context
81 + *
82 + * For SLES11
83 + *
84 + * Tony Jones <tonyj@suse.de>
85 + *
86 + * Copyright (c) 2008 Novell Inc
87 + * Contributed by Tony Jones <tonyj@suse.de>
88 + *
89 + * This program is free software; you can redistribute it and/or
90 + * modify it under the terms of version 2 of the GNU General Public
91 + * License as published by the Free Software Foundation.
92 + *
93 + * This program is distributed in the hope that it will be useful,
94 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
95 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
96 + * General Public License for more details.
97 + *
98 + * You should have received a copy of the GNU General Public License
99 + * along with this program; if not, write to the Free Software
100 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
101 + * 02111-1307 USA
102 + */
103 +
104 +#include <linux/kernel.h>
105 +#include <linux/module.h>
106 +#include <linux/proc_fs.h>
107 +#include <linux/uaccess.h>
108 +#include <linux/miscdevice.h>
109 +#include <linux/perfmon_kern.h>
110 +#include "perfmon_priv.h"
111 +#include <linux/device.h>
112 +#include <linux/compat.h>
113 +
114 +/* elements arranged to ensure current padding for 32/64bit */
115 +struct pfm_control_init {
116 + __u64 req; /* struct pfarg_ctx* */
117 + __u64 fmt_name; /* char* */
118 + __u64 fmt_arg; /* void* */
119 + __u64 fmt_size; /* size_t */
120 +};
121 +
122 +struct pfm_control_arglist {
123 + __s32 fd; /* int */
124 + __s32 count; /* int */
125 + __u64 req; /* void* */
126 +};
127 +
128 +struct pfm_control_argptr {
129 + __u64 req; /* void* */
130 + __s32 fd; /* int */
131 + __s32 _pad;
132 +};
133 +
134 +struct pfm_control_fd {
135 + __s32 fd; /* int */
136 + __s32 _pad;
137 +};
138 +
139 +union pfm_control {
140 + struct pfm_control_init init;
141 + struct pfm_control_arglist arglist;
142 + struct pfm_control_argptr argptr;
143 + struct pfm_control_fd fd;
144 +};
145 +
146 +#ifdef CONFIG_COMPAT
147 +#define _PTR(p) (compat ? compat_ptr(p) : (void*)p)
148 +#else
149 +#define _PTR(p) (unsigned long)(p)
150 +#endif
151 +
152 +static long pfm_control_create_context(union pfm_control *cdata, int compat)
153 +{
154 + struct pfm_control_init *d = &cdata->init;
155 +
156 + return sys_pfm_create_context((struct pfarg_ctx *)_PTR(d->req),
157 + (char *)_PTR(d->fmt_name),
158 + (void *)_PTR(d->fmt_arg),
159 + (size_t)d->fmt_size);
160 +}
161 +
162 +static long pfm_control_write_pmcs(union pfm_control *cdata, int compat)
163 +{
164 + struct pfm_control_arglist *d = &cdata->arglist;
165 +
166 + return sys_pfm_write_pmcs(d->fd,
167 + (struct pfarg_pmc __user *)_PTR(d->req),
168 + d->count);
169 +}
170 +
171 +static long pfm_control_write_pmds(union pfm_control *cdata, int compat)
172 +{
173 + struct pfm_control_arglist *d = &cdata->arglist;
174 +
175 + return sys_pfm_write_pmds(d->fd,
176 + (struct pfarg_pmd __user *)_PTR(d->req),
177 + d->count);
178 +}
179 +
180 +static long pfm_control_read_pmds(union pfm_control *cdata, int compat)
181 +{
182 + struct pfm_control_arglist *d = &cdata->arglist;
183 +
184 + return sys_pfm_read_pmds(d->fd,
185 + (struct pfarg_pmd __user *)_PTR(d->req),
186 + d->count);
187 +}
188 +
189 +static long pfm_control_load_context(union pfm_control *cdata, int compat)
190 +{
191 + struct pfm_control_argptr *d = &cdata->argptr;
192 +
193 + return sys_pfm_load_context(d->fd,
194 + (struct pfarg_load __user *)_PTR(d->req));
195 +}
196 +
197 +static long pfm_control_start(union pfm_control *cdata, int compat)
198 +{
199 + struct pfm_control_argptr *d = &cdata->argptr;
200 +
201 + return sys_pfm_start(d->fd, (struct pfarg_start __user *)_PTR(d->req));
202 +}
203 +
204 +static long pfm_control_stop(union pfm_control *cdata, int compat)
205 +{
206 + struct pfm_control_fd *d = &cdata->fd;
207 +
208 + return sys_pfm_stop(d->fd);
209 +}
210 +
211 +static long pfm_control_restart(union pfm_control *cdata, int compat)
212 +{
213 + struct pfm_control_fd *d = &cdata->fd;
214 +
215 + return sys_pfm_restart(d->fd);
216 +}
217 +
218 +static long pfm_control_create_evtsets(union pfm_control *cdata, int compat)
219 +{
220 + struct pfm_control_arglist *d = &cdata->arglist;
221 +
222 + return sys_pfm_create_evtsets(d->fd,
223 + (struct pfarg_setdesc __user *)_PTR(d->req),
224 + d->count);
225 +}
226 +
227 +static long pfm_control_getinfo_evtsets(union pfm_control *cdata, int compat)
228 +{
229 + struct pfm_control_arglist *d = &cdata->arglist;
230 +
231 + return sys_pfm_getinfo_evtsets(d->fd,
232 + (struct pfarg_setinfo __user *)_PTR(d->req),
233 + d->count);
234 +}
235 +
236 +static long pfm_control_delete_evtsets(union pfm_control *cdata, int compat)
237 +{
238 + struct pfm_control_arglist *d = &cdata->arglist;
239 +
240 + return sys_pfm_delete_evtsets(d->fd,
241 + (struct pfarg_setinfo __user *)_PTR(d->req),
242 + d->count);
243 +}
244 +
245 +static long pfm_control_unload_context(union pfm_control *cdata, int compat)
246 +{
247 + struct pfm_control_fd *d = &cdata->fd;
248 +
249 + return sys_pfm_unload_context(d->fd);
250 +}
251 +
252 +#define PFM_CONTROL_COUNT ARRAY_SIZE(pfm_control_tab)
253 +#define PFM_CMD(func, elem) {func, sizeof(struct elem)}
254 +
255 +struct pfm_control_elem {
256 + long (*func)(union pfm_control *, int compat);
257 + size_t size;
258 +};
259 +
260 +static struct pfm_control_elem pfm_control_tab[] = {
261 + PFM_CMD(pfm_control_create_context, pfm_control_init),
262 + PFM_CMD(pfm_control_write_pmcs, pfm_control_arglist),
263 + PFM_CMD(pfm_control_write_pmds, pfm_control_arglist),
264 + PFM_CMD(pfm_control_read_pmds, pfm_control_arglist),
265 + PFM_CMD(pfm_control_load_context, pfm_control_argptr),
266 + PFM_CMD(pfm_control_start, pfm_control_argptr),
267 + PFM_CMD(pfm_control_stop, pfm_control_fd),
268 + PFM_CMD(pfm_control_restart, pfm_control_fd),
269 + PFM_CMD(pfm_control_create_evtsets, pfm_control_arglist),
270 + PFM_CMD(pfm_control_getinfo_evtsets, pfm_control_arglist),
271 + PFM_CMD(pfm_control_delete_evtsets, pfm_control_arglist),
272 + PFM_CMD(pfm_control_unload_context, pfm_control_fd),
273 +};
274 +
275 +static int __pfm_control_ioctl(struct inode *inode, struct file *file,
276 + unsigned int cmd, unsigned long arg,
277 + int compat)
278 +{
279 + union pfm_control cdata;
280 + int rc, op;
281 +
282 + if (perfmon_disabled)
283 + return -ENOSYS;
284 +
285 + op = _IOC_NR(cmd);
286 +
287 + if (unlikely(op < 0 || op >= PFM_CONTROL_COUNT ||
288 + pfm_control_tab[op].func == NULL)) {
289 + PFM_ERR("Invalid control request %d", op);
290 + return -EINVAL;
291 + }
292 +
293 + if (_IOC_SIZE(cmd) != pfm_control_tab[op].size) {
294 + PFM_ERR("Invalid control request %d, size %d, expected %lu\n",
295 + op, _IOC_SIZE(cmd),
296 + (unsigned long)pfm_control_tab[op].size);
297 + return -EINVAL;
298 + }
299 +
300 + if (_IOC_TYPE(cmd) != 0 || _IOC_DIR(cmd) != _IOC_WRITE)
301 + return -EINVAL;
302 +
303 + if (copy_from_user(&cdata, (void*)arg, pfm_control_tab[op].size) != 0)
304 + return -EFAULT;
305 +
306 + rc = pfm_control_tab[op].func(&cdata, compat);
307 + return rc;
308 +}
309 +
310 +static int pfm_control_ioctl(struct inode *inode, struct file *file,
311 + unsigned int cmd, unsigned long arg)
312 +{
313 + return __pfm_control_ioctl(inode, file, cmd, arg, 0);
314 +}
315 +
316 +#ifdef CONFIG_COMPAT
317 +static long compat_pfm_control_ioctl(struct file *file,
318 + unsigned int cmd, unsigned long arg)
319 +{
320 + return __pfm_control_ioctl(file->f_dentry->d_inode, file, cmd, arg, 1);
321 +}
322 +#endif
323 +
324 +static const struct file_operations pfm_control_operations = {
325 + .owner = THIS_MODULE,
326 + .ioctl = pfm_control_ioctl,
327 +#ifdef CONFIG_COMPAT
328 + .compat_ioctl = compat_pfm_control_ioctl,
329 +#endif
330 +};
331 +
332 +#ifdef USE_MISC_REGISTER
333 +static struct miscdevice pfm_misc_device = {
334 + .minor = MISC_DYNAMIC_MINOR,
335 + .name = "perfmonctl",
336 + .fops = &pfm_control_operations
337 +};
338 +#endif
339 +
340 +int __init pfm_init_control(void)
341 +{
342 + int ret=0;
343 +#ifndef USE_MISC_REGISTER
344 + static struct class *pfm_class;
345 + struct device *dev;
346 + int major;
347 +#endif
348 +
349 +#ifdef USE_MISC_REGISTER
350 + ret = misc_register(&pfm_misc_device);
351 + if (ret) {
352 + PFM_ERR("Failed to create perfmon control file. Error %d\n", ret);
353 + }
354 +#else
355 + major = register_chrdev(0, "perfmon", &pfm_control_operations);
356 + if (major < 0) {
357 + PFM_ERR("Failed to register_chardev %d\n", major);
358 + return major;
359 + }
360 + pfm_class = class_create(THIS_MODULE, "perfmon");
361 + if (IS_ERR(pfm_class)) {
362 + PFM_ERR("Failed to class_create %ld\n", PTR_ERR(pfm_class));
363 + return -ENOENT;
364 + }
365 + dev = device_create(pfm_class, NULL, MKDEV(major,0), NULL, "perfmonctl");
366 + if (IS_ERR(dev)) {
367 + PFM_ERR("Failed to device_create %ld\n", PTR_ERR(dev));
368 + return -ENOENT;
369 + }
370 +#endif
371 + return ret;
372 +}
373 --- a/perfmon/perfmon_init.c
374 +++ b/perfmon/perfmon_init.c
375 @@ -104,6 +104,9 @@ int __init pfm_init(void)
376 if (pfm_init_sysfs())
377 goto error_disable;
378
379 + if (pfm_init_control())
380 + goto error_disable;
381 +
382 /* not critical, so no error checking */
383 pfm_init_debugfs();
384
385 --- a/perfmon/perfmon_priv.h
386 +++ b/perfmon/perfmon_priv.h
387 @@ -158,6 +158,7 @@ static inline void pfm_check_save_prev_c
388
389
390 int pfm_init_fs(void);
391 +int pfm_init_control(void);
392
393 int pfm_init_hotplug(void);
394
395 @@ -177,6 +178,30 @@ static inline void pfm_post_work(struct
396 #define PFM_PMC_STK_ARG PFM_ARCH_PMC_STK_ARG
397 #define PFM_PMD_STK_ARG PFM_ARCH_PMD_STK_ARG
398
399 +/* these used to be in linux/syscalls.h, now accessed via ioctl interface */
400 +asmlinkage long sys_pfm_create_context(struct pfarg_ctx __user *ureq,
401 + char __user *fmt_name,
402 + void __user *fmt_uarg, size_t fmt_size);
403 +asmlinkage long sys_pfm_write_pmcs(int fd, struct pfarg_pmc __user *ureq,
404 + int count);
405 +asmlinkage long sys_pfm_write_pmds(int fd, struct pfarg_pmd __user *ureq,
406 + int count);
407 +asmlinkage long sys_pfm_read_pmds(int fd, struct pfarg_pmd __user *ureq,
408 + int count);
409 +asmlinkage long sys_pfm_restart(int fd);
410 +asmlinkage long sys_pfm_stop(int fd);
411 +asmlinkage long sys_pfm_start(int fd, struct pfarg_start __user *ureq);
412 +asmlinkage long sys_pfm_load_context(int fd, struct pfarg_load __user *ureq);
413 +asmlinkage long sys_pfm_unload_context(int fd);
414 +asmlinkage long sys_pfm_delete_evtsets(int fd,
415 + struct pfarg_setinfo __user *ureq,
416 + int count);
417 +asmlinkage long sys_pfm_create_evtsets(int fd,
418 + struct pfarg_setdesc __user *ureq,
419 + int count);
420 +asmlinkage long sys_pfm_getinfo_evtsets(int fd,
421 + struct pfarg_setinfo __user *ureq,
422 + int count);
423 #endif /* CONFIG_PERFMON */
424
425 #endif /* __PERFMON_PRIV_H__ */