ptrace.c revision 6a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/arch/arm/kernel/ptrace.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * By Ross Biro 1/23/92 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * edited by Linus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ARM modifications Copyright (C) 2000 Russell King 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 15ce8b9d25c94980cc05e59730c97b2ef0285587b4Paul Gortmaker#include <linux/elf.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/user.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/security.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 217ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 2233fa9b13285e76fb95d940120964562e4c7081c2Russell King#include <linux/uaccess.h> 23864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#include <linux/perf_event.h> 24864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#include <linux/hw_breakpoint.h> 255be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#include <linux/regset.h> 265180bb392a8aab5233e6db858ac1d8371533e20fEric Paris#include <linux/audit.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/traps.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define REG_PC 15 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define REG_PSR 16 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does not yet catch signals sent when the child dies. 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in exit.c or in signal.c. 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Breakpoint SWI instruction: SWI &9F0001 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_ARM 0xef9f0001 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_THUMB 0xdf00 /* fill this in later */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * New breakpoints - use an undefined instruction. The ARM architecture 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reference manual guarantees that the following instruction space 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will produce an undefined instruction exception on all CPUs: 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thumb: 1101 1110 xxxx xxxx 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_ARM 0xe7f001f0 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_THUMB 0xde01 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconstruct pt_regs_offset { 58e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon const char *name; 59e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon int offset; 60e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon}; 61e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 62e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon#define REG_OFFSET_NAME(r) \ 63e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)} 64e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon#define REG_OFFSET_END {.name = NULL, .offset = 0} 65e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 66e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconstatic const struct pt_regs_offset regoffset_table[] = { 67e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r0), 68e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r1), 69e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r2), 70e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r3), 71e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r4), 72e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r5), 73e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r6), 74e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r7), 75e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r8), 76e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r9), 77e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r10), 78e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(fp), 79e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(ip), 80e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(sp), 81e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(lr), 82e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(pc), 83e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(cpsr), 84e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(ORIG_r0), 85e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_END, 86e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon}; 87e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 88e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 89e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_offset() - query register offset from its name 90e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @name: the name of a register 91e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 92e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_offset() returns the offset of a register in struct 93e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * pt_regs from its name. If the name is invalid, this returns -EINVAL; 94e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 95e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconint regs_query_register_offset(const char *name) 96e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 97e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon const struct pt_regs_offset *roff; 98e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon for (roff = regoffset_table; roff->name != NULL; roff++) 99e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon if (!strcmp(roff->name, name)) 100e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return roff->offset; 101e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return -EINVAL; 102e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 103e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 104e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 105e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_name() - query register name from its offset 106e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @offset: the offset of a register in struct pt_regs. 107e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 108e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_name() returns the name of a register from its 109e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * offset in struct pt_regs. If the @offset is invalid, this returns NULL; 110e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 111e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconconst char *regs_query_register_name(unsigned int offset) 112e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 113e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon const struct pt_regs_offset *roff; 114e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon for (roff = regoffset_table; roff->name != NULL; roff++) 115e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon if (roff->offset == offset) 116e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return roff->name; 117e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return NULL; 118e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 119e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 120e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 121e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_within_kernel_stack() - check the address in the stack 122e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @regs: pt_regs which contains kernel stack pointer. 123e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @addr: address which is checked. 124e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 125e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 126e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * If @addr is within the kernel stack, it returns true. If not, returns false. 127e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 128e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconbool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 129e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 130e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return ((addr & ~(THREAD_SIZE - 1)) == 131e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); 132e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 133e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 134e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 135e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_get_kernel_stack_nth() - get Nth entry of the stack 136e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @regs: pt_regs which contains kernel stack pointer. 137e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @n: stack entry number. 138e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 139e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 140e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * is specified by @regs. If the @n th entry is NOT in the kernel stack, 141e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * this returns 0. 142e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 143e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconunsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 144e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 145e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 146e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon addr += n; 147e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon if (regs_within_kernel_stack(regs, (unsigned long)addr)) 148e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return *addr; 149e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon else 150e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return 0; 151e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 152e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine will get a word off of the processes privileged stack. 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the offset is how far from the base addr as stored in the THREAD. 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine assumes that all the privileged stacks are in our 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data space. 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline long get_user_reg(struct task_struct *task, int offset) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 161815d5ec86eb8d5f57e5e4aa147bd1fb6338c58acAl Viro return task_pt_regs(task)->uregs[offset]; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine will put a word on the processes privileged stack. 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the offset is how far from the base addr as stored in the THREAD. 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine assumes that all the privileged stacks are in our 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data space. 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsput_user_reg(struct task_struct *task, int offset, long data) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 173815d5ec86eb8d5f57e5e4aa147bd1fb6338c58acAl Viro struct pt_regs newregs, *regs = task_pt_regs(task); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -EINVAL; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newregs = *regs; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newregs.uregs[offset] = data; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (valid_user_regs(&newregs)) { 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->uregs[offset] = data; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by kernel/ptrace.c when detaching.. 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ptrace_disable(struct task_struct *child) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 192425fc47adb5bb69f76285be77a09a3341a30799eWill Deacon /* Nothing to do. */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle hitting a breakpoint. 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ptrace_break(struct task_struct *tsk, struct pt_regs *regs) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGTRAP; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = TRAP_BRKPT; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_addr = (void __user *)instruction_pointer(regs); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGTRAP, &info, tsk); 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int break_trap(struct pt_regs *regs, unsigned int instr) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptrace_break(current, regs); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct undef_hook arm_break_hook = { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_mask = 0x0fffffff, 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_val = 0x07f001f0, 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_mask = PSR_T_BIT, 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_val = 0, 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fn = break_trap, 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct undef_hook thumb_break_hook = { 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_mask = 0xffff, 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_val = 0xde01, 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_mask = PSR_T_BIT, 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_val = PSR_T_BIT, 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fn = break_trap, 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 232d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitzstatic struct undef_hook thumb2_break_hook = { 233592201a9f154cdd5db59304d1369e94d8b551803Jon Medhurst .instr_mask = 0xffffffff, 234592201a9f154cdd5db59304d1369e94d8b551803Jon Medhurst .instr_val = 0xf7f0a000, 235d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz .cpsr_mask = PSR_T_BIT, 236d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz .cpsr_val = PSR_T_BIT, 237592201a9f154cdd5db59304d1369e94d8b551803Jon Medhurst .fn = break_trap, 238d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz}; 239d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init ptrace_break_init(void) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_undef_hook(&arm_break_hook); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_undef_hook(&thumb_break_hook); 244d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz register_undef_hook(&thumb2_break_hook); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscore_initcall(ptrace_break_init); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read the word at offset "off" into the "struct user". We 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually access the pt_regs stored on the kernel stack. 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_read_user(struct task_struct *tsk, unsigned long off, 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long __user *ret) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long tmp; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2595a4f5da543b169d555a19e889850780ddceb8f98Will Deacon if (off & 3) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = 0; 26368b7f7153fa58df710924fbb79722717d2d16094Paul Brook if (off == PT_TEXT_ADDR) 26468b7f7153fa58df710924fbb79722717d2d16094Paul Brook tmp = tsk->mm->start_code; 26568b7f7153fa58df710924fbb79722717d2d16094Paul Brook else if (off == PT_DATA_ADDR) 26668b7f7153fa58df710924fbb79722717d2d16094Paul Brook tmp = tsk->mm->start_data; 26768b7f7153fa58df710924fbb79722717d2d16094Paul Brook else if (off == PT_TEXT_END_ADDR) 26868b7f7153fa58df710924fbb79722717d2d16094Paul Brook tmp = tsk->mm->end_code; 26968b7f7153fa58df710924fbb79722717d2d16094Paul Brook else if (off < sizeof(struct pt_regs)) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = get_user_reg(tsk, off >> 2); 2715a4f5da543b169d555a19e889850780ddceb8f98Will Deacon else if (off >= sizeof(struct user)) 2725a4f5da543b169d555a19e889850780ddceb8f98Will Deacon return -EIO; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(tmp, ret); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write the word at offset "off" into "struct user". We 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually access the pt_regs stored on the kernel stack. 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_write_user(struct task_struct *tsk, unsigned long off, 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off & 3 || off >= sizeof(struct user)) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off >= sizeof(struct pt_regs)) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user_reg(tsk, off >> 2, val); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IWMMXT 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the child iWMMXt state. 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 300e7c1b32fd354c34c4dceb1736a485bc5d91f7c43Al Viro struct thread_info *thread = task_thread_info(tsk); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODATA; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iwmmxt_task_disable(thread); /* force it to ram */ 305cdaabbd74b15296acf09215355a7f3b07b92b83eRussell King return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE) 306cdaabbd74b15296acf09215355a7f3b07b92b83eRussell King ? -EFAULT : 0; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the child iWMMXt state. 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 314e7c1b32fd354c34c4dceb1736a485bc5d91f7c43Al Viro struct thread_info *thread = task_thread_info(tsk); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EACCES; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iwmmxt_task_release(thread); /* force a reload */ 31917320a9644a45ccac51ce4ff4333276844abf72dRussell King return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE) 320cdaabbd74b15296acf09215355a7f3b07b92b83eRussell King ? -EFAULT : 0; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3255429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#ifdef CONFIG_CRUNCH 3265429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek/* 3275429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek * Get the child Crunch state. 3285429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek */ 3295429b060df6d556f396b78364ad017686015bc34Lennert Buytenhekstatic int ptrace_getcrunchregs(struct task_struct *tsk, void __user *ufp) 3305429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek{ 3315429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek struct thread_info *thread = task_thread_info(tsk); 3325429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 3335429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek crunch_task_disable(thread); /* force it to ram */ 3345429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek return copy_to_user(ufp, &thread->crunchstate, CRUNCH_SIZE) 3355429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek ? -EFAULT : 0; 3365429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek} 3375429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 3385429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek/* 3395429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek * Set the child Crunch state. 3405429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek */ 3415429b060df6d556f396b78364ad017686015bc34Lennert Buytenhekstatic int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp) 3425429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek{ 3435429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek struct thread_info *thread = task_thread_info(tsk); 3445429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 3455429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek crunch_task_release(thread); /* force a reload */ 3465429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek return copy_from_user(&thread->crunchstate, ufp, CRUNCH_SIZE) 3475429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek ? -EFAULT : 0; 3485429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek} 3495429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#endif 3505429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 351864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#ifdef CONFIG_HAVE_HW_BREAKPOINT 352864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 353864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Convert a virtual register number into an index for a thread_info 354864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * breakpoint array. Breakpoints are identified using positive numbers 355864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * whilst watchpoints are negative. The registers are laid out as pairs 356864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * of (address, control), each pair mapping to a unique hw_breakpoint struct. 357864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Register 0 is reserved for describing resource information. 358864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 359864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic int ptrace_hbp_num_to_idx(long num) 360864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 361864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num < 0) 362864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num = (ARM_MAX_BRP << 1) - num; 363864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return (num - 1) >> 1; 364864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 365864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 366864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 367864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Returns the virtual register number for the address of the 368864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * breakpoint at index idx. 369864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 370864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic long ptrace_hbp_idx_to_num(int idx) 371864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 372864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon long mid = ARM_MAX_BRP << 1; 373864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon long num = (idx << 1) + 1; 374864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return num > mid ? mid - num : num; 375864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 376864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 377864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 378864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Handle hitting a HW-breakpoint. 379864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 380a8b0ca17b80e92faab46ee7179ba9e99ccb61233Peter Zijlstrastatic void ptrace_hbptriggered(struct perf_event *bp, 381864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_sample_data *data, 382864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct pt_regs *regs) 383864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 384864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); 385864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon long num; 386864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int i; 387864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon siginfo_t info; 388864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 389864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i) 390864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (current->thread.debug.hbp[i] == bp) 391864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon break; 392864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 393864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i); 394864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 395864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_signo = SIGTRAP; 396864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_errno = (int)num; 397864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_code = TRAP_HWBKPT; 398864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_addr = (void __user *)(bkpt->trigger); 399864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 400864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon force_sig_info(SIGTRAP, &info, current); 401864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 402864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 403864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 404864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Set ptrace breakpoint pointers to zero for this task. 405864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * This is required in order to prevent child processes from unregistering 406864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * breakpoints held by their parent. 407864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 408864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconvoid clear_ptrace_hw_breakpoint(struct task_struct *tsk) 409864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 410864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp)); 411864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 412864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 413864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 414864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Unregister breakpoints from this task and reset the pointers in 415864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * the thread_struct. 416864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 417864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconvoid flush_ptrace_hw_breakpoint(struct task_struct *tsk) 418864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 419864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int i; 420864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct thread_struct *t = &tsk->thread; 421864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 422864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) { 423864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (t->debug.hbp[i]) { 424864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon unregister_hw_breakpoint(t->debug.hbp[i]); 425864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon t->debug.hbp[i] = NULL; 426864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 427864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 428864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 429864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 430864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic u32 ptrace_get_hbp_resource_info(void) 431864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 432864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u8 num_brps, num_wrps, debug_arch, wp_len; 433864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u32 reg = 0; 434864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 435864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num_brps = hw_breakpoint_slots(TYPE_INST); 436864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num_wrps = hw_breakpoint_slots(TYPE_DATA); 437864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon debug_arch = arch_get_debug_arch(); 438864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon wp_len = arch_get_max_wp_len(); 439864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 440864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= debug_arch; 441864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg <<= 8; 442864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= wp_len; 443864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg <<= 8; 444864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= num_wrps; 445864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg <<= 8; 446864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= num_brps; 447864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 448864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return reg; 449864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 450864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 451864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type) 452864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 453864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event_attr attr; 454864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 455864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ptrace_breakpoint_init(&attr); 456864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 457864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* Initialise fields to sane defaults. */ 458864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_addr = 0; 459864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_len = HW_BREAKPOINT_LEN_4; 460864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_type = type; 461864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.disabled = 1; 462864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 4634dc0da86967d5463708631d02a70cfed5b104884Avi Kivity return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, 4644dc0da86967d5463708631d02a70cfed5b104884Avi Kivity tsk); 465864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 466864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 467864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic int ptrace_gethbpregs(struct task_struct *tsk, long num, 468864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon unsigned long __user *data) 469864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 470864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u32 reg; 471864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int idx, ret = 0; 472864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event *bp; 473864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct arch_hw_breakpoint_ctrl arch_ctrl; 474864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 475864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num == 0) { 476864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg = ptrace_get_hbp_resource_info(); 477864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } else { 478864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon idx = ptrace_hbp_num_to_idx(num); 479864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { 480864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EINVAL; 481864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 482864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 483864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 484864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon bp = tsk->thread.debug.hbp[idx]; 485864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (!bp) { 486864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg = 0; 487864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto put; 488864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 489864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 490864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon arch_ctrl = counter_arch_bp(bp)->ctrl; 491864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 492864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* 493864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Fix up the len because we may have adjusted it 494864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * to compensate for an unaligned address. 495864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 496864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon while (!(arch_ctrl.len & 0x1)) 497864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon arch_ctrl.len >>= 1; 498864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 499ba55d3db9bb59a52fe45dbc5d62776adbb289e54Will Deacon if (num & 0x1) 500864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg = bp->attr.bp_addr; 501ba55d3db9bb59a52fe45dbc5d62776adbb289e54Will Deacon else 502ba55d3db9bb59a52fe45dbc5d62776adbb289e54Will Deacon reg = encode_ctrl_reg(arch_ctrl); 503864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 504864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 505864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconput: 506864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (put_user(reg, data)) 507864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EFAULT; 508864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 509864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconout: 510864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return ret; 511864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 512864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 513864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic int ptrace_sethbpregs(struct task_struct *tsk, long num, 514864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon unsigned long __user *data) 515864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 516864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int idx, gen_len, gen_type, implied_type, ret = 0; 517864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u32 user_val; 518864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event *bp; 519864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct arch_hw_breakpoint_ctrl ctrl; 520864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event_attr attr; 521864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 522864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num == 0) 523864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 524864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon else if (num < 0) 525864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon implied_type = HW_BREAKPOINT_RW; 526864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon else 527864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon implied_type = HW_BREAKPOINT_X; 528864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 529864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon idx = ptrace_hbp_num_to_idx(num); 530864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { 531864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EINVAL; 532864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 533864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 534864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 535864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (get_user(user_val, data)) { 536864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EFAULT; 537864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 538864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 539864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 540864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon bp = tsk->thread.debug.hbp[idx]; 541864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (!bp) { 542864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon bp = ptrace_hbp_create(tsk, implied_type); 543864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (IS_ERR(bp)) { 544864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = PTR_ERR(bp); 545864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 546864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 547864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon tsk->thread.debug.hbp[idx] = bp; 548864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 549864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 550864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr = bp->attr; 551864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 552864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num & 0x1) { 553864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* Address */ 554864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_addr = user_val; 555864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } else { 556864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* Control */ 557864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon decode_ctrl_reg(user_val, &ctrl); 558864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type); 559864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (ret) 560864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 561864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 562864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if ((gen_type & implied_type) != gen_type) { 563ce9b1b09520789223f72a9fefd5f0e329f8d89d0Will Deacon ret = -EINVAL; 564ce9b1b09520789223f72a9fefd5f0e329f8d89d0Will Deacon goto out; 565864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 566864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 567864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_len = gen_len; 568864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_type = gen_type; 569864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.disabled = !ctrl.enabled; 570864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 571864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 572864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = modify_user_hw_breakpoint(bp, &attr); 573864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconout: 574864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return ret; 575864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 576864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#endif 577864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 5785be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin/* regset get/set implementations */ 5795be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 5805be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int gpr_get(struct task_struct *target, 5815be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 5825be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 5835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin void *kbuf, void __user *ubuf) 5845be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 5855be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct pt_regs *regs = task_pt_regs(target); 5865be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 5875be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 5885be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin regs, 5895be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(*regs)); 5905be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 5915be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 5925be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int gpr_set(struct task_struct *target, 5935be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 5945be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 5955be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const void *kbuf, const void __user *ubuf) 5965be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 5975be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin int ret; 5985be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct pt_regs newregs; 5995be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6005be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 6015be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &newregs, 6025be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(newregs)); 6035be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 6045be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 6055be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6065be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (!valid_user_regs(&newregs)) 6075be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return -EINVAL; 6085be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6095be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin *task_pt_regs(target) = newregs; 6105be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return 0; 6115be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6125be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6135be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int fpa_get(struct task_struct *target, 6145be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6155be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6165be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin void *kbuf, void __user *ubuf) 6175be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6185be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 6195be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &task_thread_info(target)->fpstate, 6205be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct user_fp)); 6215be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6225be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6235be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int fpa_set(struct task_struct *target, 6245be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6255be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6265be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const void *kbuf, const void __user *ubuf) 6275be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6285be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct thread_info *thread = task_thread_info(target); 6295be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6305be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin thread->used_cp[1] = thread->used_cp[2] = 1; 6315be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6325be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 6335be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &thread->fpstate, 6345be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct user_fp)); 6355be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6365be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6375be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#ifdef CONFIG_VFP 6385be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin/* 6395be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * VFP register get/set implementations. 6405be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6415be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * With respect to the kernel, struct user_fp is divided into three chunks: 6425be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 16 or 32 real VFP registers (d0-d15 or d0-31) 6435be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * These are transferred to/from the real registers in the task's 6445be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * vfp_hard_struct. The number of registers depends on the kernel 6455be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * configuration. 6465be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6475be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 16 or 0 fake VFP registers (d16-d31 or empty) 6485be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * i.e., the user_vfp structure has space for 32 registers even if 6495be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * the kernel doesn't have them all. 6505be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6515be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * vfp_get() reads this chunk as zero where applicable 6525be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * vfp_set() ignores this chunk 6535be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6545be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 1 word for the FPSCR 6555be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6565be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * The bounds-checking logic built into user_regset_copyout and friends 6575be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * means that we can make a simple sequence of calls to map the relevant data 6585be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * to/from the specified slice of the user regset structure. 6595be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 6605be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int vfp_get(struct task_struct *target, 6615be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6625be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6635be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin void *kbuf, void __user *ubuf) 6645be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6655be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin int ret; 6665be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct thread_info *thread = task_thread_info(target); 6675be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; 6685be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); 6695be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); 6705be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6715be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin vfp_sync_hwstate(thread); 6725be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6735be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 6745be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &vfp->fpregs, 6755be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset, 6765be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(vfp->fpregs)); 6775be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 6785be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 6795be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6805be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 6815be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(vfp->fpregs), 6825be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset); 6835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 6845be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 6855be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6865be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 6875be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &vfp->fpscr, 6885be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset, 6895be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset + sizeof(vfp->fpscr)); 6905be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6915be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6925be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin/* 6935be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * For vfp_set() a read-modify-write is done on the VFP registers, 6945be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * in order to avoid writing back a half-modified set of registers on 6955be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * failure. 6965be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 6975be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int vfp_set(struct task_struct *target, 6985be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6995be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 7005be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const void *kbuf, const void __user *ubuf) 7015be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 7025be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin int ret; 7035be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct thread_info *thread = task_thread_info(target); 704247f4993a5974e6759606c4d380748eecfd273ffDave Martin struct vfp_hard_struct new_vfp; 7055be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); 7065be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); 7075be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 708247f4993a5974e6759606c4d380748eecfd273ffDave Martin vfp_sync_hwstate(thread); 709247f4993a5974e6759606c4d380748eecfd273ffDave Martin new_vfp = thread->vfpstate.hard; 710247f4993a5974e6759606c4d380748eecfd273ffDave Martin 7115be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 7125be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &new_vfp.fpregs, 7135be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset, 7145be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(new_vfp.fpregs)); 7155be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 7165be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 7175be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7185be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 7195be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(new_vfp.fpregs), 7205be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset); 7215be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 7225be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 7235be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7245be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 7255be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &new_vfp.fpscr, 7265be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset, 7275be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset + sizeof(new_vfp.fpscr)); 7285be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 7295be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 7305be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7315be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin vfp_flush_hwstate(thread); 7328130b9d7b9d858aa04ce67805e8951e3cb6e9b2fWill Deacon thread->vfpstate.hard = new_vfp; 7335be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7345be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return 0; 7355be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 7365be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#endif /* CONFIG_VFP */ 7375be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7385be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinenum arm_regset { 7395be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin REGSET_GPR, 7405be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin REGSET_FPR, 7415be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#ifdef CONFIG_VFP 7425be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin REGSET_VFP, 7435be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#endif 7445be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin}; 7455be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7465be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic const struct user_regset arm_regsets[] = { 7475be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin [REGSET_GPR] = { 7485be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .core_note_type = NT_PRSTATUS, 7495be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .n = ELF_NGREG, 7505be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .size = sizeof(u32), 7515be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .align = sizeof(u32), 7525be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .get = gpr_get, 7535be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .set = gpr_set 7545be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin }, 7555be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin [REGSET_FPR] = { 7565be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin /* 7575be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * For the FPA regs in fpstate, the real fields are a mixture 7585be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * of sizes, so pretend that the registers are word-sized: 7595be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 7605be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .core_note_type = NT_PRFPREG, 7615be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .n = sizeof(struct user_fp) / sizeof(u32), 7625be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .size = sizeof(u32), 7635be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .align = sizeof(u32), 7645be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .get = fpa_get, 7655be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .set = fpa_set 7665be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin }, 7675be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#ifdef CONFIG_VFP 7685be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin [REGSET_VFP] = { 7695be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin /* 7705be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * Pretend that the VFP regs are word-sized, since the FPSCR is 7715be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * a single word dangling at the end of struct user_vfp: 7725be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 7735be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .core_note_type = NT_ARM_VFP, 7745be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .n = ARM_VFPREGS_SIZE / sizeof(u32), 7755be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .size = sizeof(u32), 7765be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .align = sizeof(u32), 7775be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .get = vfp_get, 7785be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .set = vfp_set 7795be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin }, 7805be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#endif /* CONFIG_VFP */ 7815be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin}; 7825be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic const struct user_regset_view user_arm_view = { 7845be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, 7855be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets) 7865be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin}; 7875be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7885be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinconst struct user_regset_view *task_user_regset_view(struct task_struct *task) 7895be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 7905be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return &user_arm_view; 7915be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 7925be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7939b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kimlong arch_ptrace(struct task_struct *child, long request, 7949b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim unsigned long addr, unsigned long data) 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 797b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim unsigned long __user *datap = (unsigned long __user *) data; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (request) { 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_PEEKUSR: 801b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_read_user(child, addr, datap); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_POKEUSR: 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ptrace_write_user(child, addr, data); 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETREGS: 8095be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_to_user(child, 8105be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_GPR, 8115be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct pt_regs), 8125be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETREGS: 8165be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_from_user(child, 8175be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_GPR, 8185be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct pt_regs), 8195be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETFPREGS: 8235be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_to_user(child, 8245be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_FPR, 8255be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(union fp_state), 8265be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8285be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETFPREGS: 8305be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_from_user(child, 8315be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_FPR, 8325be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(union fp_state), 8335be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IWMMXT 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETWMMXREGS: 838b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_getwmmxregs(child, datap); 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETWMMXREGS: 842b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_setwmmxregs(child, datap); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GET_THREAD_AREA: 847e7c1b32fd354c34c4dceb1736a485bc5d91f7c43Al Viro ret = put_user(task_thread_info(child)->tp_value, 848b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim datap); 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8513f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre case PTRACE_SET_SYSCALL: 8525ba6d3febd4978f31b2c523d64d381603923a709Russell King task_thread_info(child)->syscall = data; 8533f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre ret = 0; 8543f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre break; 8553f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre 8565429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#ifdef CONFIG_CRUNCH 8575429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek case PTRACE_GETCRUNCHREGS: 858b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_getcrunchregs(child, datap); 8595429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek break; 8605429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 8615429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek case PTRACE_SETCRUNCHREGS: 862b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_setcrunchregs(child, datap); 8635429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek break; 8645429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#endif 8655429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 8663d1228ead618b88e8606015cbabc49019981805dCatalin Marinas#ifdef CONFIG_VFP 8673d1228ead618b88e8606015cbabc49019981805dCatalin Marinas case PTRACE_GETVFPREGS: 8685be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_to_user(child, 8695be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_VFP, 8705be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, ARM_VFPREGS_SIZE, 8715be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8723d1228ead618b88e8606015cbabc49019981805dCatalin Marinas break; 8733d1228ead618b88e8606015cbabc49019981805dCatalin Marinas 8743d1228ead618b88e8606015cbabc49019981805dCatalin Marinas case PTRACE_SETVFPREGS: 8755be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_from_user(child, 8765be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_VFP, 8775be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, ARM_VFPREGS_SIZE, 8785be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8793d1228ead618b88e8606015cbabc49019981805dCatalin Marinas break; 8803d1228ead618b88e8606015cbabc49019981805dCatalin Marinas#endif 8813d1228ead618b88e8606015cbabc49019981805dCatalin Marinas 882864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#ifdef CONFIG_HAVE_HW_BREAKPOINT 883864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon case PTRACE_GETHBPREGS: 884bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker if (ptrace_get_breakpoints(child) < 0) 885bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker return -ESRCH; 886bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker 887864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = ptrace_gethbpregs(child, addr, 888864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon (unsigned long __user *)data); 889bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker ptrace_put_breakpoints(child); 890864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon break; 891864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon case PTRACE_SETHBPREGS: 892bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker if (ptrace_get_breakpoints(child) < 0) 893bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker return -ESRCH; 894bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker 895864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = ptrace_sethbpregs(child, addr, 896864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon (unsigned long __user *)data); 897bf0b8f4b55e591ba417c2dbaff42769e1fc773b0Frederic Weisbecker ptrace_put_breakpoints(child); 898864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon break; 899864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#endif 900864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ptrace_request(child, request, addr, data); 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9095180bb392a8aab5233e6db858ac1d8371533e20fEric Paris#ifdef __ARMEB__ 9105180bb392a8aab5233e6db858ac1d8371533e20fEric Paris#define AUDIT_ARCH_NR AUDIT_ARCH_ARMEB 9115180bb392a8aab5233e6db858ac1d8371533e20fEric Paris#else 9125180bb392a8aab5233e6db858ac1d8371533e20fEric Paris#define AUDIT_ARCH_NR AUDIT_ARCH_ARM 9135180bb392a8aab5233e6db858ac1d8371533e20fEric Paris#endif 9145180bb392a8aab5233e6db858ac1d8371533e20fEric Paris 9153f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitreasmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ip; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9196a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon if (why) 92029ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted audit_syscall_exit(regs); 92129ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted else 9225180bb392a8aab5233e6db858ac1d8371533e20fEric Paris audit_syscall_entry(AUDIT_ARCH_NR, scno, regs->ARM_r0, 92329ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); 92429ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted 92529ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted if (!test_thread_flag(TIF_SYSCALL_TRACE)) 92629ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted return scno; 92729ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted if (!(current->ptrace & PT_PTRACED)) 92829ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted return scno; 92929ef73b7a823b77a7cd0bdd7d7cded3fb6c2587bNathaniel Husted 9305ba6d3febd4978f31b2c523d64d381603923a709Russell King current_thread_info()->syscall = scno; 9313f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre 9326a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon /* 9336a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon * IP is used to denote syscall entry/exit: 9346a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon * IP = 0 -> entry, =1 -> exit 9356a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon */ 9366a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon ip = regs->ARM_ip; 9376a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon regs->ARM_ip = why; 9386a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the 0x80 provides a way for the tracing parent to distinguish 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds between a syscall stop and SIGTRAP delivery */ 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? 0x80 : 0)); 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this isn't the same as continuing with a signal, but it will do 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for normal use. strace only continues with a signal if the 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * stopping signal is not SIGTRAP. -brl 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current->exit_code) { 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds send_sig(current->exit_code, current, 1); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->exit_code = 0; 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->ARM_ip = ip; 9533f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre 9545ba6d3febd4978f31b2c523d64d381603923a709Russell King return current_thread_info()->syscall; 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 956