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