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> 270693bf68148c4473158e435383e75af70b704f78Wade Farnsworth#include <linux/tracehook.h> 28ad82cc08f70486b5741560b1b2121dadf82897deWill Deacon#include <linux/unistd.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/traps.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331f66e06fb6414732bef7bf4a071ef76a837badecWade Farnsworth#define CREATE_TRACE_POINTS 341f66e06fb6414732bef7bf4a071ef76a837badecWade Farnsworth#include <trace/events/syscalls.h> 351f66e06fb6414732bef7bf4a071ef76a837badecWade Farnsworth 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define REG_PC 15 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define REG_PSR 16 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does not yet catch signals sent when the child dies. 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in exit.c or in signal.c. 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Breakpoint SWI instruction: SWI &9F0001 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_ARM 0xef9f0001 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_THUMB 0xdf00 /* fill this in later */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * New breakpoints - use an undefined instruction. The ARM architecture 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reference manual guarantees that the following instruction space 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will produce an undefined instruction exception on all CPUs: 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thumb: 1101 1110 xxxx xxxx 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_ARM 0xe7f001f0 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BREAKINST_THUMB 0xde01 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 62e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconstruct pt_regs_offset { 63e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon const char *name; 64e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon int offset; 65e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon}; 66e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 67e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon#define REG_OFFSET_NAME(r) \ 68e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)} 69e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon#define REG_OFFSET_END {.name = NULL, .offset = 0} 70e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 71e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconstatic const struct pt_regs_offset regoffset_table[] = { 72e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r0), 73e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r1), 74e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r2), 75e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r3), 76e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r4), 77e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r5), 78e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r6), 79e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r7), 80e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r8), 81e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r9), 82e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(r10), 83e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(fp), 84e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(ip), 85e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(sp), 86e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(lr), 87e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(pc), 88e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(cpsr), 89e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_NAME(ORIG_r0), 90e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon REG_OFFSET_END, 91e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon}; 92e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 93e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 94e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_offset() - query register offset from its name 95e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @name: the name of a register 96e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 97e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_offset() returns the offset of a register in struct 98e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * pt_regs from its name. If the name is invalid, this returns -EINVAL; 99e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 100e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconint regs_query_register_offset(const char *name) 101e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 102e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon const struct pt_regs_offset *roff; 103e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon for (roff = regoffset_table; roff->name != NULL; roff++) 104e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon if (!strcmp(roff->name, name)) 105e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return roff->offset; 106e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return -EINVAL; 107e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 108e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 109e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 110e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_name() - query register name from its offset 111e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @offset: the offset of a register in struct pt_regs. 112e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 113e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_query_register_name() returns the name of a register from its 114e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * offset in struct pt_regs. If the @offset is invalid, this returns NULL; 115e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 116e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconconst char *regs_query_register_name(unsigned int offset) 117e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 118e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon const struct pt_regs_offset *roff; 119e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon for (roff = regoffset_table; roff->name != NULL; roff++) 120e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon if (roff->offset == offset) 121e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return roff->name; 122e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return NULL; 123e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 124e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 125e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 126e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_within_kernel_stack() - check the address in the stack 127e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @regs: pt_regs which contains kernel stack pointer. 128e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @addr: address which is checked. 129e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 130e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). 131e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * If @addr is within the kernel stack, it returns true. If not, returns false. 132e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 133e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconbool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) 134e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 135e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return ((addr & ~(THREAD_SIZE - 1)) == 136e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); 137e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 138e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 139e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon/** 140e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_get_kernel_stack_nth() - get Nth entry of the stack 141e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @regs: pt_regs which contains kernel stack pointer. 142e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * @n: stack entry number. 143e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * 144e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which 145e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * is specified by @regs. If the @n th entry is NOT in the kernel stack, 146e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon * this returns 0. 147e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon */ 148e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deaconunsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) 149e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon{ 150e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); 151e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon addr += n; 152e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon if (regs_within_kernel_stack(regs, (unsigned long)addr)) 153e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return *addr; 154e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon else 155e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon return 0; 156e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon} 157e513f8bf240d34bd6e732ba2f74df9ab84686ce6Will Deacon 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine will get a word off of the processes privileged stack. 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the offset is how far from the base addr as stored in the THREAD. 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine assumes that all the privileged stacks are in our 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data space. 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline long get_user_reg(struct task_struct *task, int offset) 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 166815d5ec86eb8d5f57e5e4aa147bd1fb6338c58acAl Viro return task_pt_regs(task)->uregs[offset]; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine will put a word on the processes privileged stack. 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the offset is how far from the base addr as stored in the THREAD. 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this routine assumes that all the privileged stacks are in our 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data space. 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsput_user_reg(struct task_struct *task, int offset, long data) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 178815d5ec86eb8d5f57e5e4aa147bd1fb6338c58acAl Viro struct pt_regs newregs, *regs = task_pt_regs(task); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -EINVAL; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newregs = *regs; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newregs.uregs[offset] = data; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (valid_user_regs(&newregs)) { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->uregs[offset] = data; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by kernel/ptrace.c when detaching.. 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ptrace_disable(struct task_struct *child) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 197425fc47adb5bb69f76285be77a09a3341a30799eWill Deacon /* Nothing to do. */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle hitting a breakpoint. 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ptrace_break(struct task_struct *tsk, struct pt_regs *regs) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t info; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_signo = SIGTRAP; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_errno = 0; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_code = TRAP_BRKPT; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.si_addr = (void __user *)instruction_pointer(regs); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGTRAP, &info, tsk); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int break_trap(struct pt_regs *regs, unsigned int instr) 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptrace_break(current, regs); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct undef_hook arm_break_hook = { 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_mask = 0x0fffffff, 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_val = 0x07f001f0, 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_mask = PSR_T_BIT, 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_val = 0, 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fn = break_trap, 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct undef_hook thumb_break_hook = { 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_mask = 0xffff, 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .instr_val = 0xde01, 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_mask = PSR_T_BIT, 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cpsr_val = PSR_T_BIT, 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fn = break_trap, 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 237d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitzstatic struct undef_hook thumb2_break_hook = { 238592201a9f154cdd5db59304d1369e94d8b551803Jon Medhurst .instr_mask = 0xffffffff, 239592201a9f154cdd5db59304d1369e94d8b551803Jon Medhurst .instr_val = 0xf7f0a000, 240d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz .cpsr_mask = PSR_T_BIT, 241d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz .cpsr_val = PSR_T_BIT, 242592201a9f154cdd5db59304d1369e94d8b551803Jon Medhurst .fn = break_trap, 243d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz}; 244d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init ptrace_break_init(void) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_undef_hook(&arm_break_hook); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register_undef_hook(&thumb_break_hook); 249d23bc1b3a7e6db935acb9a949a5985d9b77dfd13Daniel Jacobowitz register_undef_hook(&thumb2_break_hook); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscore_initcall(ptrace_break_init); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read the word at offset "off" into the "struct user". We 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually access the pt_regs stored on the kernel stack. 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_read_user(struct task_struct *tsk, unsigned long off, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long __user *ret) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long tmp; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2645a4f5da543b169d555a19e889850780ddceb8f98Will Deacon if (off & 3) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = 0; 26868b7f7153fa58df710924fbb79722717d2d16094Paul Brook if (off == PT_TEXT_ADDR) 26968b7f7153fa58df710924fbb79722717d2d16094Paul Brook tmp = tsk->mm->start_code; 27068b7f7153fa58df710924fbb79722717d2d16094Paul Brook else if (off == PT_DATA_ADDR) 27168b7f7153fa58df710924fbb79722717d2d16094Paul Brook tmp = tsk->mm->start_data; 27268b7f7153fa58df710924fbb79722717d2d16094Paul Brook else if (off == PT_TEXT_END_ADDR) 27368b7f7153fa58df710924fbb79722717d2d16094Paul Brook tmp = tsk->mm->end_code; 27468b7f7153fa58df710924fbb79722717d2d16094Paul Brook else if (off < sizeof(struct pt_regs)) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = get_user_reg(tsk, off >> 2); 2765a4f5da543b169d555a19e889850780ddceb8f98Will Deacon else if (off >= sizeof(struct user)) 2775a4f5da543b169d555a19e889850780ddceb8f98Will Deacon return -EIO; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(tmp, ret); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write the word at offset "off" into "struct user". We 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually access the pt_regs stored on the kernel stack. 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_write_user(struct task_struct *tsk, unsigned long off, 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long val) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off & 3 || off >= sizeof(struct user)) 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off >= sizeof(struct pt_regs)) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user_reg(tsk, off >> 2, val); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IWMMXT 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the child iWMMXt state. 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 305e7c1b32fd354c34c4dceb1736a485bc5d91f7c43Al Viro struct thread_info *thread = task_thread_info(tsk); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODATA; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iwmmxt_task_disable(thread); /* force it to ram */ 310cdaabbd74b15296acf09215355a7f3b07b92b83eRussell King return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE) 311cdaabbd74b15296acf09215355a7f3b07b92b83eRussell King ? -EFAULT : 0; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the child iWMMXt state. 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 319e7c1b32fd354c34c4dceb1736a485bc5d91f7c43Al Viro struct thread_info *thread = task_thread_info(tsk); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EACCES; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iwmmxt_task_release(thread); /* force a reload */ 32417320a9644a45ccac51ce4ff4333276844abf72dRussell King return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE) 325cdaabbd74b15296acf09215355a7f3b07b92b83eRussell King ? -EFAULT : 0; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3305429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#ifdef CONFIG_CRUNCH 3315429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek/* 3325429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek * Get the child Crunch state. 3335429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek */ 3345429b060df6d556f396b78364ad017686015bc34Lennert Buytenhekstatic int ptrace_getcrunchregs(struct task_struct *tsk, void __user *ufp) 3355429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek{ 3365429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek struct thread_info *thread = task_thread_info(tsk); 3375429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 3385429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek crunch_task_disable(thread); /* force it to ram */ 3395429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek return copy_to_user(ufp, &thread->crunchstate, CRUNCH_SIZE) 3405429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek ? -EFAULT : 0; 3415429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek} 3425429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 3435429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek/* 3445429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek * Set the child Crunch state. 3455429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek */ 3465429b060df6d556f396b78364ad017686015bc34Lennert Buytenhekstatic int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp) 3475429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek{ 3485429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek struct thread_info *thread = task_thread_info(tsk); 3495429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 3505429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek crunch_task_release(thread); /* force a reload */ 3515429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek return copy_from_user(&thread->crunchstate, ufp, CRUNCH_SIZE) 3525429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek ? -EFAULT : 0; 3535429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek} 3545429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#endif 3555429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 356864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#ifdef CONFIG_HAVE_HW_BREAKPOINT 357864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 358864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Convert a virtual register number into an index for a thread_info 359864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * breakpoint array. Breakpoints are identified using positive numbers 360864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * whilst watchpoints are negative. The registers are laid out as pairs 361864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * of (address, control), each pair mapping to a unique hw_breakpoint struct. 362864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Register 0 is reserved for describing resource information. 363864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 364864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic int ptrace_hbp_num_to_idx(long num) 365864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 366864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num < 0) 367864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num = (ARM_MAX_BRP << 1) - num; 368864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return (num - 1) >> 1; 369864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 370864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 371864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 372864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Returns the virtual register number for the address of the 373864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * breakpoint at index idx. 374864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 375864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic long ptrace_hbp_idx_to_num(int idx) 376864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 377864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon long mid = ARM_MAX_BRP << 1; 378864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon long num = (idx << 1) + 1; 379864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return num > mid ? mid - num : num; 380864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 381864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 382864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 383864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Handle hitting a HW-breakpoint. 384864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 385a8b0ca17b80e92faab46ee7179ba9e99ccb61233Peter Zijlstrastatic void ptrace_hbptriggered(struct perf_event *bp, 386864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_sample_data *data, 387864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct pt_regs *regs) 388864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 389864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); 390864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon long num; 391864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int i; 392864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon siginfo_t info; 393864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 394864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i) 395864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (current->thread.debug.hbp[i] == bp) 396864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon break; 397864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 398864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i); 399864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 400864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_signo = SIGTRAP; 401864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_errno = (int)num; 402864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_code = TRAP_HWBKPT; 403864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon info.si_addr = (void __user *)(bkpt->trigger); 404864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 405864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon force_sig_info(SIGTRAP, &info, current); 406864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 407864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 408864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 409864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Set ptrace breakpoint pointers to zero for this task. 410864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * This is required in order to prevent child processes from unregistering 411864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * breakpoints held by their parent. 412864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 413864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconvoid clear_ptrace_hw_breakpoint(struct task_struct *tsk) 414864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 415864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp)); 416864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 417864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 418864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon/* 419864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Unregister breakpoints from this task and reset the pointers in 420864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * the thread_struct. 421864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 422864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconvoid flush_ptrace_hw_breakpoint(struct task_struct *tsk) 423864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 424864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int i; 425864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct thread_struct *t = &tsk->thread; 426864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 427864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) { 428864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (t->debug.hbp[i]) { 429864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon unregister_hw_breakpoint(t->debug.hbp[i]); 430864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon t->debug.hbp[i] = NULL; 431864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 432864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 433864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 434864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 435864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic u32 ptrace_get_hbp_resource_info(void) 436864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 437864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u8 num_brps, num_wrps, debug_arch, wp_len; 438864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u32 reg = 0; 439864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 440864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num_brps = hw_breakpoint_slots(TYPE_INST); 441864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon num_wrps = hw_breakpoint_slots(TYPE_DATA); 442864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon debug_arch = arch_get_debug_arch(); 443864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon wp_len = arch_get_max_wp_len(); 444864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 445864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= debug_arch; 446864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg <<= 8; 447864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= wp_len; 448864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg <<= 8; 449864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= num_wrps; 450864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg <<= 8; 451864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg |= num_brps; 452864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 453864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return reg; 454864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 455864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 456864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type) 457864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 458864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event_attr attr; 459864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 460864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ptrace_breakpoint_init(&attr); 461864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 462864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* Initialise fields to sane defaults. */ 463864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_addr = 0; 464864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_len = HW_BREAKPOINT_LEN_4; 465864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_type = type; 466864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.disabled = 1; 467864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 4684dc0da86967d5463708631d02a70cfed5b104884Avi Kivity return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, 4694dc0da86967d5463708631d02a70cfed5b104884Avi Kivity tsk); 470864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 471864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 472864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic int ptrace_gethbpregs(struct task_struct *tsk, long num, 473864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon unsigned long __user *data) 474864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 475864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u32 reg; 476864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int idx, ret = 0; 477864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event *bp; 478864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct arch_hw_breakpoint_ctrl arch_ctrl; 479864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 480864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num == 0) { 481864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg = ptrace_get_hbp_resource_info(); 482864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } else { 483864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon idx = ptrace_hbp_num_to_idx(num); 484864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { 485864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EINVAL; 486864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 487864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 488864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 489864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon bp = tsk->thread.debug.hbp[idx]; 490864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (!bp) { 491864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg = 0; 492864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto put; 493864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 494864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 495864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon arch_ctrl = counter_arch_bp(bp)->ctrl; 496864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 497864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* 498864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * Fix up the len because we may have adjusted it 499864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon * to compensate for an unaligned address. 500864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon */ 501864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon while (!(arch_ctrl.len & 0x1)) 502864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon arch_ctrl.len >>= 1; 503864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 504ba55d3db9bb59a52fe45dbc5d62776adbb289e54Will Deacon if (num & 0x1) 505864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon reg = bp->attr.bp_addr; 506ba55d3db9bb59a52fe45dbc5d62776adbb289e54Will Deacon else 507ba55d3db9bb59a52fe45dbc5d62776adbb289e54Will Deacon reg = encode_ctrl_reg(arch_ctrl); 508864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 509864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 510864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconput: 511864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (put_user(reg, data)) 512864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EFAULT; 513864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 514864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconout: 515864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return ret; 516864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 517864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 518864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconstatic int ptrace_sethbpregs(struct task_struct *tsk, long num, 519864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon unsigned long __user *data) 520864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon{ 521864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon int idx, gen_len, gen_type, implied_type, ret = 0; 522864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon u32 user_val; 523864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event *bp; 524864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct arch_hw_breakpoint_ctrl ctrl; 525864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon struct perf_event_attr attr; 526864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 527864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num == 0) 528864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 529864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon else if (num < 0) 530864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon implied_type = HW_BREAKPOINT_RW; 531864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon else 532864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon implied_type = HW_BREAKPOINT_X; 533864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 534864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon idx = ptrace_hbp_num_to_idx(num); 535864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { 536864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EINVAL; 537864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 538864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 539864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 540864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (get_user(user_val, data)) { 541864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = -EFAULT; 542864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 543864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 544864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 545864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon bp = tsk->thread.debug.hbp[idx]; 546864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (!bp) { 547864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon bp = ptrace_hbp_create(tsk, implied_type); 548864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (IS_ERR(bp)) { 549864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = PTR_ERR(bp); 550864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 551864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 552864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon tsk->thread.debug.hbp[idx] = bp; 553864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 554864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 555864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr = bp->attr; 556864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 557864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (num & 0x1) { 558864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* Address */ 559864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_addr = user_val; 560864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } else { 561864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon /* Control */ 562864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon decode_ctrl_reg(user_val, &ctrl); 563864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type); 564864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if (ret) 565864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon goto out; 566864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 567864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon if ((gen_type & implied_type) != gen_type) { 568ce9b1b09520789223f72a9fefd5f0e329f8d89d0Will Deacon ret = -EINVAL; 569ce9b1b09520789223f72a9fefd5f0e329f8d89d0Will Deacon goto out; 570864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 571864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 572864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_len = gen_len; 573864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.bp_type = gen_type; 574864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon attr.disabled = !ctrl.enabled; 575864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon } 576864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 577864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = modify_user_hw_breakpoint(bp, &attr); 578864232fa1a2f8dfe003438ef0851a56722740f3eWill Deaconout: 579864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon return ret; 580864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon} 581864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#endif 582864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 5835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin/* regset get/set implementations */ 5845be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 5855be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int gpr_get(struct task_struct *target, 5865be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 5875be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 5885be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin void *kbuf, void __user *ubuf) 5895be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 5905be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct pt_regs *regs = task_pt_regs(target); 5915be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 5925be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 5935be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin regs, 5945be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(*regs)); 5955be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 5965be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 5975be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int gpr_set(struct task_struct *target, 5985be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 5995be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6005be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const void *kbuf, const void __user *ubuf) 6015be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6025be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin int ret; 6035be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct pt_regs newregs; 6045be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6055be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 6065be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &newregs, 6075be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(newregs)); 6085be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 6095be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 6105be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6115be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (!valid_user_regs(&newregs)) 6125be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return -EINVAL; 6135be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6145be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin *task_pt_regs(target) = newregs; 6155be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return 0; 6165be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6175be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6185be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int fpa_get(struct task_struct *target, 6195be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6205be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6215be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin void *kbuf, void __user *ubuf) 6225be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6235be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 6245be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &task_thread_info(target)->fpstate, 6255be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct user_fp)); 6265be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6275be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6285be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int fpa_set(struct task_struct *target, 6295be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6305be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6315be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const void *kbuf, const void __user *ubuf) 6325be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6335be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct thread_info *thread = task_thread_info(target); 6345be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6355be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin thread->used_cp[1] = thread->used_cp[2] = 1; 6365be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6375be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 6385be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &thread->fpstate, 6395be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct user_fp)); 6405be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6415be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6425be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#ifdef CONFIG_VFP 6435be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin/* 6445be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * VFP register get/set implementations. 6455be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6465be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * With respect to the kernel, struct user_fp is divided into three chunks: 6475be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 16 or 32 real VFP registers (d0-d15 or d0-31) 6485be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * These are transferred to/from the real registers in the task's 6495be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * vfp_hard_struct. The number of registers depends on the kernel 6505be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * configuration. 6515be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6525be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 16 or 0 fake VFP registers (d16-d31 or empty) 6535be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * i.e., the user_vfp structure has space for 32 registers even if 6545be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * the kernel doesn't have them all. 6555be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6565be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * vfp_get() reads this chunk as zero where applicable 6575be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * vfp_set() ignores this chunk 6585be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6595be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 1 word for the FPSCR 6605be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * 6615be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * The bounds-checking logic built into user_regset_copyout and friends 6625be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * means that we can make a simple sequence of calls to map the relevant data 6635be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * to/from the specified slice of the user regset structure. 6645be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 6655be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int vfp_get(struct task_struct *target, 6665be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 6675be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 6685be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin void *kbuf, void __user *ubuf) 6695be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 6705be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin int ret; 6715be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct thread_info *thread = task_thread_info(target); 6725be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; 6735be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); 6745be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); 6755be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6765be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin vfp_sync_hwstate(thread); 6775be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6785be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 6795be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &vfp->fpregs, 6805be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset, 6815be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(vfp->fpregs)); 6825be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 6835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 6845be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6855be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 6865be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(vfp->fpregs), 6875be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset); 6885be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 6895be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 6905be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6915be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 6925be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &vfp->fpscr, 6935be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset, 6945be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset + sizeof(vfp->fpscr)); 6955be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 6965be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 6975be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin/* 6985be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * For vfp_set() a read-modify-write is done on the VFP registers, 6995be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * in order to avoid writing back a half-modified set of registers on 7005be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * failure. 7015be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 7025be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic int vfp_set(struct task_struct *target, 7035be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const struct user_regset *regset, 7045be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin unsigned int pos, unsigned int count, 7055be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const void *kbuf, const void __user *ubuf) 7065be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 7075be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin int ret; 7085be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin struct thread_info *thread = task_thread_info(target); 709247f4993a5974e6759606c4d380748eecfd273ffDave Martin struct vfp_hard_struct new_vfp; 7105be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); 7115be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); 7125be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 713247f4993a5974e6759606c4d380748eecfd273ffDave Martin vfp_sync_hwstate(thread); 714247f4993a5974e6759606c4d380748eecfd273ffDave Martin new_vfp = thread->vfpstate.hard; 715247f4993a5974e6759606c4d380748eecfd273ffDave Martin 7165be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 7175be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &new_vfp.fpregs, 7185be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset, 7195be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(new_vfp.fpregs)); 7205be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 7215be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 7225be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7235be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 7245be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpregs_offset + sizeof(new_vfp.fpregs), 7255be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset); 7265be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 7275be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 7285be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7295be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 7305be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &new_vfp.fpscr, 7315be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset, 7325be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin user_fpscr_offset + sizeof(new_vfp.fpscr)); 7335be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin if (ret) 7345be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return ret; 7355be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7365be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin vfp_flush_hwstate(thread); 7378130b9d7b9d858aa04ce67805e8951e3cb6e9b2fWill Deacon thread->vfpstate.hard = new_vfp; 7385be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7395be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return 0; 7405be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 7415be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#endif /* CONFIG_VFP */ 7425be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7435be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinenum arm_regset { 7445be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin REGSET_GPR, 7455be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin REGSET_FPR, 7465be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#ifdef CONFIG_VFP 7475be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin REGSET_VFP, 7485be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#endif 7495be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin}; 7505be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7515be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic const struct user_regset arm_regsets[] = { 7525be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin [REGSET_GPR] = { 7535be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .core_note_type = NT_PRSTATUS, 7545be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .n = ELF_NGREG, 7555be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .size = sizeof(u32), 7565be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .align = sizeof(u32), 7575be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .get = gpr_get, 7585be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .set = gpr_set 7595be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin }, 7605be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin [REGSET_FPR] = { 7615be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin /* 7625be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * For the FPA regs in fpstate, the real fields are a mixture 7635be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * of sizes, so pretend that the registers are word-sized: 7645be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 7655be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .core_note_type = NT_PRFPREG, 7665be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .n = sizeof(struct user_fp) / sizeof(u32), 7675be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .size = sizeof(u32), 7685be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .align = sizeof(u32), 7695be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .get = fpa_get, 7705be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .set = fpa_set 7715be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin }, 7725be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#ifdef CONFIG_VFP 7735be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin [REGSET_VFP] = { 7745be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin /* 7755be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * Pretend that the VFP regs are word-sized, since the FPSCR is 7765be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin * a single word dangling at the end of struct user_vfp: 7775be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin */ 7785be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .core_note_type = NT_ARM_VFP, 7795be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .n = ARM_VFPREGS_SIZE / sizeof(u32), 7805be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .size = sizeof(u32), 7815be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .align = sizeof(u32), 7825be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .get = vfp_get, 7835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .set = vfp_set 7845be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin }, 7855be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin#endif /* CONFIG_VFP */ 7865be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin}; 7875be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7885be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinstatic const struct user_regset_view user_arm_view = { 7895be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, 7905be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets) 7915be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin}; 7925be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7935be6f62b0059a3344437b4c2877152c58cb3fdebDave Martinconst struct user_regset_view *task_user_regset_view(struct task_struct *task) 7945be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin{ 7955be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin return &user_arm_view; 7965be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin} 7975be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 7989b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kimlong arch_ptrace(struct task_struct *child, long request, 7999b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim unsigned long addr, unsigned long data) 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 802b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim unsigned long __user *datap = (unsigned long __user *) data; 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (request) { 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_PEEKUSR: 806b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_read_user(child, addr, datap); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_POKEUSR: 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ptrace_write_user(child, addr, data); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETREGS: 8145be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_to_user(child, 8155be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_GPR, 8165be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct pt_regs), 8175be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETREGS: 8215be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_from_user(child, 8225be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_GPR, 8235be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(struct pt_regs), 8245be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETFPREGS: 8285be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_to_user(child, 8295be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_FPR, 8305be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(union fp_state), 8315be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8335be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETFPREGS: 8355be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_from_user(child, 8365be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_FPR, 8375be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, sizeof(union fp_state), 8385be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IWMMXT 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETWMMXREGS: 843b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_getwmmxregs(child, datap); 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETWMMXREGS: 847b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_setwmmxregs(child, datap); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GET_THREAD_AREA: 852a4780adeefd042482f624f5e0d577bf9cdcbb760André Hentschel ret = put_user(task_thread_info(child)->tp_value[0], 853b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim datap); 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8563f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre case PTRACE_SET_SYSCALL: 8575ba6d3febd4978f31b2c523d64d381603923a709Russell King task_thread_info(child)->syscall = data; 8583f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre ret = 0; 8593f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre break; 8603f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre 8615429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#ifdef CONFIG_CRUNCH 8625429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek case PTRACE_GETCRUNCHREGS: 863b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_getcrunchregs(child, datap); 8645429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek break; 8655429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 8665429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek case PTRACE_SETCRUNCHREGS: 867b640a0d192265c47bbf60951115bdb59d2c017d1Namhyung Kim ret = ptrace_setcrunchregs(child, datap); 8685429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek break; 8695429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek#endif 8705429b060df6d556f396b78364ad017686015bc34Lennert Buytenhek 8713d1228ead618b88e8606015cbabc49019981805dCatalin Marinas#ifdef CONFIG_VFP 8723d1228ead618b88e8606015cbabc49019981805dCatalin Marinas case PTRACE_GETVFPREGS: 8735be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_to_user(child, 8745be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_VFP, 8755be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, ARM_VFPREGS_SIZE, 8765be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8773d1228ead618b88e8606015cbabc49019981805dCatalin Marinas break; 8783d1228ead618b88e8606015cbabc49019981805dCatalin Marinas 8793d1228ead618b88e8606015cbabc49019981805dCatalin Marinas case PTRACE_SETVFPREGS: 8805be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin ret = copy_regset_from_user(child, 8815be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin &user_arm_view, REGSET_VFP, 8825be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin 0, ARM_VFPREGS_SIZE, 8835be6f62b0059a3344437b4c2877152c58cb3fdebDave Martin datap); 8843d1228ead618b88e8606015cbabc49019981805dCatalin Marinas break; 8853d1228ead618b88e8606015cbabc49019981805dCatalin Marinas#endif 8863d1228ead618b88e8606015cbabc49019981805dCatalin Marinas 887864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#ifdef CONFIG_HAVE_HW_BREAKPOINT 888864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon case PTRACE_GETHBPREGS: 889864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = ptrace_gethbpregs(child, addr, 890864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon (unsigned long __user *)data); 891864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon break; 892864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon case PTRACE_SETHBPREGS: 893864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon ret = ptrace_sethbpregs(child, addr, 894864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon (unsigned long __user *)data); 895864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon break; 896864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon#endif 897864232fa1a2f8dfe003438ef0851a56722740f3eWill Deacon 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ptrace_request(child, request, addr, data); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 906ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deaconenum ptrace_syscall_dir { 907ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon PTRACE_SYSCALL_ENTER = 0, 908ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon PTRACE_SYSCALL_EXIT, 909ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon}; 910ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon 91142309ab450b608ddcfafa90e4cfa93a5001ecfbaWill Deaconstatic void tracehook_report_syscall(struct pt_regs *regs, 9129b790d71d58be65f9508ab60920eb978af828412Kees Cook enum ptrace_syscall_dir dir) 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ip; 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9166a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon /* 9176a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon * IP is used to denote syscall entry/exit: 9186a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon * IP = 0 -> entry, =1 -> exit 9196a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon */ 9206a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon ip = regs->ARM_ip; 921ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon regs->ARM_ip = dir; 9226a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73Will Deacon 923ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon if (dir == PTRACE_SYSCALL_EXIT) 9240693bf68148c4473158e435383e75af70b704f78Wade Farnsworth tracehook_report_syscall_exit(regs, 0); 9250693bf68148c4473158e435383e75af70b704f78Wade Farnsworth else if (tracehook_report_syscall_entry(regs)) 9260693bf68148c4473158e435383e75af70b704f78Wade Farnsworth current_thread_info()->syscall = -1; 9270693bf68148c4473158e435383e75af70b704f78Wade Farnsworth 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->ARM_ip = ip; 929ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon} 9303f471126ee53feb5e9b210ea2f525ed3bb9b7a7fNicolas Pitre 931ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deaconasmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) 932ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon{ 9339b790d71d58be65f9508ab60920eb978af828412Kees Cook current_thread_info()->syscall = scno; 9349b790d71d58be65f9508ab60920eb978af828412Kees Cook 9359b790d71d58be65f9508ab60920eb978af828412Kees Cook /* Do the secure computing check first; failures should be fast. */ 936a4412fc9486ec85686c6c7929e7e829f62ae377eAndy Lutomirski#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER 937a4412fc9486ec85686c6c7929e7e829f62ae377eAndy Lutomirski if (secure_computing() == -1) 9389b790d71d58be65f9508ab60920eb978af828412Kees Cook return -1; 939a4412fc9486ec85686c6c7929e7e829f62ae377eAndy Lutomirski#else 940a4412fc9486ec85686c6c7929e7e829f62ae377eAndy Lutomirski /* XXX: remove this once OABI gets fixed */ 941a4412fc9486ec85686c6c7929e7e829f62ae377eAndy Lutomirski secure_computing_strict(scno); 942a4412fc9486ec85686c6c7929e7e829f62ae377eAndy Lutomirski#endif 9439b790d71d58be65f9508ab60920eb978af828412Kees Cook 9449b790d71d58be65f9508ab60920eb978af828412Kees Cook if (test_thread_flag(TIF_SYSCALL_TRACE)) 94542309ab450b608ddcfafa90e4cfa93a5001ecfbaWill Deacon tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); 94642309ab450b608ddcfafa90e4cfa93a5001ecfbaWill Deacon 94742309ab450b608ddcfafa90e4cfa93a5001ecfbaWill Deacon scno = current_thread_info()->syscall; 9489b790d71d58be65f9508ab60920eb978af828412Kees Cook 9491f66e06fb6414732bef7bf4a071ef76a837badecWade Farnsworth if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 950ebb5e15c3eb942c047108063423d5d6a04b9f167Will Deacon trace_sys_enter(regs, scno); 9519b790d71d58be65f9508ab60920eb978af828412Kees Cook 95291397401bb5072f71e8ce8744ad0bdec3e875a91Eric Paris audit_syscall_entry(scno, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, 95391397401bb5072f71e8ce8744ad0bdec3e875a91Eric Paris regs->ARM_r3); 9549b790d71d58be65f9508ab60920eb978af828412Kees Cook 955ebb5e15c3eb942c047108063423d5d6a04b9f167Will Deacon return scno; 956ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon} 957ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon 958b10bca0bc699af201770989a88fa293155e9d8deWill Deaconasmlinkage void syscall_trace_exit(struct pt_regs *regs) 959ad722541147e6e517a2077e3d944105e7bc4fa8eWill Deacon{ 960b10bca0bc699af201770989a88fa293155e9d8deWill Deacon /* 961b10bca0bc699af201770989a88fa293155e9d8deWill Deacon * Audit the syscall before anything else, as a debugger may 962b10bca0bc699af201770989a88fa293155e9d8deWill Deacon * come in and change the current registers. 963b10bca0bc699af201770989a88fa293155e9d8deWill Deacon */ 964b10bca0bc699af201770989a88fa293155e9d8deWill Deacon audit_syscall_exit(regs); 9659b790d71d58be65f9508ab60920eb978af828412Kees Cook 966b10bca0bc699af201770989a88fa293155e9d8deWill Deacon /* 967b10bca0bc699af201770989a88fa293155e9d8deWill Deacon * Note that we haven't updated the ->syscall field for the 968b10bca0bc699af201770989a88fa293155e9d8deWill Deacon * current thread. This isn't a problem because it will have 969b10bca0bc699af201770989a88fa293155e9d8deWill Deacon * been set on syscall entry and there hasn't been an opportunity 970b10bca0bc699af201770989a88fa293155e9d8deWill Deacon * for a PTRACE_SET_SYSCALL since then. 971b10bca0bc699af201770989a88fa293155e9d8deWill Deacon */ 9721f66e06fb6414732bef7bf4a071ef76a837badecWade Farnsworth if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 973b10bca0bc699af201770989a88fa293155e9d8deWill Deacon trace_sys_exit(regs, regs_return_value(regs)); 9749b790d71d58be65f9508ab60920eb978af828412Kees Cook 975b10bca0bc699af201770989a88fa293155e9d8deWill Deacon if (test_thread_flag(TIF_SYSCALL_TRACE)) 976b10bca0bc699af201770989a88fa293155e9d8deWill Deacon tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT); 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 978