18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci#ifndef _POWERPC_PERF_CALLCHAIN_H
38c2ecf20Sopenharmony_ci#define _POWERPC_PERF_CALLCHAIN_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ciint read_user_stack_slow(const void __user *ptr, void *buf, int nb);
68c2ecf20Sopenharmony_civoid perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
78c2ecf20Sopenharmony_ci			    struct pt_regs *regs);
88c2ecf20Sopenharmony_civoid perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
98c2ecf20Sopenharmony_ci			    struct pt_regs *regs);
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic inline bool invalid_user_sp(unsigned long sp)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	unsigned long mask = is_32bit_task() ? 3 : 7;
148c2ecf20Sopenharmony_ci	unsigned long top = STACK_TOP - (is_32bit_task() ? 16 : 32);
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	return (!sp || (sp & mask) || (sp > top));
178c2ecf20Sopenharmony_ci}
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * On 32-bit we just access the address and let hash_page create a
218c2ecf20Sopenharmony_ci * HPTE if necessary, so there is no need to fall back to reading
228c2ecf20Sopenharmony_ci * the page tables.  Since this is called at interrupt level,
238c2ecf20Sopenharmony_ci * do_page_fault() won't treat a DSI as a page fault.
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_cistatic inline int __read_user_stack(const void __user *ptr, void *ret,
268c2ecf20Sopenharmony_ci				    size_t size)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	unsigned long addr = (unsigned long)ptr;
298c2ecf20Sopenharmony_ci	int rc;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	if (addr > TASK_SIZE - size || (addr & (size - 1)))
328c2ecf20Sopenharmony_ci		return -EFAULT;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	rc = copy_from_user_nofault(ret, ptr, size);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC64) && rc)
378c2ecf20Sopenharmony_ci		return read_user_stack_slow(ptr, ret, size);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	return rc;
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#endif /* _POWERPC_PERF_CALLCHAIN_H */
43