1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Performance counter callchain support - powerpc architecture code
5 * Copyright © 2009 Paul Mackerras, IBM Corporation.
7 #include <linux/kernel.h>
8 #include <linux/sched.h>
9 #include <linux/perf_event.h>
10 #include <linux/percpu.h>
11 #include <linux/uaccess.h>
13 #include <asm/ptrace.h>
14 #include <asm/sigcontext.h>
15 #include <asm/ucontext.h>
17 #include <asm/pte-walk.h>
19 #include "callchain.h"
22 * On 64-bit we don't want to invoke hash_page on user addresses from
23 * interrupt context, so if the access faults, we read the page tables
24 * to find which page (if any) is mapped and access it directly. Radix
25 * has no need for this so it doesn't use read_user_stack_slow.
27 int read_user_stack_slow(const void __user
*ptr
, void *buf
, int nb
)
30 unsigned long addr
= (unsigned long) ptr
;
35 if (get_user_page_fast_only(addr
, FOLL_WRITE
, &page
)) {
36 kaddr
= page_address(page
);
38 /* align address to page boundary */
39 offset
= addr
& ~PAGE_MASK
;
41 memcpy(buf
, kaddr
+ offset
, nb
);
48 static int read_user_stack_64(const unsigned long __user
*ptr
, unsigned long *ret
)
50 return __read_user_stack(ptr
, ret
, sizeof(*ret
));
54 * 64-bit user processes use the same stack frame for RT and non-RT signals.
56 struct signal_frame_64
{
57 char dummy
[__SIGNAL_FRAMESIZE
];
59 unsigned long unused
[2];
60 unsigned int tramp
[6];
61 struct siginfo
*pinfo
;
67 static int is_sigreturn_64_address(unsigned long nip
, unsigned long fp
)
69 if (nip
== fp
+ offsetof(struct signal_frame_64
, tramp
))
71 if (current
->mm
->context
.vdso
&&
72 nip
== VDSO64_SYMBOL(current
->mm
->context
.vdso
, sigtramp_rt64
))
78 * Do some sanity checking on the signal frame pointed to by sp.
79 * We check the pinfo and puc pointers in the frame.
81 static int sane_signal_64_frame(unsigned long sp
)
83 struct signal_frame_64 __user
*sf
;
84 unsigned long pinfo
, puc
;
86 sf
= (struct signal_frame_64 __user
*) sp
;
87 if (read_user_stack_64((unsigned long __user
*) &sf
->pinfo
, &pinfo
) ||
88 read_user_stack_64((unsigned long __user
*) &sf
->puc
, &puc
))
90 return pinfo
== (unsigned long) &sf
->info
&&
91 puc
== (unsigned long) &sf
->uc
;
94 void perf_callchain_user_64(struct perf_callchain_entry_ctx
*entry
,
97 unsigned long sp
, next_sp
;
98 unsigned long next_ip
;
101 struct signal_frame_64 __user
*sigframe
;
102 unsigned long __user
*fp
, *uregs
;
104 next_ip
= perf_instruction_pointer(regs
);
107 perf_callchain_store(entry
, next_ip
);
109 while (entry
->nr
< entry
->max_stack
) {
110 fp
= (unsigned long __user
*) sp
;
111 if (invalid_user_sp(sp
) || read_user_stack_64(fp
, &next_sp
))
113 if (level
> 0 && read_user_stack_64(&fp
[2], &next_ip
))
117 * Note: the next_sp - sp >= signal frame size check
118 * is true when next_sp < sp, which can happen when
119 * transitioning from an alternate signal stack to the
122 if (next_sp
- sp
>= sizeof(struct signal_frame_64
) &&
123 (is_sigreturn_64_address(next_ip
, sp
) ||
124 (level
<= 1 && is_sigreturn_64_address(lr
, sp
))) &&
125 sane_signal_64_frame(sp
)) {
127 * This looks like an signal frame
129 sigframe
= (struct signal_frame_64 __user
*) sp
;
130 uregs
= sigframe
->uc
.uc_mcontext
.gp_regs
;
131 if (read_user_stack_64(&uregs
[PT_NIP
], &next_ip
) ||
132 read_user_stack_64(&uregs
[PT_LNK
], &lr
) ||
133 read_user_stack_64(&uregs
[PT_R1
], &sp
))
136 perf_callchain_store_context(entry
, PERF_CONTEXT_USER
);
137 perf_callchain_store(entry
, next_ip
);
143 perf_callchain_store(entry
, next_ip
);