perf_callchain.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * arm64 callchain support
  4. *
  5. * Copyright (C) 2015 ARM Limited
  6. */
  7. #include <linux/perf_event.h>
  8. #include <linux/stacktrace.h>
  9. #include <linux/uaccess.h>
  10. #include <asm/pointer_auth.h>
  11. static bool callchain_trace(void *data, unsigned long pc)
  12. {
  13. struct perf_callchain_entry_ctx *entry = data;
  14. return perf_callchain_store(entry, pc) == 0;
  15. }
  16. void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
  17. struct pt_regs *regs)
  18. {
  19. if (perf_guest_state()) {
  20. /* We don't support guest os callchain now */
  21. return;
  22. }
  23. arch_stack_walk_user(callchain_trace, entry, regs);
  24. }
  25. void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
  26. struct pt_regs *regs)
  27. {
  28. if (perf_guest_state()) {
  29. /* We don't support guest os callchain now */
  30. return;
  31. }
  32. arch_stack_walk(callchain_trace, entry, current, regs);
  33. }
  34. unsigned long perf_instruction_pointer(struct pt_regs *regs)
  35. {
  36. if (perf_guest_state())
  37. return perf_guest_get_ip();
  38. return instruction_pointer(regs);
  39. }
  40. unsigned long perf_misc_flags(struct pt_regs *regs)
  41. {
  42. unsigned int guest_state = perf_guest_state();
  43. int misc = 0;
  44. if (guest_state) {
  45. if (guest_state & PERF_GUEST_USER)
  46. misc |= PERF_RECORD_MISC_GUEST_USER;
  47. else
  48. misc |= PERF_RECORD_MISC_GUEST_KERNEL;
  49. } else {
  50. if (user_mode(regs))
  51. misc |= PERF_RECORD_MISC_USER;
  52. else
  53. misc |= PERF_RECORD_MISC_KERNEL;
  54. }
  55. return misc;
  56. }