1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Cell Broadband Engine OProfile Support
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright IBM Corporation 2006
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Maynard Johnson <maynardj@us.ibm.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /* The purpose of this file is to handle SPU event task switching
11*4882a593Smuzhiyun * and to record SPU context information into the OProfile
12*4882a593Smuzhiyun * event buffer.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * Additionally, the spu_sync_buffer function is provided as a helper
15*4882a593Smuzhiyun * for recoding actual SPU program counter samples to the event buffer.
16*4882a593Smuzhiyun */
17*4882a593Smuzhiyun #include <linux/dcookies.h>
18*4882a593Smuzhiyun #include <linux/kref.h>
19*4882a593Smuzhiyun #include <linux/mm.h>
20*4882a593Smuzhiyun #include <linux/fs.h>
21*4882a593Smuzhiyun #include <linux/file.h>
22*4882a593Smuzhiyun #include <linux/module.h>
23*4882a593Smuzhiyun #include <linux/notifier.h>
24*4882a593Smuzhiyun #include <linux/numa.h>
25*4882a593Smuzhiyun #include <linux/oprofile.h>
26*4882a593Smuzhiyun #include <linux/slab.h>
27*4882a593Smuzhiyun #include <linux/spinlock.h>
28*4882a593Smuzhiyun #include "pr_util.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define RELEASE_ALL 9999
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun static DEFINE_SPINLOCK(buffer_lock);
33*4882a593Smuzhiyun static DEFINE_SPINLOCK(cache_lock);
34*4882a593Smuzhiyun static int num_spu_nodes;
35*4882a593Smuzhiyun static int spu_prof_num_nodes;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun struct spu_buffer spu_buff[MAX_NUMNODES * SPUS_PER_NODE];
38*4882a593Smuzhiyun struct delayed_work spu_work;
39*4882a593Smuzhiyun static unsigned max_spu_buff;
40*4882a593Smuzhiyun
spu_buff_add(unsigned long int value,int spu)41*4882a593Smuzhiyun static void spu_buff_add(unsigned long int value, int spu)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun /* spu buff is a circular buffer. Add entries to the
44*4882a593Smuzhiyun * head. Head is the index to store the next value.
45*4882a593Smuzhiyun * The buffer is full when there is one available entry
46*4882a593Smuzhiyun * in the queue, i.e. head and tail can't be equal.
47*4882a593Smuzhiyun * That way we can tell the difference between the
48*4882a593Smuzhiyun * buffer being full versus empty.
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun * ASSUMPTION: the buffer_lock is held when this function
51*4882a593Smuzhiyun * is called to lock the buffer, head and tail.
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun int full = 1;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (spu_buff[spu].head >= spu_buff[spu].tail) {
56*4882a593Smuzhiyun if ((spu_buff[spu].head - spu_buff[spu].tail)
57*4882a593Smuzhiyun < (max_spu_buff - 1))
58*4882a593Smuzhiyun full = 0;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun } else if (spu_buff[spu].tail > spu_buff[spu].head) {
61*4882a593Smuzhiyun if ((spu_buff[spu].tail - spu_buff[spu].head)
62*4882a593Smuzhiyun > 1)
63*4882a593Smuzhiyun full = 0;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun if (!full) {
67*4882a593Smuzhiyun spu_buff[spu].buff[spu_buff[spu].head] = value;
68*4882a593Smuzhiyun spu_buff[spu].head++;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun if (spu_buff[spu].head >= max_spu_buff)
71*4882a593Smuzhiyun spu_buff[spu].head = 0;
72*4882a593Smuzhiyun } else {
73*4882a593Smuzhiyun /* From the user's perspective make the SPU buffer
74*4882a593Smuzhiyun * size management/overflow look like we are using
75*4882a593Smuzhiyun * per cpu buffers. The user uses the same
76*4882a593Smuzhiyun * per cpu parameter to adjust the SPU buffer size.
77*4882a593Smuzhiyun * Increment the sample_lost_overflow to inform
78*4882a593Smuzhiyun * the user the buffer size needs to be increased.
79*4882a593Smuzhiyun */
80*4882a593Smuzhiyun oprofile_cpu_buffer_inc_smpl_lost();
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /* This function copies the per SPU buffers to the
85*4882a593Smuzhiyun * OProfile kernel buffer.
86*4882a593Smuzhiyun */
sync_spu_buff(void)87*4882a593Smuzhiyun static void sync_spu_buff(void)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun int spu;
90*4882a593Smuzhiyun unsigned long flags;
91*4882a593Smuzhiyun int curr_head;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun for (spu = 0; spu < num_spu_nodes; spu++) {
94*4882a593Smuzhiyun /* In case there was an issue and the buffer didn't
95*4882a593Smuzhiyun * get created skip it.
96*4882a593Smuzhiyun */
97*4882a593Smuzhiyun if (spu_buff[spu].buff == NULL)
98*4882a593Smuzhiyun continue;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /* Hold the lock to make sure the head/tail
101*4882a593Smuzhiyun * doesn't change while spu_buff_add() is
102*4882a593Smuzhiyun * deciding if the buffer is full or not.
103*4882a593Smuzhiyun * Being a little paranoid.
104*4882a593Smuzhiyun */
105*4882a593Smuzhiyun spin_lock_irqsave(&buffer_lock, flags);
106*4882a593Smuzhiyun curr_head = spu_buff[spu].head;
107*4882a593Smuzhiyun spin_unlock_irqrestore(&buffer_lock, flags);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* Transfer the current contents to the kernel buffer.
110*4882a593Smuzhiyun * data can still be added to the head of the buffer.
111*4882a593Smuzhiyun */
112*4882a593Smuzhiyun oprofile_put_buff(spu_buff[spu].buff,
113*4882a593Smuzhiyun spu_buff[spu].tail,
114*4882a593Smuzhiyun curr_head, max_spu_buff);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun spin_lock_irqsave(&buffer_lock, flags);
117*4882a593Smuzhiyun spu_buff[spu].tail = curr_head;
118*4882a593Smuzhiyun spin_unlock_irqrestore(&buffer_lock, flags);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
wq_sync_spu_buff(struct work_struct * work)123*4882a593Smuzhiyun static void wq_sync_spu_buff(struct work_struct *work)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun /* move data from spu buffers to kernel buffer */
126*4882a593Smuzhiyun sync_spu_buff();
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /* only reschedule if profiling is not done */
129*4882a593Smuzhiyun if (spu_prof_running)
130*4882a593Smuzhiyun schedule_delayed_work(&spu_work, DEFAULT_TIMER_EXPIRE);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* Container for caching information about an active SPU task. */
134*4882a593Smuzhiyun struct cached_info {
135*4882a593Smuzhiyun struct vma_to_fileoffset_map *map;
136*4882a593Smuzhiyun struct spu *the_spu; /* needed to access pointer to local_store */
137*4882a593Smuzhiyun struct kref cache_ref;
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun static struct cached_info *spu_info[MAX_NUMNODES * 8];
141*4882a593Smuzhiyun
destroy_cached_info(struct kref * kref)142*4882a593Smuzhiyun static void destroy_cached_info(struct kref *kref)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct cached_info *info;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun info = container_of(kref, struct cached_info, cache_ref);
147*4882a593Smuzhiyun vma_map_free(info->map);
148*4882a593Smuzhiyun kfree(info);
149*4882a593Smuzhiyun module_put(THIS_MODULE);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* Return the cached_info for the passed SPU number.
153*4882a593Smuzhiyun * ATTENTION: Callers are responsible for obtaining the
154*4882a593Smuzhiyun * cache_lock if needed prior to invoking this function.
155*4882a593Smuzhiyun */
get_cached_info(struct spu * the_spu,int spu_num)156*4882a593Smuzhiyun static struct cached_info *get_cached_info(struct spu *the_spu, int spu_num)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun struct kref *ref;
159*4882a593Smuzhiyun struct cached_info *ret_info;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (spu_num >= num_spu_nodes) {
162*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
163*4882a593Smuzhiyun "%s, line %d: Invalid index %d into spu info cache\n",
164*4882a593Smuzhiyun __func__, __LINE__, spu_num);
165*4882a593Smuzhiyun ret_info = NULL;
166*4882a593Smuzhiyun goto out;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun if (!spu_info[spu_num] && the_spu) {
169*4882a593Smuzhiyun ref = spu_get_profile_private_kref(the_spu->ctx);
170*4882a593Smuzhiyun if (ref) {
171*4882a593Smuzhiyun spu_info[spu_num] = container_of(ref, struct cached_info, cache_ref);
172*4882a593Smuzhiyun kref_get(&spu_info[spu_num]->cache_ref);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun ret_info = spu_info[spu_num];
177*4882a593Smuzhiyun out:
178*4882a593Smuzhiyun return ret_info;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* Looks for cached info for the passed spu. If not found, the
183*4882a593Smuzhiyun * cached info is created for the passed spu.
184*4882a593Smuzhiyun * Returns 0 for success; otherwise, -1 for error.
185*4882a593Smuzhiyun */
186*4882a593Smuzhiyun static int
prepare_cached_spu_info(struct spu * spu,unsigned long objectId)187*4882a593Smuzhiyun prepare_cached_spu_info(struct spu *spu, unsigned long objectId)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun unsigned long flags;
190*4882a593Smuzhiyun struct vma_to_fileoffset_map *new_map;
191*4882a593Smuzhiyun int retval = 0;
192*4882a593Smuzhiyun struct cached_info *info;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /* We won't bother getting cache_lock here since
195*4882a593Smuzhiyun * don't do anything with the cached_info that's returned.
196*4882a593Smuzhiyun */
197*4882a593Smuzhiyun info = get_cached_info(spu, spu->number);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (info) {
200*4882a593Smuzhiyun pr_debug("Found cached SPU info.\n");
201*4882a593Smuzhiyun goto out;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* Create cached_info and set spu_info[spu->number] to point to it.
205*4882a593Smuzhiyun * spu->number is a system-wide value, not a per-node value.
206*4882a593Smuzhiyun */
207*4882a593Smuzhiyun info = kzalloc(sizeof(*info), GFP_KERNEL);
208*4882a593Smuzhiyun if (!info) {
209*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
210*4882a593Smuzhiyun "%s, line %d: create vma_map failed\n",
211*4882a593Smuzhiyun __func__, __LINE__);
212*4882a593Smuzhiyun retval = -ENOMEM;
213*4882a593Smuzhiyun goto err_alloc;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun new_map = create_vma_map(spu, objectId);
216*4882a593Smuzhiyun if (!new_map) {
217*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
218*4882a593Smuzhiyun "%s, line %d: create vma_map failed\n",
219*4882a593Smuzhiyun __func__, __LINE__);
220*4882a593Smuzhiyun retval = -ENOMEM;
221*4882a593Smuzhiyun goto err_alloc;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun pr_debug("Created vma_map\n");
225*4882a593Smuzhiyun info->map = new_map;
226*4882a593Smuzhiyun info->the_spu = spu;
227*4882a593Smuzhiyun kref_init(&info->cache_ref);
228*4882a593Smuzhiyun spin_lock_irqsave(&cache_lock, flags);
229*4882a593Smuzhiyun spu_info[spu->number] = info;
230*4882a593Smuzhiyun /* Increment count before passing off ref to SPUFS. */
231*4882a593Smuzhiyun kref_get(&info->cache_ref);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /* We increment the module refcount here since SPUFS is
234*4882a593Smuzhiyun * responsible for the final destruction of the cached_info,
235*4882a593Smuzhiyun * and it must be able to access the destroy_cached_info()
236*4882a593Smuzhiyun * function defined in the OProfile module. We decrement
237*4882a593Smuzhiyun * the module refcount in destroy_cached_info.
238*4882a593Smuzhiyun */
239*4882a593Smuzhiyun try_module_get(THIS_MODULE);
240*4882a593Smuzhiyun spu_set_profile_private_kref(spu->ctx, &info->cache_ref,
241*4882a593Smuzhiyun destroy_cached_info);
242*4882a593Smuzhiyun spin_unlock_irqrestore(&cache_lock, flags);
243*4882a593Smuzhiyun goto out;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun err_alloc:
246*4882a593Smuzhiyun kfree(info);
247*4882a593Smuzhiyun out:
248*4882a593Smuzhiyun return retval;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * NOTE: The caller is responsible for locking the
253*4882a593Smuzhiyun * cache_lock prior to calling this function.
254*4882a593Smuzhiyun */
release_cached_info(int spu_index)255*4882a593Smuzhiyun static int release_cached_info(int spu_index)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun int index, end;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (spu_index == RELEASE_ALL) {
260*4882a593Smuzhiyun end = num_spu_nodes;
261*4882a593Smuzhiyun index = 0;
262*4882a593Smuzhiyun } else {
263*4882a593Smuzhiyun if (spu_index >= num_spu_nodes) {
264*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
265*4882a593Smuzhiyun "%s, line %d: "
266*4882a593Smuzhiyun "Invalid index %d into spu info cache\n",
267*4882a593Smuzhiyun __func__, __LINE__, spu_index);
268*4882a593Smuzhiyun goto out;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun end = spu_index + 1;
271*4882a593Smuzhiyun index = spu_index;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun for (; index < end; index++) {
274*4882a593Smuzhiyun if (spu_info[index]) {
275*4882a593Smuzhiyun kref_put(&spu_info[index]->cache_ref,
276*4882a593Smuzhiyun destroy_cached_info);
277*4882a593Smuzhiyun spu_info[index] = NULL;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun out:
282*4882a593Smuzhiyun return 0;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* The source code for fast_get_dcookie was "borrowed"
286*4882a593Smuzhiyun * from drivers/oprofile/buffer_sync.c.
287*4882a593Smuzhiyun */
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* Optimisation. We can manage without taking the dcookie sem
290*4882a593Smuzhiyun * because we cannot reach this code without at least one
291*4882a593Smuzhiyun * dcookie user still being registered (namely, the reader
292*4882a593Smuzhiyun * of the event buffer).
293*4882a593Smuzhiyun */
fast_get_dcookie(const struct path * path)294*4882a593Smuzhiyun static inline unsigned long fast_get_dcookie(const struct path *path)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun unsigned long cookie;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (path->dentry->d_flags & DCACHE_COOKIE)
299*4882a593Smuzhiyun return (unsigned long)path->dentry;
300*4882a593Smuzhiyun get_dcookie(path, &cookie);
301*4882a593Smuzhiyun return cookie;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /* Look up the dcookie for the task's mm->exe_file,
305*4882a593Smuzhiyun * which corresponds loosely to "application name". Also, determine
306*4882a593Smuzhiyun * the offset for the SPU ELF object. If computed offset is
307*4882a593Smuzhiyun * non-zero, it implies an embedded SPU object; otherwise, it's a
308*4882a593Smuzhiyun * separate SPU binary, in which case we retrieve it's dcookie.
309*4882a593Smuzhiyun * For the embedded case, we must determine if SPU ELF is embedded
310*4882a593Smuzhiyun * in the executable application or another file (i.e., shared lib).
311*4882a593Smuzhiyun * If embedded in a shared lib, we must get the dcookie and return
312*4882a593Smuzhiyun * that to the caller.
313*4882a593Smuzhiyun */
314*4882a593Smuzhiyun static unsigned long
get_exec_dcookie_and_offset(struct spu * spu,unsigned int * offsetp,unsigned long * spu_bin_dcookie,unsigned long spu_ref)315*4882a593Smuzhiyun get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp,
316*4882a593Smuzhiyun unsigned long *spu_bin_dcookie,
317*4882a593Smuzhiyun unsigned long spu_ref)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun unsigned long app_cookie = 0;
320*4882a593Smuzhiyun unsigned int my_offset = 0;
321*4882a593Smuzhiyun struct vm_area_struct *vma;
322*4882a593Smuzhiyun struct file *exe_file;
323*4882a593Smuzhiyun struct mm_struct *mm = spu->mm;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (!mm)
326*4882a593Smuzhiyun goto out;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun exe_file = get_mm_exe_file(mm);
329*4882a593Smuzhiyun if (exe_file) {
330*4882a593Smuzhiyun app_cookie = fast_get_dcookie(&exe_file->f_path);
331*4882a593Smuzhiyun pr_debug("got dcookie for %pD\n", exe_file);
332*4882a593Smuzhiyun fput(exe_file);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun mmap_read_lock(mm);
336*4882a593Smuzhiyun for (vma = mm->mmap; vma; vma = vma->vm_next) {
337*4882a593Smuzhiyun if (vma->vm_start > spu_ref || vma->vm_end <= spu_ref)
338*4882a593Smuzhiyun continue;
339*4882a593Smuzhiyun my_offset = spu_ref - vma->vm_start;
340*4882a593Smuzhiyun if (!vma->vm_file)
341*4882a593Smuzhiyun goto fail_no_image_cookie;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun pr_debug("Found spu ELF at %X(object-id:%lx) for file %pD\n",
344*4882a593Smuzhiyun my_offset, spu_ref, vma->vm_file);
345*4882a593Smuzhiyun *offsetp = my_offset;
346*4882a593Smuzhiyun break;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun *spu_bin_dcookie = fast_get_dcookie(&vma->vm_file->f_path);
350*4882a593Smuzhiyun pr_debug("got dcookie for %pD\n", vma->vm_file);
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun mmap_read_unlock(mm);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun out:
355*4882a593Smuzhiyun return app_cookie;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun fail_no_image_cookie:
358*4882a593Smuzhiyun mmap_read_unlock(mm);
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
361*4882a593Smuzhiyun "%s, line %d: Cannot find dcookie for SPU binary\n",
362*4882a593Smuzhiyun __func__, __LINE__);
363*4882a593Smuzhiyun goto out;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* This function finds or creates cached context information for the
369*4882a593Smuzhiyun * passed SPU and records SPU context information into the OProfile
370*4882a593Smuzhiyun * event buffer.
371*4882a593Smuzhiyun */
process_context_switch(struct spu * spu,unsigned long objectId)372*4882a593Smuzhiyun static int process_context_switch(struct spu *spu, unsigned long objectId)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun unsigned long flags;
375*4882a593Smuzhiyun int retval;
376*4882a593Smuzhiyun unsigned int offset = 0;
377*4882a593Smuzhiyun unsigned long spu_cookie = 0, app_dcookie;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun retval = prepare_cached_spu_info(spu, objectId);
380*4882a593Smuzhiyun if (retval)
381*4882a593Smuzhiyun goto out;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /* Get dcookie first because a mutex_lock is taken in that
384*4882a593Smuzhiyun * code path, so interrupts must not be disabled.
385*4882a593Smuzhiyun */
386*4882a593Smuzhiyun app_dcookie = get_exec_dcookie_and_offset(spu, &offset, &spu_cookie, objectId);
387*4882a593Smuzhiyun if (!app_dcookie || !spu_cookie) {
388*4882a593Smuzhiyun retval = -ENOENT;
389*4882a593Smuzhiyun goto out;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun /* Record context info in event buffer */
393*4882a593Smuzhiyun spin_lock_irqsave(&buffer_lock, flags);
394*4882a593Smuzhiyun spu_buff_add(ESCAPE_CODE, spu->number);
395*4882a593Smuzhiyun spu_buff_add(SPU_CTX_SWITCH_CODE, spu->number);
396*4882a593Smuzhiyun spu_buff_add(spu->number, spu->number);
397*4882a593Smuzhiyun spu_buff_add(spu->pid, spu->number);
398*4882a593Smuzhiyun spu_buff_add(spu->tgid, spu->number);
399*4882a593Smuzhiyun spu_buff_add(app_dcookie, spu->number);
400*4882a593Smuzhiyun spu_buff_add(spu_cookie, spu->number);
401*4882a593Smuzhiyun spu_buff_add(offset, spu->number);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /* Set flag to indicate SPU PC data can now be written out. If
404*4882a593Smuzhiyun * the SPU program counter data is seen before an SPU context
405*4882a593Smuzhiyun * record is seen, the postprocessing will fail.
406*4882a593Smuzhiyun */
407*4882a593Smuzhiyun spu_buff[spu->number].ctx_sw_seen = 1;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun spin_unlock_irqrestore(&buffer_lock, flags);
410*4882a593Smuzhiyun smp_wmb(); /* insure spu event buffer updates are written */
411*4882a593Smuzhiyun /* don't want entries intermingled... */
412*4882a593Smuzhiyun out:
413*4882a593Smuzhiyun return retval;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun /*
417*4882a593Smuzhiyun * This function is invoked on either a bind_context or unbind_context.
418*4882a593Smuzhiyun * If called for an unbind_context, the val arg is 0; otherwise,
419*4882a593Smuzhiyun * it is the object-id value for the spu context.
420*4882a593Smuzhiyun * The data arg is of type 'struct spu *'.
421*4882a593Smuzhiyun */
spu_active_notify(struct notifier_block * self,unsigned long val,void * data)422*4882a593Smuzhiyun static int spu_active_notify(struct notifier_block *self, unsigned long val,
423*4882a593Smuzhiyun void *data)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun int retval;
426*4882a593Smuzhiyun unsigned long flags;
427*4882a593Smuzhiyun struct spu *the_spu = data;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun pr_debug("SPU event notification arrived\n");
430*4882a593Smuzhiyun if (!val) {
431*4882a593Smuzhiyun spin_lock_irqsave(&cache_lock, flags);
432*4882a593Smuzhiyun retval = release_cached_info(the_spu->number);
433*4882a593Smuzhiyun spin_unlock_irqrestore(&cache_lock, flags);
434*4882a593Smuzhiyun } else {
435*4882a593Smuzhiyun retval = process_context_switch(the_spu, val);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun return retval;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun static struct notifier_block spu_active = {
441*4882a593Smuzhiyun .notifier_call = spu_active_notify,
442*4882a593Smuzhiyun };
443*4882a593Smuzhiyun
number_of_online_nodes(void)444*4882a593Smuzhiyun static int number_of_online_nodes(void)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun u32 cpu; u32 tmp;
447*4882a593Smuzhiyun int nodes = 0;
448*4882a593Smuzhiyun for_each_online_cpu(cpu) {
449*4882a593Smuzhiyun tmp = cbe_cpu_to_node(cpu) + 1;
450*4882a593Smuzhiyun if (tmp > nodes)
451*4882a593Smuzhiyun nodes++;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun return nodes;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
oprofile_spu_buff_create(void)456*4882a593Smuzhiyun static int oprofile_spu_buff_create(void)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun int spu;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun max_spu_buff = oprofile_get_cpu_buffer_size();
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun for (spu = 0; spu < num_spu_nodes; spu++) {
463*4882a593Smuzhiyun /* create circular buffers to store the data in.
464*4882a593Smuzhiyun * use locks to manage accessing the buffers
465*4882a593Smuzhiyun */
466*4882a593Smuzhiyun spu_buff[spu].head = 0;
467*4882a593Smuzhiyun spu_buff[spu].tail = 0;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun /*
470*4882a593Smuzhiyun * Create a buffer for each SPU. Can't reliably
471*4882a593Smuzhiyun * create a single buffer for all spus due to not
472*4882a593Smuzhiyun * enough contiguous kernel memory.
473*4882a593Smuzhiyun */
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun spu_buff[spu].buff = kzalloc((max_spu_buff
476*4882a593Smuzhiyun * sizeof(unsigned long)),
477*4882a593Smuzhiyun GFP_KERNEL);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (!spu_buff[spu].buff) {
480*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
481*4882a593Smuzhiyun "%s, line %d: oprofile_spu_buff_create "
482*4882a593Smuzhiyun "failed to allocate spu buffer %d.\n",
483*4882a593Smuzhiyun __func__, __LINE__, spu);
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun /* release the spu buffers that have been allocated */
486*4882a593Smuzhiyun while (spu >= 0) {
487*4882a593Smuzhiyun kfree(spu_buff[spu].buff);
488*4882a593Smuzhiyun spu_buff[spu].buff = 0;
489*4882a593Smuzhiyun spu--;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun return -ENOMEM;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun return 0;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* The main purpose of this function is to synchronize
498*4882a593Smuzhiyun * OProfile with SPUFS by registering to be notified of
499*4882a593Smuzhiyun * SPU task switches.
500*4882a593Smuzhiyun *
501*4882a593Smuzhiyun * NOTE: When profiling SPUs, we must ensure that only
502*4882a593Smuzhiyun * spu_sync_start is invoked and not the generic sync_start
503*4882a593Smuzhiyun * in drivers/oprofile/oprof.c. A return value of
504*4882a593Smuzhiyun * SKIP_GENERIC_SYNC or SYNC_START_ERROR will
505*4882a593Smuzhiyun * accomplish this.
506*4882a593Smuzhiyun */
spu_sync_start(void)507*4882a593Smuzhiyun int spu_sync_start(void)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun int spu;
510*4882a593Smuzhiyun int ret = SKIP_GENERIC_SYNC;
511*4882a593Smuzhiyun int register_ret;
512*4882a593Smuzhiyun unsigned long flags = 0;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun spu_prof_num_nodes = number_of_online_nodes();
515*4882a593Smuzhiyun num_spu_nodes = spu_prof_num_nodes * 8;
516*4882a593Smuzhiyun INIT_DELAYED_WORK(&spu_work, wq_sync_spu_buff);
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun /* create buffer for storing the SPU data to put in
519*4882a593Smuzhiyun * the kernel buffer.
520*4882a593Smuzhiyun */
521*4882a593Smuzhiyun ret = oprofile_spu_buff_create();
522*4882a593Smuzhiyun if (ret)
523*4882a593Smuzhiyun goto out;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun spin_lock_irqsave(&buffer_lock, flags);
526*4882a593Smuzhiyun for (spu = 0; spu < num_spu_nodes; spu++) {
527*4882a593Smuzhiyun spu_buff_add(ESCAPE_CODE, spu);
528*4882a593Smuzhiyun spu_buff_add(SPU_PROFILING_CODE, spu);
529*4882a593Smuzhiyun spu_buff_add(num_spu_nodes, spu);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun spin_unlock_irqrestore(&buffer_lock, flags);
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun for (spu = 0; spu < num_spu_nodes; spu++) {
534*4882a593Smuzhiyun spu_buff[spu].ctx_sw_seen = 0;
535*4882a593Smuzhiyun spu_buff[spu].last_guard_val = 0;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun /* Register for SPU events */
539*4882a593Smuzhiyun register_ret = spu_switch_event_register(&spu_active);
540*4882a593Smuzhiyun if (register_ret) {
541*4882a593Smuzhiyun ret = SYNC_START_ERROR;
542*4882a593Smuzhiyun goto out;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun pr_debug("spu_sync_start -- running.\n");
546*4882a593Smuzhiyun out:
547*4882a593Smuzhiyun return ret;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /* Record SPU program counter samples to the oprofile event buffer. */
spu_sync_buffer(int spu_num,unsigned int * samples,int num_samples)551*4882a593Smuzhiyun void spu_sync_buffer(int spu_num, unsigned int *samples,
552*4882a593Smuzhiyun int num_samples)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun unsigned long long file_offset;
555*4882a593Smuzhiyun unsigned long flags;
556*4882a593Smuzhiyun int i;
557*4882a593Smuzhiyun struct vma_to_fileoffset_map *map;
558*4882a593Smuzhiyun struct spu *the_spu;
559*4882a593Smuzhiyun unsigned long long spu_num_ll = spu_num;
560*4882a593Smuzhiyun unsigned long long spu_num_shifted = spu_num_ll << 32;
561*4882a593Smuzhiyun struct cached_info *c_info;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun /* We need to obtain the cache_lock here because it's
564*4882a593Smuzhiyun * possible that after getting the cached_info, the SPU job
565*4882a593Smuzhiyun * corresponding to this cached_info may end, thus resulting
566*4882a593Smuzhiyun * in the destruction of the cached_info.
567*4882a593Smuzhiyun */
568*4882a593Smuzhiyun spin_lock_irqsave(&cache_lock, flags);
569*4882a593Smuzhiyun c_info = get_cached_info(NULL, spu_num);
570*4882a593Smuzhiyun if (!c_info) {
571*4882a593Smuzhiyun /* This legitimately happens when the SPU task ends before all
572*4882a593Smuzhiyun * samples are recorded.
573*4882a593Smuzhiyun * No big deal -- so we just drop a few samples.
574*4882a593Smuzhiyun */
575*4882a593Smuzhiyun pr_debug("SPU_PROF: No cached SPU context "
576*4882a593Smuzhiyun "for SPU #%d. Dropping samples.\n", spu_num);
577*4882a593Smuzhiyun goto out;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun map = c_info->map;
581*4882a593Smuzhiyun the_spu = c_info->the_spu;
582*4882a593Smuzhiyun spin_lock(&buffer_lock);
583*4882a593Smuzhiyun for (i = 0; i < num_samples; i++) {
584*4882a593Smuzhiyun unsigned int sample = *(samples+i);
585*4882a593Smuzhiyun int grd_val = 0;
586*4882a593Smuzhiyun file_offset = 0;
587*4882a593Smuzhiyun if (sample == 0)
588*4882a593Smuzhiyun continue;
589*4882a593Smuzhiyun file_offset = vma_map_lookup( map, sample, the_spu, &grd_val);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* If overlays are used by this SPU application, the guard
592*4882a593Smuzhiyun * value is non-zero, indicating which overlay section is in
593*4882a593Smuzhiyun * use. We need to discard samples taken during the time
594*4882a593Smuzhiyun * period which an overlay occurs (i.e., guard value changes).
595*4882a593Smuzhiyun */
596*4882a593Smuzhiyun if (grd_val && grd_val != spu_buff[spu_num].last_guard_val) {
597*4882a593Smuzhiyun spu_buff[spu_num].last_guard_val = grd_val;
598*4882a593Smuzhiyun /* Drop the rest of the samples. */
599*4882a593Smuzhiyun break;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* We must ensure that the SPU context switch has been written
603*4882a593Smuzhiyun * out before samples for the SPU. Otherwise, the SPU context
604*4882a593Smuzhiyun * information is not available and the postprocessing of the
605*4882a593Smuzhiyun * SPU PC will fail with no available anonymous map information.
606*4882a593Smuzhiyun */
607*4882a593Smuzhiyun if (spu_buff[spu_num].ctx_sw_seen)
608*4882a593Smuzhiyun spu_buff_add((file_offset | spu_num_shifted),
609*4882a593Smuzhiyun spu_num);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun spin_unlock(&buffer_lock);
612*4882a593Smuzhiyun out:
613*4882a593Smuzhiyun spin_unlock_irqrestore(&cache_lock, flags);
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun
spu_sync_stop(void)617*4882a593Smuzhiyun int spu_sync_stop(void)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun unsigned long flags = 0;
620*4882a593Smuzhiyun int ret;
621*4882a593Smuzhiyun int k;
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun ret = spu_switch_event_unregister(&spu_active);
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun if (ret)
626*4882a593Smuzhiyun printk(KERN_ERR "SPU_PROF: "
627*4882a593Smuzhiyun "%s, line %d: spu_switch_event_unregister " \
628*4882a593Smuzhiyun "returned %d\n",
629*4882a593Smuzhiyun __func__, __LINE__, ret);
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun /* flush any remaining data in the per SPU buffers */
632*4882a593Smuzhiyun sync_spu_buff();
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun spin_lock_irqsave(&cache_lock, flags);
635*4882a593Smuzhiyun ret = release_cached_info(RELEASE_ALL);
636*4882a593Smuzhiyun spin_unlock_irqrestore(&cache_lock, flags);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun /* remove scheduled work queue item rather then waiting
639*4882a593Smuzhiyun * for every queued entry to execute. Then flush pending
640*4882a593Smuzhiyun * system wide buffer to event buffer.
641*4882a593Smuzhiyun */
642*4882a593Smuzhiyun cancel_delayed_work(&spu_work);
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun for (k = 0; k < num_spu_nodes; k++) {
645*4882a593Smuzhiyun spu_buff[k].ctx_sw_seen = 0;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun /*
648*4882a593Smuzhiyun * spu_sys_buff will be null if there was a problem
649*4882a593Smuzhiyun * allocating the buffer. Only delete if it exists.
650*4882a593Smuzhiyun */
651*4882a593Smuzhiyun kfree(spu_buff[k].buff);
652*4882a593Smuzhiyun spu_buff[k].buff = 0;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun pr_debug("spu_sync_stop -- done.\n");
655*4882a593Smuzhiyun return ret;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
658