diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/Makefile | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/context.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/file.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sched.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/spufs.h | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sputrace.c | 272 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/sputrace.h | 39 |
7 files changed, 45 insertions, 278 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 99610a6361f2..b93f877ba504 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile | |||
@@ -4,7 +4,8 @@ spufs-y += inode.o file.o context.o syscalls.o coredump.o | |||
4 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o | 4 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o |
5 | spufs-y += switch.o fault.o lscsa_alloc.o | 5 | spufs-y += switch.o fault.o lscsa_alloc.o |
6 | 6 | ||
7 | obj-$(CONFIG_SPU_TRACE) += sputrace.o | 7 | # magic for the trace events |
8 | CFLAGS_sched.o := -I$(src) | ||
8 | 9 | ||
9 | # Rules to build switch.o with the help of SPU tool chain | 10 | # Rules to build switch.o with the help of SPU tool chain |
10 | SPU_CROSS := spu- | 11 | SPU_CROSS := spu- |
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index db5398c0339f..0c87bcd2452a 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/spu.h> | 28 | #include <asm/spu.h> |
29 | #include <asm/spu_csa.h> | 29 | #include <asm/spu_csa.h> |
30 | #include "spufs.h" | 30 | #include "spufs.h" |
31 | #include "sputrace.h" | ||
31 | 32 | ||
32 | 33 | ||
33 | atomic_t nr_spu_contexts = ATOMIC_INIT(0); | 34 | atomic_t nr_spu_contexts = ATOMIC_INIT(0); |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index d6a519e6e1c1..ab8aef9bb8ea 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
39 | 39 | ||
40 | #include "spufs.h" | 40 | #include "spufs.h" |
41 | #include "sputrace.h" | ||
41 | 42 | ||
42 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) | 43 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) |
43 | 44 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index f085369301b1..bb5b77c66d05 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <asm/spu_csa.h> | 47 | #include <asm/spu_csa.h> |
48 | #include <asm/spu_priv1.h> | 48 | #include <asm/spu_priv1.h> |
49 | #include "spufs.h" | 49 | #include "spufs.h" |
50 | #define CREATE_TRACE_POINTS | ||
51 | #include "sputrace.h" | ||
50 | 52 | ||
51 | struct spu_prio_array { | 53 | struct spu_prio_array { |
52 | DECLARE_BITMAP(bitmap, MAX_PRIO); | 54 | DECLARE_BITMAP(bitmap, MAX_PRIO); |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index ae31573bea4a..c448bac65518 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -373,9 +373,4 @@ extern void spu_free_lscsa(struct spu_state *csa); | |||
373 | extern void spuctx_switch_state(struct spu_context *ctx, | 373 | extern void spuctx_switch_state(struct spu_context *ctx, |
374 | enum spu_utilization_state new_state); | 374 | enum spu_utilization_state new_state); |
375 | 375 | ||
376 | #define spu_context_trace(name, ctx, spu) \ | ||
377 | trace_mark(name, "ctx %p spu %p", ctx, spu); | ||
378 | #define spu_context_nospu_trace(name, ctx) \ | ||
379 | trace_mark(name, "ctx %p", ctx); | ||
380 | |||
381 | #endif | 376 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c deleted file mode 100644 index d0b1f3f4d9c8..000000000000 --- a/arch/powerpc/platforms/cell/spufs/sputrace.c +++ /dev/null | |||
@@ -1,272 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 IBM Deutschland Entwicklung GmbH | ||
3 | * Released under GPL v2. | ||
4 | * | ||
5 | * Partially based on net/ipv4/tcp_probe.c. | ||
6 | * | ||
7 | * Simple tracing facility for spu contexts. | ||
8 | */ | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/marker.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | #include <linux/wait.h> | ||
15 | #include <asm/atomic.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include "spufs.h" | ||
18 | |||
19 | struct spu_probe { | ||
20 | const char *name; | ||
21 | const char *format; | ||
22 | marker_probe_func *probe_func; | ||
23 | }; | ||
24 | |||
25 | struct sputrace { | ||
26 | ktime_t tstamp; | ||
27 | int owner_tid; /* owner */ | ||
28 | int curr_tid; | ||
29 | const char *name; | ||
30 | int number; | ||
31 | }; | ||
32 | |||
33 | static int bufsize __read_mostly = 16384; | ||
34 | MODULE_PARM_DESC(bufsize, "Log buffer size (number of records)"); | ||
35 | module_param(bufsize, int, 0); | ||
36 | |||
37 | |||
38 | static DEFINE_SPINLOCK(sputrace_lock); | ||
39 | static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait); | ||
40 | static ktime_t sputrace_start; | ||
41 | static unsigned long sputrace_head, sputrace_tail; | ||
42 | static struct sputrace *sputrace_log; | ||
43 | static int sputrace_logging; | ||
44 | |||
45 | static int sputrace_used(void) | ||
46 | { | ||
47 | return (sputrace_head - sputrace_tail) % bufsize; | ||
48 | } | ||
49 | |||
50 | static inline int sputrace_avail(void) | ||
51 | { | ||
52 | return bufsize - sputrace_used(); | ||
53 | } | ||
54 | |||
55 | static int sputrace_sprint(char *tbuf, int n) | ||
56 | { | ||
57 | const struct sputrace *t = sputrace_log + sputrace_tail % bufsize; | ||
58 | struct timespec tv = | ||
59 | ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start)); | ||
60 | |||
61 | return snprintf(tbuf, n, | ||
62 | "[%lu.%09lu] %d: %s (ctxthread = %d, spu = %d)\n", | ||
63 | (unsigned long) tv.tv_sec, | ||
64 | (unsigned long) tv.tv_nsec, | ||
65 | t->curr_tid, | ||
66 | t->name, | ||
67 | t->owner_tid, | ||
68 | t->number); | ||
69 | } | ||
70 | |||
71 | static ssize_t sputrace_read(struct file *file, char __user *buf, | ||
72 | size_t len, loff_t *ppos) | ||
73 | { | ||
74 | int error = 0, cnt = 0; | ||
75 | |||
76 | if (!buf || len < 0) | ||
77 | return -EINVAL; | ||
78 | |||
79 | while (cnt < len) { | ||
80 | char tbuf[128]; | ||
81 | int width; | ||
82 | |||
83 | /* If we have data ready to return, don't block waiting | ||
84 | * for more */ | ||
85 | if (cnt > 0 && sputrace_used() == 0) | ||
86 | break; | ||
87 | |||
88 | error = wait_event_interruptible(sputrace_wait, | ||
89 | sputrace_used() > 0); | ||
90 | if (error) | ||
91 | break; | ||
92 | |||
93 | spin_lock(&sputrace_lock); | ||
94 | if (sputrace_head == sputrace_tail) { | ||
95 | spin_unlock(&sputrace_lock); | ||
96 | continue; | ||
97 | } | ||
98 | |||
99 | width = sputrace_sprint(tbuf, sizeof(tbuf)); | ||
100 | if (width < len) | ||
101 | sputrace_tail = (sputrace_tail + 1) % bufsize; | ||
102 | spin_unlock(&sputrace_lock); | ||
103 | |||
104 | if (width >= len) | ||
105 | break; | ||
106 | |||
107 | error = copy_to_user(buf + cnt, tbuf, width); | ||
108 | if (error) | ||
109 | break; | ||
110 | cnt += width; | ||
111 | } | ||
112 | |||
113 | return cnt == 0 ? error : cnt; | ||
114 | } | ||
115 | |||
116 | static int sputrace_open(struct inode *inode, struct file *file) | ||
117 | { | ||
118 | int rc; | ||
119 | |||
120 | spin_lock(&sputrace_lock); | ||
121 | if (sputrace_logging) { | ||
122 | rc = -EBUSY; | ||
123 | goto out; | ||
124 | } | ||
125 | |||
126 | sputrace_logging = 1; | ||
127 | sputrace_head = sputrace_tail = 0; | ||
128 | sputrace_start = ktime_get(); | ||
129 | rc = 0; | ||
130 | |||
131 | out: | ||
132 | spin_unlock(&sputrace_lock); | ||
133 | return rc; | ||
134 | } | ||
135 | |||
136 | static int sputrace_release(struct inode *inode, struct file *file) | ||
137 | { | ||
138 | spin_lock(&sputrace_lock); | ||
139 | sputrace_logging = 0; | ||
140 | spin_unlock(&sputrace_lock); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static const struct file_operations sputrace_fops = { | ||
145 | .owner = THIS_MODULE, | ||
146 | .open = sputrace_open, | ||
147 | .read = sputrace_read, | ||
148 | .release = sputrace_release, | ||
149 | }; | ||
150 | |||
151 | static void sputrace_log_item(const char *name, struct spu_context *ctx, | ||
152 | struct spu *spu) | ||
153 | { | ||
154 | spin_lock(&sputrace_lock); | ||
155 | |||
156 | if (!sputrace_logging) { | ||
157 | spin_unlock(&sputrace_lock); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | if (sputrace_avail() > 1) { | ||
162 | struct sputrace *t = sputrace_log + sputrace_head; | ||
163 | |||
164 | t->tstamp = ktime_get(); | ||
165 | t->owner_tid = ctx->tid; | ||
166 | t->name = name; | ||
167 | t->curr_tid = current->pid; | ||
168 | t->number = spu ? spu->number : -1; | ||
169 | |||
170 | sputrace_head = (sputrace_head + 1) % bufsize; | ||
171 | } else { | ||
172 | printk(KERN_WARNING | ||
173 | "sputrace: lost samples due to full buffer.\n"); | ||
174 | } | ||
175 | spin_unlock(&sputrace_lock); | ||
176 | |||
177 | wake_up(&sputrace_wait); | ||
178 | } | ||
179 | |||
180 | static void spu_context_event(void *probe_private, void *call_data, | ||
181 | const char *format, va_list *args) | ||
182 | { | ||
183 | struct spu_probe *p = probe_private; | ||
184 | struct spu_context *ctx; | ||
185 | struct spu *spu; | ||
186 | |||
187 | ctx = va_arg(*args, struct spu_context *); | ||
188 | spu = va_arg(*args, struct spu *); | ||
189 | |||
190 | sputrace_log_item(p->name, ctx, spu); | ||
191 | } | ||
192 | |||
193 | static void spu_context_nospu_event(void *probe_private, void *call_data, | ||
194 | const char *format, va_list *args) | ||
195 | { | ||
196 | struct spu_probe *p = probe_private; | ||
197 | struct spu_context *ctx; | ||
198 | |||
199 | ctx = va_arg(*args, struct spu_context *); | ||
200 | |||
201 | sputrace_log_item(p->name, ctx, NULL); | ||
202 | } | ||
203 | |||
204 | struct spu_probe spu_probes[] = { | ||
205 | { "spu_bind_context__enter", "ctx %p spu %p", spu_context_event }, | ||
206 | { "spu_unbind_context__enter", "ctx %p spu %p", spu_context_event }, | ||
207 | { "spu_get_idle__enter", "ctx %p", spu_context_nospu_event }, | ||
208 | { "spu_get_idle__found", "ctx %p spu %p", spu_context_event }, | ||
209 | { "spu_get_idle__not_found", "ctx %p", spu_context_nospu_event }, | ||
210 | { "spu_find_victim__enter", "ctx %p", spu_context_nospu_event }, | ||
211 | { "spusched_tick__preempt", "ctx %p spu %p", spu_context_event }, | ||
212 | { "spusched_tick__newslice", "ctx %p", spu_context_nospu_event }, | ||
213 | { "spu_yield__enter", "ctx %p", spu_context_nospu_event }, | ||
214 | { "spu_deactivate__enter", "ctx %p", spu_context_nospu_event }, | ||
215 | { "__spu_deactivate__unload", "ctx %p spu %p", spu_context_event }, | ||
216 | { "spufs_ps_fault__enter", "ctx %p", spu_context_nospu_event }, | ||
217 | { "spufs_ps_fault__sleep", "ctx %p", spu_context_nospu_event }, | ||
218 | { "spufs_ps_fault__wake", "ctx %p spu %p", spu_context_event }, | ||
219 | { "spufs_ps_fault__insert", "ctx %p spu %p", spu_context_event }, | ||
220 | { "spu_acquire_saved__enter", "ctx %p", spu_context_nospu_event }, | ||
221 | { "destroy_spu_context__enter", "ctx %p", spu_context_nospu_event }, | ||
222 | { "spufs_stop_callback__enter", "ctx %p spu %p", spu_context_event }, | ||
223 | }; | ||
224 | |||
225 | static int __init sputrace_init(void) | ||
226 | { | ||
227 | struct proc_dir_entry *entry; | ||
228 | int i, error = -ENOMEM; | ||
229 | |||
230 | sputrace_log = kcalloc(bufsize, sizeof(struct sputrace), GFP_KERNEL); | ||
231 | if (!sputrace_log) | ||
232 | goto out; | ||
233 | |||
234 | entry = proc_create("sputrace", S_IRUSR, NULL, &sputrace_fops); | ||
235 | if (!entry) | ||
236 | goto out_free_log; | ||
237 | |||
238 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) { | ||
239 | struct spu_probe *p = &spu_probes[i]; | ||
240 | |||
241 | error = marker_probe_register(p->name, p->format, | ||
242 | p->probe_func, p); | ||
243 | if (error) | ||
244 | printk(KERN_INFO "Unable to register probe %s\n", | ||
245 | p->name); | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | |||
250 | out_free_log: | ||
251 | kfree(sputrace_log); | ||
252 | out: | ||
253 | return -ENOMEM; | ||
254 | } | ||
255 | |||
256 | static void __exit sputrace_exit(void) | ||
257 | { | ||
258 | int i; | ||
259 | |||
260 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) | ||
261 | marker_probe_unregister(spu_probes[i].name, | ||
262 | spu_probes[i].probe_func, &spu_probes[i]); | ||
263 | |||
264 | remove_proc_entry("sputrace", NULL); | ||
265 | kfree(sputrace_log); | ||
266 | marker_synchronize_unregister(); | ||
267 | } | ||
268 | |||
269 | module_init(sputrace_init); | ||
270 | module_exit(sputrace_exit); | ||
271 | |||
272 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.h b/arch/powerpc/platforms/cell/spufs/sputrace.h new file mode 100644 index 000000000000..db2656aa4103 --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/sputrace.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #if !defined(_TRACE_SPUFS_H) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define _TRACE_SPUFS_H | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | |||
6 | #undef TRACE_SYSTEM | ||
7 | #define TRACE_SYSTEM spufs | ||
8 | |||
9 | TRACE_EVENT(spufs_context, | ||
10 | TP_PROTO(struct spu_context *ctx, struct spu *spu, const char *name), | ||
11 | TP_ARGS(ctx, spu, name), | ||
12 | |||
13 | TP_STRUCT__entry( | ||
14 | __field(const char *, name) | ||
15 | __field(int, owner_tid) | ||
16 | __field(int, number) | ||
17 | ), | ||
18 | |||
19 | TP_fast_assign( | ||
20 | __entry->name = name; | ||
21 | __entry->owner_tid = ctx->tid; | ||
22 | __entry->number = spu ? spu->number : -1; | ||
23 | ), | ||
24 | |||
25 | TP_printk("%s (ctxthread = %d, spu = %d)", | ||
26 | __entry->name, __entry->owner_tid, __entry->number) | ||
27 | ); | ||
28 | |||
29 | #define spu_context_trace(name, ctx, spu) \ | ||
30 | trace_spufs_context(ctx, spu, __stringify(name)) | ||
31 | #define spu_context_nospu_trace(name, ctx) \ | ||
32 | trace_spufs_context(ctx, NULL, __stringify(name)) | ||
33 | |||
34 | #endif /* _TRACE_SPUFS_H */ | ||
35 | |||
36 | #undef TRACE_INCLUDE_PATH | ||
37 | #define TRACE_INCLUDE_PATH . | ||
38 | #define TRACE_INCLUDE_FILE sputrace | ||
39 | #include <trace/define_trace.h> | ||