]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.suse/perfmon2-add_ioctl_interface.patch
Move xen patchset to new version's subdir.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / perfmon2-add_ioctl_interface.patch
CommitLineData
00e5a55c
BS
1From: Tony Jones <tonyj@suse.de>
2Subject: switch to ioctl interface for perfmon2
3Patch-mainline: never
4
5Patch accepted from SGI (bnc#430298, FATE #303968) added 12 new syscalls.
6Since these have not been accepted upstream, we don't want to have to
7support them. Decision was made to switch to a ioctl based interface.
8
9Signed-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__ */