2 * arch/ubicom32/oprofile/profile.c
3 * Oprofile support for arch Ubicom32
5 * (C) Copyright 2009, Ubicom, Inc.
7 * This file is part of the Ubicom32 Linux Kernel Port.
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option)
15 * The Ubicom32 Linux Kernel Port is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with the Ubicom32 Linux Kernel Port. If not, see
22 * <http://www.gnu.org/licenses/>.
24 * Ubicom32 implementation derived from (with many thanks):
33 * @remark Copyright 2002 OProfile authors
34 * @remark Read the file COPYING
36 * @author Hunyue Yau <hy@hy-research.com>
39 #include <linux/oprofile.h>
40 #include <linux/init.h>
41 #include <linux/errno.h>
42 #include <linux/interrupt.h>
43 #include <linux/module.h>
44 #include <linux/kernel.h>
46 #include <asm/devtree.h>
47 #include <asm/thread.h>
49 /* For identifying userland vs kernel address */
50 #include <asm/stacktrace.h>
53 /* For communications with the backend */
54 static struct profilenode
*profile_node
;
56 /* Bitmask containing all Linux threads - as seen by the ROSR reg */
57 static unsigned long th_all_mask
;
59 /* Lookup table to translate a hardware thread into a CPU identifier
60 * Table is indexed by the ROSR value which is assumed to be
61 * relatively small (0...15).
63 unsigned int cpu_map
[THREAD_ARCHITECTURAL_MAX
];
65 static struct pt_regs regs
;
68 * For each sample returned, checked to see if they are relevant to
69 * us. This is necessary as the ubicom32 architecture has other software
70 * running outside of Linux. Only then, put the sample into the relevant
73 * To minimize overhead, a global mask with all possible threads of in
74 * interest to us is used as a first check. Then a second mask identifying
75 * the thread is used to obtain an identifier for that "CPU".
79 * ubicom32_build_cpu_th_mask()
81 * Build a lookup table for translation between hardware thread
82 * "ROSR" values and Linux CPU ids
84 * *** This gets executed on all CPUs at once! ***
86 static void ubicom32_build_cpu_th_mask(void *mask
)
88 thread_t self
= thread_get_self();
89 unsigned long *th_m
= mask
;
91 BUG_ON(self
<= 0 || self
>= THREAD_ARCHITECTURAL_MAX
);
92 cpu_map
[self
] = smp_processor_id();
100 * Process samples returned from the profiler backend. The backend
101 * may return samples that are irrelevant to us or may even return
102 * multiple samples for the same CPU. Note that the sames may be
103 * for ANY cpu. At this time, this is unique and to support this requires
104 * Oprofile to expose an interface to accept the CPU that the same came
107 static irqreturn_t
profile_interrupt(int irq
, void *arg
)
114 if (!(profile_node
->enabled
) || profile_node
->count
< 0) {
116 "Unexpected interrupt, no samples or not enabled!\n");
120 profile_node
->busy
= 1; /* Keep backend out */
122 for (i
= 0; i
< profile_node
->count
; i
++) {
123 buf_entry
= profile_node
->tail
;
124 profile_node
->tail
++;
125 profile_node
->tail
%= IPPROFILETIO_MAX_SAMPLES
;
127 /* Note - the "thread" ID is only the lower 4 bits */
128 th
= (0x0f & profile_node
->samples
[buf_entry
].thread
);
131 if ((bit_th
& th_all_mask
) == 0)
134 regs
.pc
= profile_node
->samples
[buf_entry
].pc
;
136 is_kernel
= ubicom32_is_kernel(regs
.pc
);
138 oprofile_add_ext_sample_cpu(regs
.pc
, ®s
, 0, is_kernel
,
141 profile_node
->count
= 0;
142 profile_node
->busy
= 0;
150 * Notification from oprofile to start the profiler
152 static int profile_start(void)
157 profile_node
->enabled
= 1;
165 * Notification from oprofile to stop the profiler
167 static void profile_stop(void)
170 profile_node
->enabled
= 0;
174 * oprofile_arch_init()
176 * Attach to Oprofile after qualify the availability of the backend
179 int __init
oprofile_arch_init(struct oprofile_operations
*ops
)
183 profile_node
= (struct profilenode
*)devtree_find_node("profiler");
185 if (profile_node
== NULL
) {
186 printk(KERN_WARNING
"Cannot find profiler node\n");
190 r
= request_irq(profile_node
->dn
.recvirq
, profile_interrupt
,
191 IRQF_DISABLED
, "profiler", NULL
);
195 printk(KERN_WARNING
"Cannot get profiler IRQ\n");
199 ops
->start
= profile_start
;
200 ops
->stop
= profile_stop
;
201 ops
->cpu_type
= "timer";
203 memset(cpu_map
, 0, sizeof(cpu_map
));
205 on_each_cpu(ubicom32_build_cpu_th_mask
, &th_all_mask
, 1);
207 memset(®s
, 0, sizeof(regs
));
213 * oprofile_arch_exit()
215 * External call to take outselves out.
216 * Make sure backend is not running.
218 void oprofile_arch_exit(void)
220 BUG_ON(profile_node
->enabled
);