Branch data Line data Source code
1 : : #undef DEBUG
2 : :
3 : : /*
4 : : * ARM performance counter support.
5 : : *
6 : : * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
7 : : * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
8 : : *
9 : : * This code is based on the sparc64 perf event code, which is in turn based
10 : : * on the x86 code. Callchain code is based on the ARM OProfile backtrace
11 : : * code.
12 : : */
13 : : #define pr_fmt(fmt) "hw perfevents: " fmt
14 : :
15 : : #include <linux/cpumask.h>
16 : : #include <linux/kernel.h>
17 : : #include <linux/platform_device.h>
18 : : #include <linux/pm_runtime.h>
19 : : #include <linux/uaccess.h>
20 : :
21 : : #include <asm/irq_regs.h>
22 : : #include <asm/pmu.h>
23 : : #include <asm/stacktrace.h>
24 : :
25 : : static int
26 : : armpmu_map_cache_event(const unsigned (*cache_map)
27 : : [PERF_COUNT_HW_CACHE_MAX]
28 : : [PERF_COUNT_HW_CACHE_OP_MAX]
29 : : [PERF_COUNT_HW_CACHE_RESULT_MAX],
30 : : u64 config)
31 : : {
32 : : unsigned int cache_type, cache_op, cache_result, ret;
33 : :
34 : 0 : cache_type = (config >> 0) & 0xff;
35 [ # # ]: 0 : if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
36 : : return -EINVAL;
37 : :
38 : 0 : cache_op = (config >> 8) & 0xff;
39 [ # # ]: 0 : if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
40 : : return -EINVAL;
41 : :
42 : 0 : cache_result = (config >> 16) & 0xff;
43 [ # # ]: 0 : if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
44 : : return -EINVAL;
45 : :
46 : 0 : ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
47 : :
48 [ # # ]: 0 : if (ret == CACHE_OP_UNSUPPORTED)
49 : : return -ENOENT;
50 : :
51 : 0 : return ret;
52 : : }
53 : :
54 : : static int
55 : : armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
56 : : {
57 : : int mapping;
58 : :
59 [ # # ]: 0 : if (config >= PERF_COUNT_HW_MAX)
60 : : return -EINVAL;
61 : :
62 : 0 : mapping = (*event_map)[config];
63 [ # # ]: 0 : return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
64 : : }
65 : :
66 : : static int
67 : : armpmu_map_raw_event(u32 raw_event_mask, u64 config)
68 : : {
69 : 0 : return (int)(config & raw_event_mask);
70 : : }
71 : :
72 : : int
73 : 0 : armpmu_map_event(struct perf_event *event,
74 : : const unsigned (*event_map)[PERF_COUNT_HW_MAX],
75 : : const unsigned (*cache_map)
76 : : [PERF_COUNT_HW_CACHE_MAX]
77 : : [PERF_COUNT_HW_CACHE_OP_MAX]
78 : : [PERF_COUNT_HW_CACHE_RESULT_MAX],
79 : : u32 raw_event_mask)
80 : : {
81 : 0 : u64 config = event->attr.config;
82 : :
83 [ # # # # ]: 0 : switch (event->attr.type) {
84 : : case PERF_TYPE_HARDWARE:
85 : 0 : return armpmu_map_hw_event(event_map, config);
86 : : case PERF_TYPE_HW_CACHE:
87 : 0 : return armpmu_map_cache_event(cache_map, config);
88 : : case PERF_TYPE_RAW:
89 : 0 : return armpmu_map_raw_event(raw_event_mask, config);
90 : : default:
91 [ # # ]: 0 : if (event->attr.type >= PERF_TYPE_MAX)
92 : 0 : return armpmu_map_raw_event(raw_event_mask, config);
93 : : }
94 : :
95 : : return -ENOENT;
96 : : }
97 : :
98 : 0 : int armpmu_event_set_period(struct perf_event *event)
99 : : {
100 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
101 : : struct hw_perf_event *hwc = &event->hw;
102 : 0 : s64 left = local64_read(&hwc->period_left);
103 : 0 : s64 period = hwc->sample_period;
104 : : int ret = 0;
105 : :
106 [ # # ]: 0 : if (unlikely(left <= -period)) {
107 : : left = period;
108 : : local64_set(&hwc->period_left, left);
109 : 0 : hwc->last_period = period;
110 : : ret = 1;
111 : : }
112 : :
113 [ # # ]: 0 : if (unlikely(left <= 0)) {
114 : 0 : left += period;
115 : : local64_set(&hwc->period_left, left);
116 : 0 : hwc->last_period = period;
117 : : ret = 1;
118 : : }
119 : :
120 [ # # ]: 0 : if (left > (s64)armpmu->max_period)
121 : : left = armpmu->max_period;
122 : :
123 : 0 : local64_set(&hwc->prev_count, (u64)-left);
124 : :
125 : 0 : armpmu->write_counter(event, (u64)(-left) & 0xffffffff);
126 : :
127 : 0 : perf_event_update_userpage(event);
128 : :
129 : 0 : return ret;
130 : : }
131 : :
132 : 0 : u64 armpmu_event_update(struct perf_event *event)
133 : : {
134 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
135 : : struct hw_perf_event *hwc = &event->hw;
136 : : u64 delta, prev_raw_count, new_raw_count;
137 : :
138 : : again:
139 : 0 : prev_raw_count = local64_read(&hwc->prev_count);
140 : 0 : new_raw_count = armpmu->read_counter(event);
141 : :
142 [ # # ]: 0 : if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
143 : 0 : new_raw_count) != prev_raw_count)
144 : : goto again;
145 : :
146 : 0 : delta = (new_raw_count - prev_raw_count) & armpmu->max_period;
147 : :
148 : 0 : local64_add(delta, &event->count);
149 : 0 : local64_sub(delta, &hwc->period_left);
150 : :
151 : 0 : return new_raw_count;
152 : : }
153 : :
154 : : static void
155 : 0 : armpmu_read(struct perf_event *event)
156 : : {
157 : 0 : armpmu_event_update(event);
158 : 0 : }
159 : :
160 : : static void
161 : 0 : armpmu_stop(struct perf_event *event, int flags)
162 : : {
163 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
164 : : struct hw_perf_event *hwc = &event->hw;
165 : :
166 [ # # ]: 0 : if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
167 : 0 : return;
168 : : /*
169 : : * ARM pmu always has to update the counter, so ignore
170 : : * PERF_EF_UPDATE, see comments in armpmu_start().
171 : : */
172 [ # # ]: 0 : if (!(hwc->state & PERF_HES_STOPPED)) {
173 : 0 : armpmu->disable(event);
174 : 0 : armpmu_event_update(event);
175 : 0 : hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
176 : : }
177 : : }
178 : :
179 : 0 : static void armpmu_start(struct perf_event *event, int flags)
180 : : {
181 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
182 : : struct hw_perf_event *hwc = &event->hw;
183 : :
184 [ # # ]: 0 : if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
185 : 0 : return;
186 : : /*
187 : : * ARM pmu always has to reprogram the period, so ignore
188 : : * PERF_EF_RELOAD, see the comment below.
189 : : */
190 [ # # ]: 0 : if (flags & PERF_EF_RELOAD)
191 [ # # ][ # # ]: 0 : WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
[ # # ]
192 : :
193 : 0 : hwc->state = 0;
194 : : /*
195 : : * Set the period again. Some counters can't be stopped, so when we
196 : : * were stopped we simply disabled the IRQ source and the counter
197 : : * may have been left counting. If we don't do this step then we may
198 : : * get an interrupt too soon or *way* too late if the overflow has
199 : : * happened since disabling.
200 : : */
201 : 0 : armpmu_event_set_period(event);
202 : 0 : armpmu->enable(event);
203 : : }
204 : :
205 : : static void
206 : 0 : armpmu_del(struct perf_event *event, int flags)
207 : : {
208 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
209 : 0 : struct pmu_hw_events *hw_events = armpmu->get_hw_events();
210 : : struct hw_perf_event *hwc = &event->hw;
211 : 0 : int idx = hwc->idx;
212 : :
213 [ # # ]: 0 : if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
214 : 0 : return;
215 : :
216 : 0 : armpmu_stop(event, PERF_EF_UPDATE);
217 : 0 : hw_events->events[idx] = NULL;
218 : 0 : clear_bit(idx, hw_events->used_mask);
219 : :
220 : 0 : perf_event_update_userpage(event);
221 : : }
222 : :
223 : : static int
224 : 0 : armpmu_add(struct perf_event *event, int flags)
225 : : {
226 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
227 : 0 : struct pmu_hw_events *hw_events = armpmu->get_hw_events();
228 : : struct hw_perf_event *hwc = &event->hw;
229 : : int idx;
230 : : int err = 0;
231 : :
232 : : /* An event following a process won't be stopped earlier */
233 [ # # ]: 0 : if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus))
234 : : return 0;
235 : :
236 : 0 : perf_pmu_disable(event->pmu);
237 : :
238 : : /* If we don't have a space for the counter then finish early. */
239 : 0 : idx = armpmu->get_event_idx(hw_events, event);
240 [ # # ]: 0 : if (idx < 0) {
241 : : err = idx;
242 : : goto out;
243 : : }
244 : :
245 : : /*
246 : : * If there is an event in the counter we are going to use then make
247 : : * sure it is disabled.
248 : : */
249 : 0 : event->hw.idx = idx;
250 : 0 : armpmu->disable(event);
251 : 0 : hw_events->events[idx] = event;
252 : :
253 : 0 : hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
254 [ # # ]: 0 : if (flags & PERF_EF_START)
255 : 0 : armpmu_start(event, PERF_EF_RELOAD);
256 : :
257 : : /* Propagate our changes to the userspace mapping. */
258 : 0 : perf_event_update_userpage(event);
259 : :
260 : : out:
261 : 0 : perf_pmu_enable(event->pmu);
262 : 0 : return err;
263 : : }
264 : :
265 : : static int
266 : 0 : validate_event(struct pmu_hw_events *hw_events,
267 : : struct perf_event *event)
268 : : {
269 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
270 : :
271 [ # # ]: 0 : if (is_software_event(event))
272 : : return 1;
273 : :
274 [ # # ]: 0 : if (event->state < PERF_EVENT_STATE_OFF)
275 : : return 1;
276 : :
277 [ # # ][ # # ]: 0 : if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
278 : : return 1;
279 : :
280 : 0 : return armpmu->get_event_idx(hw_events, event) >= 0;
281 : : }
282 : :
283 : : static int
284 : 0 : validate_group(struct perf_event *event)
285 : : {
286 : 0 : struct perf_event *sibling, *leader = event->group_leader;
287 : : struct pmu_hw_events fake_pmu;
288 : : DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
289 : :
290 : : /*
291 : : * Initialise the fake PMU. We only need to populate the
292 : : * used_mask for the purposes of validation.
293 : : */
294 : 0 : memset(fake_used_mask, 0, sizeof(fake_used_mask));
295 : 0 : fake_pmu.used_mask = fake_used_mask;
296 : :
297 [ # # ]: 0 : if (!validate_event(&fake_pmu, leader))
298 : : return -EINVAL;
299 : :
300 [ # # ]: 0 : list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
301 [ # # ]: 0 : if (!validate_event(&fake_pmu, sibling))
302 : : return -EINVAL;
303 : : }
304 : :
305 [ # # ]: 0 : if (!validate_event(&fake_pmu, event))
306 : : return -EINVAL;
307 : :
308 : 0 : return 0;
309 : : }
310 : :
311 : 0 : static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
312 : : {
313 : : struct arm_pmu *armpmu = (struct arm_pmu *) dev;
314 : 0 : struct platform_device *plat_device = armpmu->plat_device;
315 : 0 : struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
316 : :
317 [ # # ][ # # ]: 0 : if (plat && plat->handle_irq)
318 : 0 : return plat->handle_irq(irq, dev, armpmu->handle_irq);
319 : : else
320 : 0 : return armpmu->handle_irq(irq, dev);
321 : : }
322 : :
323 : : static void
324 : : armpmu_release_hardware(struct arm_pmu *armpmu)
325 : : {
326 : 0 : armpmu->free_irq(armpmu);
327 : : pm_runtime_put_sync(&armpmu->plat_device->dev);
328 : : }
329 : :
330 : : static int
331 : 0 : armpmu_reserve_hardware(struct arm_pmu *armpmu)
332 : : {
333 : : int err;
334 : 0 : struct platform_device *pmu_device = armpmu->plat_device;
335 : :
336 [ # # ]: 0 : if (!pmu_device)
337 : : return -ENODEV;
338 : :
339 : : pm_runtime_get_sync(&pmu_device->dev);
340 : 0 : err = armpmu->request_irq(armpmu, armpmu_dispatch_irq);
341 [ # # ]: 0 : if (err) {
342 : : armpmu_release_hardware(armpmu);
343 : 0 : return err;
344 : : }
345 : :
346 : : return 0;
347 : : }
348 : :
349 : : static void
350 : 0 : hw_perf_event_destroy(struct perf_event *event)
351 : : {
352 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
353 : 0 : atomic_t *active_events = &armpmu->active_events;
354 : 0 : struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
355 : :
356 [ # # ]: 0 : if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
357 : : armpmu_release_hardware(armpmu);
358 : 0 : mutex_unlock(pmu_reserve_mutex);
359 : : }
360 : 0 : }
361 : :
362 : : static int
363 : : event_requires_mode_exclusion(struct perf_event_attr *attr)
364 : : {
365 : : return attr->exclude_idle || attr->exclude_user ||
366 : 0 : attr->exclude_kernel || attr->exclude_hv;
367 : : }
368 : :
369 : : static int
370 : 0 : __hw_perf_event_init(struct perf_event *event)
371 : : {
372 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
373 : 0 : struct hw_perf_event *hwc = &event->hw;
374 : : int mapping;
375 : :
376 : 0 : mapping = armpmu->map_event(event);
377 : :
378 [ # # ]: 0 : if (mapping < 0) {
379 : : pr_debug("event %x:%llx not supported\n", event->attr.type,
380 : : event->attr.config);
381 : : return mapping;
382 : : }
383 : :
384 : : /*
385 : : * We don't assign an index until we actually place the event onto
386 : : * hardware. Use -1 to signify that we haven't decided where to put it
387 : : * yet. For SMP systems, each core has it's own PMU so we can't do any
388 : : * clever allocation or constraints checking at this point.
389 : : */
390 : 0 : hwc->idx = -1;
391 : 0 : hwc->config_base = 0;
392 : 0 : hwc->config = 0;
393 : 0 : hwc->event_base = 0;
394 : :
395 : : /*
396 : : * Check whether we need to exclude the counter from certain modes.
397 : : */
398 [ # # # # ]: 0 : if ((!armpmu->set_event_filter ||
399 [ # # ]: 0 : armpmu->set_event_filter(hwc, &event->attr)) &&
400 : : event_requires_mode_exclusion(&event->attr)) {
401 : : pr_debug("ARM performance counters do not support "
402 : : "mode exclusion\n");
403 : : return -EOPNOTSUPP;
404 : : }
405 : :
406 : : /*
407 : : * Store the event encoding into the config_base field.
408 : : */
409 : 0 : hwc->config_base |= (unsigned long)mapping;
410 : :
411 [ # # ]: 0 : if (!hwc->sample_period) {
412 : : /*
413 : : * For non-sampling runs, limit the sample_period to half
414 : : * of the counter width. That way, the new counter value
415 : : * is far less likely to overtake the previous one unless
416 : : * you have some serious IRQ latency issues.
417 : : */
418 : 0 : hwc->sample_period = armpmu->max_period >> 1;
419 : 0 : hwc->last_period = hwc->sample_period;
420 : 0 : local64_set(&hwc->period_left, hwc->sample_period);
421 : : }
422 : :
423 [ # # ]: 0 : if (event->group_leader != event) {
424 [ # # ]: 0 : if (validate_group(event) != 0)
425 : : return -EINVAL;
426 : : }
427 : :
428 : : return 0;
429 : : }
430 : :
431 : 0 : static int armpmu_event_init(struct perf_event *event)
432 : : {
433 : 0 : struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
434 : : int err = 0;
435 : 0 : atomic_t *active_events = &armpmu->active_events;
436 : :
437 [ # # ][ # # ]: 0 : if (event->cpu != -1 &&
438 : 0 : !cpumask_test_cpu(event->cpu, &armpmu->valid_cpus))
439 : : return -ENOENT;
440 : :
441 : : /* does not support taken branch sampling */
442 [ # # ]: 0 : if (has_branch_stack(event))
443 : : return -EOPNOTSUPP;
444 : :
445 [ # # ]: 0 : if (armpmu->map_event(event) == -ENOENT)
446 : : return -ENOENT;
447 : :
448 : 0 : event->destroy = hw_perf_event_destroy;
449 : :
450 [ # # ]: 0 : if (!atomic_inc_not_zero(active_events)) {
451 : 0 : mutex_lock(&armpmu->reserve_mutex);
452 [ # # ]: 0 : if (atomic_read(active_events) == 0)
453 : 0 : err = armpmu_reserve_hardware(armpmu);
454 : :
455 [ # # ]: 0 : if (!err)
456 : : atomic_inc(active_events);
457 : 0 : mutex_unlock(&armpmu->reserve_mutex);
458 : : }
459 : :
460 [ # # ]: 0 : if (err)
461 : : return err;
462 : :
463 : 0 : err = __hw_perf_event_init(event);
464 [ # # ]: 0 : if (err)
465 : 0 : hw_perf_event_destroy(event);
466 : :
467 : 0 : return err;
468 : : }
469 : :
470 : 0 : static void armpmu_enable(struct pmu *pmu)
471 : : {
472 : : struct arm_pmu *armpmu = to_arm_pmu(pmu);
473 : 0 : struct pmu_hw_events *hw_events = armpmu->get_hw_events();
474 : 0 : int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
475 : :
476 [ # # ]: 0 : if (enabled)
477 : 0 : armpmu->start(armpmu);
478 : 0 : }
479 : :
480 : 0 : static void armpmu_disable(struct pmu *pmu)
481 : : {
482 : : struct arm_pmu *armpmu = to_arm_pmu(pmu);
483 : 0 : armpmu->stop(armpmu);
484 : 0 : }
485 : :
486 : : #ifdef CONFIG_PM_RUNTIME
487 : : static int armpmu_runtime_resume(struct device *dev)
488 : : {
489 : : struct arm_pmu_platdata *plat = dev_get_platdata(dev);
490 : :
491 : : if (plat && plat->runtime_resume)
492 : : return plat->runtime_resume(dev);
493 : :
494 : : return 0;
495 : : }
496 : :
497 : : static int armpmu_runtime_suspend(struct device *dev)
498 : : {
499 : : struct arm_pmu_platdata *plat = dev_get_platdata(dev);
500 : :
501 : : if (plat && plat->runtime_suspend)
502 : : return plat->runtime_suspend(dev);
503 : :
504 : : return 0;
505 : : }
506 : : #endif
507 : :
508 : : const struct dev_pm_ops armpmu_dev_pm_ops = {
509 : : SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
510 : : };
511 : :
512 : 0 : static void armpmu_init(struct arm_pmu *armpmu)
513 : : {
514 : 0 : atomic_set(&armpmu->active_events, 0);
515 : 0 : mutex_init(&armpmu->reserve_mutex);
516 : :
517 : 0 : armpmu->pmu = (struct pmu) {
518 : : .pmu_enable = armpmu_enable,
519 : : .pmu_disable = armpmu_disable,
520 : : .event_init = armpmu_event_init,
521 : : .add = armpmu_add,
522 : : .del = armpmu_del,
523 : : .start = armpmu_start,
524 : : .stop = armpmu_stop,
525 : : .read = armpmu_read,
526 : : };
527 : 0 : }
528 : :
529 : 0 : int armpmu_register(struct arm_pmu *armpmu, int type)
530 : : {
531 : 0 : armpmu_init(armpmu);
532 : : pm_runtime_enable(&armpmu->plat_device->dev);
533 : 0 : pr_info("enabled with %s PMU driver, %d counters available\n",
534 : : armpmu->name, armpmu->num_events);
535 : 0 : return perf_pmu_register(&armpmu->pmu, armpmu->name, type);
536 : : }
537 : :
538 : : /*
539 : : * Callchain handling code.
540 : : */
541 : :
542 : : /*
543 : : * The registers we're interested in are at the end of the variable
544 : : * length saved register structure. The fp points at the end of this
545 : : * structure so the address of this struct is:
546 : : * (struct frame_tail *)(xxx->fp)-1
547 : : *
548 : : * This code has been adapted from the ARM OProfile support.
549 : : */
550 : : struct frame_tail {
551 : : struct frame_tail __user *fp;
552 : : unsigned long sp;
553 : : unsigned long lr;
554 : : } __attribute__((packed));
555 : :
556 : : /*
557 : : * Get the return address for a single stackframe and return a pointer to the
558 : : * next frame tail.
559 : : */
560 : : static struct frame_tail __user *
561 : 0 : user_backtrace(struct frame_tail __user *tail,
562 : : struct perf_callchain_entry *entry)
563 : : {
564 : : struct frame_tail buftail;
565 : :
566 : : /* Also check accessibility of one struct frame_tail beyond */
567 [ # # ]: 0 : if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
568 : : return NULL;
569 [ # # ]: 0 : if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
570 : : return NULL;
571 : :
572 : 0 : perf_callchain_store(entry, buftail.lr);
573 : :
574 : : /*
575 : : * Frame pointers should strictly progress back up the stack
576 : : * (towards higher addresses).
577 : : */
578 [ # # ]: 0 : if (tail + 1 >= buftail.fp)
579 : : return NULL;
580 : :
581 : 0 : return buftail.fp - 1;
582 : : }
583 : :
584 : : void
585 : 0 : perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
586 : : {
587 : : struct frame_tail __user *tail;
588 : :
589 [ # # ][ # # ]: 0 : if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
590 : : /* We don't support guest os callchain now */
591 : 0 : return;
592 : : }
593 : :
594 : 0 : perf_callchain_store(entry, regs->ARM_pc);
595 : 0 : tail = (struct frame_tail __user *)regs->ARM_fp - 1;
596 : :
597 [ # # ][ # # ]: 0 : while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
598 [ # # ]: 0 : tail && !((unsigned long)tail & 0x3))
599 : 0 : tail = user_backtrace(tail, entry);
600 : : }
601 : :
602 : : /*
603 : : * Gets called by walk_stackframe() for every stackframe. This will be called
604 : : * whist unwinding the stackframe and is like a subroutine return so we use
605 : : * the PC.
606 : : */
607 : : static int
608 : 0 : callchain_trace(struct stackframe *fr,
609 : : void *data)
610 : : {
611 : : struct perf_callchain_entry *entry = data;
612 : 0 : perf_callchain_store(entry, fr->pc);
613 : 0 : return 0;
614 : : }
615 : :
616 : : void
617 : 0 : perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
618 : : {
619 : : struct stackframe fr;
620 : :
621 [ # # ][ # # ]: 0 : if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
622 : : /* We don't support guest os callchain now */
623 : 0 : return;
624 : : }
625 : :
626 : 0 : fr.fp = regs->ARM_fp;
627 : 0 : fr.sp = regs->ARM_sp;
628 : 0 : fr.lr = regs->ARM_lr;
629 : 0 : fr.pc = regs->ARM_pc;
630 : 0 : walk_stackframe(&fr, callchain_trace, entry);
631 : : }
632 : :
633 : 0 : unsigned long perf_instruction_pointer(struct pt_regs *regs)
634 : : {
635 [ # # ][ # # ]: 0 : if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
636 : 0 : return perf_guest_cbs->get_guest_ip();
637 : :
638 : 0 : return instruction_pointer(regs);
639 : : }
640 : :
641 : 0 : unsigned long perf_misc_flags(struct pt_regs *regs)
642 : : {
643 : : int misc = 0;
644 : :
645 [ # # ][ # # ]: 0 : if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
646 [ # # ]: 0 : if (perf_guest_cbs->is_user_mode())
647 : : misc |= PERF_RECORD_MISC_GUEST_USER;
648 : : else
649 : : misc |= PERF_RECORD_MISC_GUEST_KERNEL;
650 : : } else {
651 [ # # ]: 0 : if (user_mode(regs))
652 : : misc |= PERF_RECORD_MISC_USER;
653 : : else
654 : : misc |= PERF_RECORD_MISC_KERNEL;
655 : : }
656 : :
657 : 0 : return misc;
658 : : }
|