1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun #ifndef _POWERPC_PERF_CALLCHAIN_H
3*4882a593Smuzhiyun #define _POWERPC_PERF_CALLCHAIN_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun int read_user_stack_slow(const void __user *ptr, void *buf, int nb);
6*4882a593Smuzhiyun void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
7*4882a593Smuzhiyun struct pt_regs *regs);
8*4882a593Smuzhiyun void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
9*4882a593Smuzhiyun struct pt_regs *regs);
10*4882a593Smuzhiyun
invalid_user_sp(unsigned long sp)11*4882a593Smuzhiyun static inline bool invalid_user_sp(unsigned long sp)
12*4882a593Smuzhiyun {
13*4882a593Smuzhiyun unsigned long mask = is_32bit_task() ? 3 : 7;
14*4882a593Smuzhiyun unsigned long top = STACK_TOP - (is_32bit_task() ? 16 : 32);
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun return (!sp || (sp & mask) || (sp > top));
17*4882a593Smuzhiyun }
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun * On 32-bit we just access the address and let hash_page create a
21*4882a593Smuzhiyun * HPTE if necessary, so there is no need to fall back to reading
22*4882a593Smuzhiyun * the page tables. Since this is called at interrupt level,
23*4882a593Smuzhiyun * do_page_fault() won't treat a DSI as a page fault.
24*4882a593Smuzhiyun */
__read_user_stack(const void __user * ptr,void * ret,size_t size)25*4882a593Smuzhiyun static inline int __read_user_stack(const void __user *ptr, void *ret,
26*4882a593Smuzhiyun size_t size)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun unsigned long addr = (unsigned long)ptr;
29*4882a593Smuzhiyun int rc;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun if (addr > TASK_SIZE - size || (addr & (size - 1)))
32*4882a593Smuzhiyun return -EFAULT;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun rc = copy_from_user_nofault(ret, ptr, size);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_PPC64) && rc)
37*4882a593Smuzhiyun return read_user_stack_slow(ptr, ret, size);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun return rc;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #endif /* _POWERPC_PERF_CALLCHAIN_H */
43