11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PowerPC version 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Derived from "arch/m68k/kernel/ptrace.c" 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994 by Hamish Macdonald 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Taken from linux/kernel/ptrace.c and modified for M680x0. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified by Cort Dougan (cort@hq.fsmlabs.com) 11b123923d486d38e1a961e82040a26838401aebb5Paul Mackerras * and Paul Mackerras (paulus@samba.org). 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Public License. See the file README.legal in the main directory of 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this archive for more details. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 24f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath#include <linux/regset.h> 254f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath#include <linux/tracehook.h> 263caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath#include <linux/elf.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/user.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/security.h> 297ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 30ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse#include <linux/seccomp.h> 31ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse#include <linux/audit.h> 3202424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie#include <trace/syscall.h> 335aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#include <linux/hw_breakpoint.h> 345aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#include <linux/perf_event.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/page.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h> 39ae3a197e3d0bfe3f4bf1693723e82dc018c096f3David Howells#include <asm/switch_to.h> 4021a6290220679d94912a068c75db2c5cd9c6552aPaul Mackerras 4102424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie#define CREATE_TRACE_POINTS 4202424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie#include <trace/events/syscalls.h> 4302424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie 44abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt/* 45359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * The parameter save area on the stack is used to store arguments being passed 46359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * to callee function and is located at fixed offset from stack pointer. 47359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar */ 48359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#ifdef CONFIG_PPC32 49359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#define PARAMETER_SAVE_AREA_OFFSET 24 /* bytes */ 50359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#else /* CONFIG_PPC32 */ 51359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#define PARAMETER_SAVE_AREA_OFFSET 48 /* bytes */ 52359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#endif 53359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar 54359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkarstruct pt_regs_offset { 55359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar const char *name; 56359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar int offset; 57359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar}; 58359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar 59359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#define STR(s) #s /* convert to string */ 60359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} 61359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#define GPR_OFFSET_NAME(num) \ 62359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])} 63359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#define REG_OFFSET_END {.name = NULL, .offset = 0} 64359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar 65359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkarstatic const struct pt_regs_offset regoffset_table[] = { 66359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(0), 67359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(1), 68359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(2), 69359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(3), 70359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(4), 71359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(5), 72359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(6), 73359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(7), 74359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(8), 75359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(9), 76359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(10), 77359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(11), 78359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(12), 79359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(13), 80359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(14), 81359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(15), 82359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(16), 83359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(17), 84359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(18), 85359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(19), 86359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(20), 87359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(21), 88359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(22), 89359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(23), 90359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(24), 91359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(25), 92359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(26), 93359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(27), 94359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(28), 95359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(29), 96359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(30), 97359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar GPR_OFFSET_NAME(31), 98359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(nip), 99359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(msr), 100359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(ctr), 101359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(link), 102359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(xer), 103359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(ccr), 104359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#ifdef CONFIG_PPC64 105359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(softe), 106359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#else 107359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(mq), 108359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar#endif 109359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(trap), 110359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(dar), 111359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_NAME(dsisr), 112359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar REG_OFFSET_END, 113359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar}; 114359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar 115359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar/** 116359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * regs_query_register_offset() - query register offset from its name 117359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * @name: the name of a register 118359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * 119359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * regs_query_register_offset() returns the offset of a register in struct 120359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * pt_regs from its name. If the name is invalid, this returns -EINVAL; 121359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar */ 122359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkarint regs_query_register_offset(const char *name) 123359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar{ 124359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar const struct pt_regs_offset *roff; 125359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar for (roff = regoffset_table; roff->name != NULL; roff++) 126359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar if (!strcmp(roff->name, name)) 127359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar return roff->offset; 128359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar return -EINVAL; 129359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar} 130359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar 131359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar/** 132359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * regs_query_register_name() - query register name from its offset 133359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * @offset: the offset of a register in struct pt_regs. 134359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * 135359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * regs_query_register_name() returns the name of a register from its 136359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar * offset in struct pt_regs. If the @offset is invalid, this returns NULL; 137359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar */ 138359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkarconst char *regs_query_register_name(unsigned int offset) 139359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar{ 140359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar const struct pt_regs_offset *roff; 141359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar for (roff = regoffset_table; roff->name != NULL; roff++) 142359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar if (roff->offset == offset) 143359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar return roff->name; 144359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar return NULL; 145359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar} 146359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar 147359e4284a3f37aba7fd06d993863de2509d86f54Mahesh Salgaonkar/* 148abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt * does not yet catch signals sent when the child dies. 149abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt * in exit.c or in signal.c. 150abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt */ 151abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt 152abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt/* 153abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt * Set of msr bits that gdb can change on behalf of a process. 154abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt */ 155172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 156abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#define MSR_DEBUGCHANGE 0 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 158abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 160acd89828484db6371202f5d292781ae6f832eda2Benjamin Herrenschmidt 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 162abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt * Max register writeable via put_reg 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 164abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#ifdef CONFIG_PPC32 165abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#define PT_MAX_PUT_REG PT_MQ 166abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#else 167abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#define PT_MAX_PUT_REG PT_CCR 168abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt#endif 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17026f7713020129e556e494fd36b2db1e651e33ba3Roland McGrathstatic unsigned long get_user_msr(struct task_struct *task) 17126f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath{ 17226f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath return task->thread.regs->msr | task->thread.fpexc_mode; 17326f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath} 17426f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath 17526f7713020129e556e494fd36b2db1e651e33ba3Roland McGrathstatic int set_user_msr(struct task_struct *task, unsigned long msr) 17626f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath{ 17726f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath task->thread.regs->msr &= ~MSR_DEBUGCHANGE; 17826f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath task->thread.regs->msr |= msr & MSR_DEBUGCHANGE; 17926f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath return 0; 18026f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath} 18126f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath 18226f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath/* 18326f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath * We prevent mucking around with the reserved area of trap 18426f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath * which are used internally by the kernel. 18526f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath */ 18626f7713020129e556e494fd36b2db1e651e33ba3Roland McGrathstatic int set_user_trap(struct task_struct *task, unsigned long trap) 18726f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath{ 18826f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath task->thread.regs->trap = trap & 0xfff0; 18926f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath return 0; 19026f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath} 19126f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 193865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * Get contents of register REGNO in task TASK. 194865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt */ 195865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidtunsigned long ptrace_get_reg(struct task_struct *task, int regno) 196865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt{ 197865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt if (task->thread.regs == NULL) 198865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt return -EIO; 199865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 20026f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath if (regno == PT_MSR) 20126f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath return get_user_msr(task); 202865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 203865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) 204865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt return ((unsigned long *)task->thread.regs)[regno]; 205865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 206865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt return -EIO; 207865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt} 208865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 209865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt/* 210865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * Write contents of register REGNO in task TASK. 211865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt */ 212865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidtint ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) 213865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt{ 214865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt if (task->thread.regs == NULL) 215865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt return -EIO; 216865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 21726f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath if (regno == PT_MSR) 21826f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath return set_user_msr(task, data); 21926f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath if (regno == PT_TRAP) 22026f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath return set_user_trap(task, data); 22126f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath 22226f7713020129e556e494fd36b2db1e651e33ba3Roland McGrath if (regno <= PT_MAX_PUT_REG) { 223865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt ((unsigned long *)task->thread.regs)[regno] = data; 224865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt return 0; 225865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt } 226865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt return -EIO; 227865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt} 228865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 22944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrathstatic int gpr_get(struct task_struct *target, const struct user_regset *regset, 23044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath unsigned int pos, unsigned int count, 23144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath void *kbuf, void __user *ubuf) 23244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath{ 233a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf int i, ret; 23444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 23544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (target->thread.regs == NULL) 23644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath return -EIO; 23744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 238a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf if (!FULL_REGS(target->thread.regs)) { 239a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf /* We have a partial register set. Fill 14-31 with bogus values */ 240a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf for (i = 14; i < 32; i++) 241a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf target->thread.regs->gpr[i] = NV_REG_POISON; 242a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf } 24344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 24444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 24544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath target->thread.regs, 24644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 0, offsetof(struct pt_regs, msr)); 24744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) { 24844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath unsigned long msr = get_user_msr(target); 24944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr, 25044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath offsetof(struct pt_regs, msr), 25144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath offsetof(struct pt_regs, msr) + 25244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath sizeof(msr)); 25344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath } 25444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 25544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != 25644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath offsetof(struct pt_regs, msr) + sizeof(long)); 25744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 25844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) 25944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 26044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath &target->thread.regs->orig_gpr3, 26144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath offsetof(struct pt_regs, orig_gpr3), 26244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath sizeof(struct pt_regs)); 26344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) 26444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 26544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath sizeof(struct pt_regs), -1); 26644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 26744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath return ret; 26844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath} 26944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 27044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrathstatic int gpr_set(struct task_struct *target, const struct user_regset *regset, 27144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath unsigned int pos, unsigned int count, 27244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath const void *kbuf, const void __user *ubuf) 27344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath{ 27444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath unsigned long reg; 27544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath int ret; 27644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 27744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (target->thread.regs == NULL) 27844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath return -EIO; 27944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 28044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath CHECK_FULL_REGS(target->thread.regs); 28144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 28244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 28344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath target->thread.regs, 28444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 0, PT_MSR * sizeof(reg)); 28544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 28644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret && count > 0) { 28744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, 28844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath PT_MSR * sizeof(reg), 28944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath (PT_MSR + 1) * sizeof(reg)); 29044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) 29144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = set_user_msr(target, reg); 29244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath } 29344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 29444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != 29544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath offsetof(struct pt_regs, msr) + sizeof(long)); 29644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 29744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) 29844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 29944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath &target->thread.regs->orig_gpr3, 30044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath PT_ORIG_R3 * sizeof(reg), 30144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath (PT_MAX_PUT_REG + 1) * sizeof(reg)); 30244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 30344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret) 30444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyin_ignore( 30544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath &pos, &count, &kbuf, &ubuf, 30644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath (PT_MAX_PUT_REG + 1) * sizeof(reg), 30744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath PT_TRAP * sizeof(reg)); 30844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 30944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret && count > 0) { 31044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, 31144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath PT_TRAP * sizeof(reg), 31244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath (PT_TRAP + 1) * sizeof(reg)); 31344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) 31444dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = set_user_trap(target, reg); 31544dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath } 31644dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 31744dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath if (!ret) 31844dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath ret = user_regset_copyin_ignore( 31944dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath &pos, &count, &kbuf, &ubuf, 32044dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath (PT_TRAP + 1) * sizeof(reg), -1); 32144dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath 32244dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath return ret; 32344dd3f50d3848e332b49e83a142b39b960ec962eRoland McGrath} 324865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 325f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrathstatic int fpr_get(struct task_struct *target, const struct user_regset *regset, 326f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath unsigned int pos, unsigned int count, 327f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath void *kbuf, void __user *ubuf) 328f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath{ 329c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#ifdef CONFIG_VSX 330c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling double buf[33]; 331c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling int i; 332c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#endif 333f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath flush_fp_to_thread(target); 334f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath 335c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#ifdef CONFIG_VSX 336c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling /* copy to local buffer then write that out */ 337c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling for (i = 0; i < 32 ; i++) 338c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling buf[i] = target->thread.TS_FPR(i); 339c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling memcpy(&buf[32], &target->thread.fpscr, sizeof(double)); 340c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1); 341c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling 342c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#else 343f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) != 3449c75a31c3525a127f70b919856e32be3d8b03755Michael Neuling offsetof(struct thread_struct, TS_FPR(32))); 345f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath 346f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 347f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath &target->thread.fpr, 0, -1); 348c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#endif 349f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath} 350f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath 351f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrathstatic int fpr_set(struct task_struct *target, const struct user_regset *regset, 352f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath unsigned int pos, unsigned int count, 353f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath const void *kbuf, const void __user *ubuf) 354f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath{ 355c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#ifdef CONFIG_VSX 356c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling double buf[33]; 357c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling int i; 358c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#endif 359f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath flush_fp_to_thread(target); 360f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath 361c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#ifdef CONFIG_VSX 362c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling /* copy to local buffer then write that out */ 363c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1); 364c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling if (i) 365c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling return i; 366c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling for (i = 0; i < 32 ; i++) 367c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling target->thread.TS_FPR(i) = buf[i]; 368c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling memcpy(&target->thread.fpscr, &buf[32], sizeof(double)); 369c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling return 0; 370c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#else 371f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) != 3729c75a31c3525a127f70b919856e32be3d8b03755Michael Neuling offsetof(struct thread_struct, TS_FPR(32))); 373f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath 374f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 375f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath &target->thread.fpr, 0, -1); 376c6e6771b87d4e339d27f1383c8a808ae9b4ee5b8Michael Neuling#endif 377f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath} 378f65255e8d51ecbc6c9eef20d39e0377d19b658caRoland McGrath 379865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#ifdef CONFIG_ALTIVEC 380865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt/* 381865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. 382865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * The transfer totals 34 quadword. Quadwords 0-31 contain the 383865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * corresponding vector registers. Quadword 32 contains the vscr as the 384865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * last word (offset 12) within that quadword. Quadword 33 contains the 385865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * vrsave as the first word (offset 0) within the quadword. 386865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * 387865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * This definition of the VMX state is compatible with the current PPC32 388865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * ptrace interface. This allows signal handling and ptrace to use the 389865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * same structures. This also simplifies the implementation of a bi-arch 390865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * (combined (32- and 64-bit) gdb. 391865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt */ 392865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 3933caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrathstatic int vr_active(struct task_struct *target, 3943caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath const struct user_regset *regset) 3953caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath{ 3963caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath flush_altivec_to_thread(target); 3973caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath return target->thread.used_vr ? regset->n : 0; 3983caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath} 3993caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4003caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrathstatic int vr_get(struct task_struct *target, const struct user_regset *regset, 4013caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath unsigned int pos, unsigned int count, 4023caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath void *kbuf, void __user *ubuf) 4033caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath{ 4043caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath int ret; 4053caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4063caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath flush_altivec_to_thread(target); 4073caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4083caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath BUILD_BUG_ON(offsetof(struct thread_struct, vscr) != 4093caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath offsetof(struct thread_struct, vr[32])); 4103caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4113caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 4123caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath &target->thread.vr, 0, 4133caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 33 * sizeof(vector128)); 4143caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath if (!ret) { 4153caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath /* 4163caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath * Copy out only the low-order word of vrsave. 4173caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath */ 4183caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath union { 4193caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath elf_vrreg_t reg; 4203caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath u32 word; 4213caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath } vrsave; 4223caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath memset(&vrsave, 0, sizeof(vrsave)); 4233caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath vrsave.word = target->thread.vrsave; 4243caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave, 4253caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 33 * sizeof(vector128), -1); 4263caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath } 4273caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4283caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath return ret; 4293caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath} 4303caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4313caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrathstatic int vr_set(struct task_struct *target, const struct user_regset *regset, 4323caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath unsigned int pos, unsigned int count, 4333caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath const void *kbuf, const void __user *ubuf) 4343caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath{ 4353caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath int ret; 4363caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4373caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath flush_altivec_to_thread(target); 4383caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4393caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath BUILD_BUG_ON(offsetof(struct thread_struct, vscr) != 4403caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath offsetof(struct thread_struct, vr[32])); 4413caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4423caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 4433caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath &target->thread.vr, 0, 33 * sizeof(vector128)); 4443caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath if (!ret && count > 0) { 4453caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath /* 4463caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath * We use only the first word of vrsave. 4473caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath */ 4483caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath union { 4493caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath elf_vrreg_t reg; 4503caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath u32 word; 4513caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath } vrsave; 4523caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath memset(&vrsave, 0, sizeof(vrsave)); 4533caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath vrsave.word = target->thread.vrsave; 4543caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave, 4553caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 33 * sizeof(vector128), -1); 4563caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath if (!ret) 4573caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath target->thread.vrsave = vrsave.word; 4583caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath } 4593caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath 4603caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath return ret; 4613caf06c6e0656b25f694e3d414191cedcecf76ceRoland McGrath} 462865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#endif /* CONFIG_ALTIVEC */ 463865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 464ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#ifdef CONFIG_VSX 465ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling/* 466ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling * Currently to set and and get all the vsx state, you need to call 46725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * the fp and VMX calls as well. This only get/sets the lower 32 468ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling * 128bit VSX registers. 469ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling */ 470ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 471ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neulingstatic int vsr_active(struct task_struct *target, 472ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling const struct user_regset *regset) 473ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling{ 474ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling flush_vsx_to_thread(target); 475ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling return target->thread.used_vsr ? regset->n : 0; 476ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling} 477ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 478ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neulingstatic int vsr_get(struct task_struct *target, const struct user_regset *regset, 479ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling unsigned int pos, unsigned int count, 480ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling void *kbuf, void __user *ubuf) 481ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling{ 482f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling double buf[32]; 483f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling int ret, i; 484ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 485ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling flush_vsx_to_thread(target); 486ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 487f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling for (i = 0; i < 32 ; i++) 4887d2a175b9bf6e9422bebe95130a3c79a25ff4602Michael Neuling buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET]; 489ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 490f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling buf, 0, 32 * sizeof(double)); 491ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 492ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling return ret; 493ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling} 494ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 495ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neulingstatic int vsr_set(struct task_struct *target, const struct user_regset *regset, 496ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling unsigned int pos, unsigned int count, 497ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling const void *kbuf, const void __user *ubuf) 498ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling{ 499f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling double buf[32]; 500f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling int ret,i; 501ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 502ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling flush_vsx_to_thread(target); 503ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 504ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 505f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling buf, 0, 32 * sizeof(double)); 506f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling for (i = 0; i < 32 ; i++) 5077d2a175b9bf6e9422bebe95130a3c79a25ff4602Michael Neuling target->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; 508f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling 509ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 510ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling return ret; 511ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling} 512ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#endif /* CONFIG_VSX */ 513ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 514865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#ifdef CONFIG_SPE 515865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 516865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt/* 517865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * For get_evrregs/set_evrregs functions 'data' has the following layout: 518865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * 519865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * struct { 520865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * u32 evr[32]; 521865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * u64 acc; 522865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * u32 spefscr; 523865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt * } 524865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt */ 525865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 526a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrathstatic int evr_active(struct task_struct *target, 527a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath const struct user_regset *regset) 528865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt{ 529a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath flush_spe_to_thread(target); 530a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath return target->thread.used_spe ? regset->n : 0; 531a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath} 532865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 533a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrathstatic int evr_get(struct task_struct *target, const struct user_regset *regset, 534a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath unsigned int pos, unsigned int count, 535a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath void *kbuf, void __user *ubuf) 536a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath{ 537a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath int ret; 538865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 539a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath flush_spe_to_thread(target); 540865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 541a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 542a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath &target->thread.evr, 543a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 0, sizeof(target->thread.evr)); 544865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 545a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) != 546a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath offsetof(struct thread_struct, spefscr)); 547a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 548a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath if (!ret) 549a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 550a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath &target->thread.acc, 551a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath sizeof(target->thread.evr), -1); 552a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 553a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath return ret; 554a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath} 555a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 556a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrathstatic int evr_set(struct task_struct *target, const struct user_regset *regset, 557a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath unsigned int pos, unsigned int count, 558a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath const void *kbuf, const void __user *ubuf) 559a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath{ 560a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath int ret; 561a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 562a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath flush_spe_to_thread(target); 563a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 564a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 565a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath &target->thread.evr, 566a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 0, sizeof(target->thread.evr)); 567865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 568a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) != 569a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath offsetof(struct thread_struct, spefscr)); 570a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 571a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath if (!ret) 572a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 573a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath &target->thread.acc, 574a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath sizeof(target->thread.evr), -1); 575a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath 576a4e4b175b6028ebfb2217e0ca1fa0487dc73ccc4Roland McGrath return ret; 577865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt} 578865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#endif /* CONFIG_SPE */ 579865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 580865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 58180fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath/* 58280fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath * These are our native regset flavors. 58380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath */ 58480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrathenum powerpc_regset { 58580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath REGSET_GPR, 58680fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath REGSET_FPR, 58780fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#ifdef CONFIG_ALTIVEC 58880fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath REGSET_VMX, 58980fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#endif 590ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#ifdef CONFIG_VSX 591ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling REGSET_VSX, 592ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#endif 59380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#ifdef CONFIG_SPE 59480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath REGSET_SPE, 59580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#endif 59680fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath}; 59780fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath 59880fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrathstatic const struct user_regset native_regsets[] = { 59980fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath [REGSET_GPR] = { 60080fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 60180fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .size = sizeof(long), .align = sizeof(long), 60280fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .get = gpr_get, .set = gpr_set 60380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath }, 60480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath [REGSET_FPR] = { 60580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 60680fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .size = sizeof(double), .align = sizeof(double), 60780fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .get = fpr_get, .set = fpr_set 60880fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath }, 60980fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#ifdef CONFIG_ALTIVEC 61080fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath [REGSET_VMX] = { 61180fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .core_note_type = NT_PPC_VMX, .n = 34, 61280fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .size = sizeof(vector128), .align = sizeof(vector128), 61380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .active = vr_active, .get = vr_get, .set = vr_set 61480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath }, 61580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#endif 616ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#ifdef CONFIG_VSX 617ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling [REGSET_VSX] = { 618f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling .core_note_type = NT_PPC_VSX, .n = 32, 619f3e909c2750eb20536bacacc867dc9047b70546aMichael Neuling .size = sizeof(double), .align = sizeof(double), 620ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling .active = vsr_active, .get = vsr_get, .set = vsr_set 621ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling }, 622ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#endif 62380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#ifdef CONFIG_SPE 62480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath [REGSET_SPE] = { 62580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .n = 35, 62680fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .size = sizeof(u32), .align = sizeof(u32), 62780fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .active = evr_active, .get = evr_get, .set = evr_set 62880fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath }, 62980fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath#endif 63080fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath}; 63180fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath 63280fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrathstatic const struct user_regset_view user_ppc_native_view = { 63380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, 63480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets) 63580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath}; 63680fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath 637fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#ifdef CONFIG_PPC64 638fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#include <linux/compat.h> 639fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 640fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrathstatic int gpr32_get(struct task_struct *target, 641fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath const struct user_regset *regset, 642fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath unsigned int pos, unsigned int count, 643fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath void *kbuf, void __user *ubuf) 644fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath{ 645fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath const unsigned long *regs = &target->thread.regs->gpr[0]; 646fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath compat_ulong_t *k = kbuf; 647fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath compat_ulong_t __user *u = ubuf; 648fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath compat_ulong_t reg; 649a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf int i; 650fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 651fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (target->thread.regs == NULL) 652fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EIO; 653fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 654a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf if (!FULL_REGS(target->thread.regs)) { 655a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf /* We have a partial register set. Fill 14-31 with bogus values */ 656a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf for (i = 14; i < 32; i++) 657a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf target->thread.regs->gpr[i] = NV_REG_POISON; 658a71f5d5d279375205009a4be56a3cf6682921292Mike Wolf } 659fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 660fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath pos /= sizeof(reg); 661fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath count /= sizeof(reg); 662fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 663fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (kbuf) 664fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos < PT_MSR; --count) 665fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath *k++ = regs[pos++]; 666fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath else 667fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos < PT_MSR; --count) 668fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (__put_user((compat_ulong_t) regs[pos++], u++)) 669fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 670fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 671fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (count > 0 && pos == PT_MSR) { 672fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath reg = get_user_msr(target); 673fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (kbuf) 674fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath *k++ = reg; 675fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath else if (__put_user(reg, u++)) 676fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 677fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath ++pos; 678fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath --count; 679fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath } 680fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 681fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (kbuf) 682fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos < PT_REGS_COUNT; --count) 683fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath *k++ = regs[pos++]; 684fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath else 685fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos < PT_REGS_COUNT; --count) 686fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (__put_user((compat_ulong_t) regs[pos++], u++)) 687fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 688fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 689fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath kbuf = k; 690fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath ubuf = u; 691fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath pos *= sizeof(reg); 692fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath count *= sizeof(reg); 693fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 694fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath PT_REGS_COUNT * sizeof(reg), -1); 695fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath} 696fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 697fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrathstatic int gpr32_set(struct task_struct *target, 698fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath const struct user_regset *regset, 699fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath unsigned int pos, unsigned int count, 700fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath const void *kbuf, const void __user *ubuf) 701fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath{ 702fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath unsigned long *regs = &target->thread.regs->gpr[0]; 703fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath const compat_ulong_t *k = kbuf; 704fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath const compat_ulong_t __user *u = ubuf; 705fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath compat_ulong_t reg; 706fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 707fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (target->thread.regs == NULL) 708fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EIO; 709fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 710fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath CHECK_FULL_REGS(target->thread.regs); 711fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 712fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath pos /= sizeof(reg); 713fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath count /= sizeof(reg); 714fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 715fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (kbuf) 716fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos < PT_MSR; --count) 717fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath regs[pos++] = *k++; 718fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath else 719fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos < PT_MSR; --count) { 720fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (__get_user(reg, u++)) 721fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 722fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath regs[pos++] = reg; 723fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath } 724fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 725fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 726fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (count > 0 && pos == PT_MSR) { 727fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (kbuf) 728fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath reg = *k++; 729fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath else if (__get_user(reg, u++)) 730fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 731fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath set_user_msr(target, reg); 732fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath ++pos; 733fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath --count; 734fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath } 735fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 736c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath if (kbuf) { 737fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) 738fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath regs[pos++] = *k++; 739c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath for (; count > 0 && pos < PT_TRAP; --count, ++pos) 740c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath ++k; 741c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath } else { 742fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { 743fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (__get_user(reg, u++)) 744fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 745fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath regs[pos++] = reg; 746fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath } 747c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath for (; count > 0 && pos < PT_TRAP; --count, ++pos) 748c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath if (__get_user(reg, u++)) 749c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath return -EFAULT; 750c2372eb9bcafdd149b26987a8c25bbed92fd2775Roland McGrath } 751fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 752fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (count > 0 && pos == PT_TRAP) { 753fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (kbuf) 754fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath reg = *k++; 755fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath else if (__get_user(reg, u++)) 756fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return -EFAULT; 757fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath set_user_trap(target, reg); 758fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath ++pos; 759fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath --count; 760fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath } 761fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 762fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath kbuf = k; 763fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath ubuf = u; 764fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath pos *= sizeof(reg); 765fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath count *= sizeof(reg); 766fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 767fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath (PT_TRAP + 1) * sizeof(reg), -1); 768fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath} 769fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 770fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath/* 771fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath * These are the regset flavors matching the CONFIG_PPC32 native set. 772fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath */ 773fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrathstatic const struct user_regset compat_regsets[] = { 774fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath [REGSET_GPR] = { 775fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, 776fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), 777fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .get = gpr32_get, .set = gpr32_set 778fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath }, 779fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath [REGSET_FPR] = { 780fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, 781fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .size = sizeof(double), .align = sizeof(double), 782fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .get = fpr_get, .set = fpr_set 783fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath }, 784fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#ifdef CONFIG_ALTIVEC 785fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath [REGSET_VMX] = { 786fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .core_note_type = NT_PPC_VMX, .n = 34, 787fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .size = sizeof(vector128), .align = sizeof(vector128), 788fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .active = vr_active, .get = vr_get, .set = vr_set 789fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath }, 790fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#endif 791fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#ifdef CONFIG_SPE 792fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath [REGSET_SPE] = { 79324f1a849614ba1805e26a05da7cc8c6bd67490eaRoland McGrath .core_note_type = NT_PPC_SPE, .n = 35, 794fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .size = sizeof(u32), .align = sizeof(u32), 795fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .active = evr_active, .get = evr_get, .set = evr_set 796fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath }, 797fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#endif 798fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath}; 799fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 800fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrathstatic const struct user_regset_view user_ppc_compat_view = { 801fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI, 802fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets) 803fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath}; 804fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#endif /* CONFIG_PPC64 */ 805fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath 80680fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrathconst struct user_regset_view *task_user_regset_view(struct task_struct *task) 80780fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath{ 808fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#ifdef CONFIG_PPC64 809fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath if (test_tsk_thread_flag(task, TIF_32BIT)) 810fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath return &user_ppc_compat_view; 811fa8f5cb0c980e9fe3e04bc937fbd13417b52c046Roland McGrath#endif 81280fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath return &user_ppc_native_view; 81380fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath} 81480fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath 81580fdf4709497a276a826c9d8426ef1effc8f8e33Roland McGrath 8162a84b0d71973692b291f03a870c4d0d13f722d79Roland McGrathvoid user_enable_single_step(struct task_struct *task) 817865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt{ 818865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt struct pt_regs *regs = task->thread.regs; 819865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 820865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt if (regs != NULL) { 821172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 822ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath task->thread.dbcr0 &= ~DBCR0_BT; 823d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; 824865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt regs->msr |= MSR_DE; 825865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#else 826ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath regs->msr &= ~MSR_BE; 827865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt regs->msr |= MSR_SE; 828865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#endif 829865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt } 830865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt set_tsk_thread_flag(task, TIF_SINGLESTEP); 831865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt} 832865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 833ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrathvoid user_enable_block_step(struct task_struct *task) 834ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath{ 835ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath struct pt_regs *regs = task->thread.regs; 836ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath 837ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath if (regs != NULL) { 838172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 839ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath task->thread.dbcr0 &= ~DBCR0_IC; 840ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT; 841ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath regs->msr |= MSR_DE; 842ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath#else 843ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath regs->msr &= ~MSR_SE; 844ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath regs->msr |= MSR_BE; 845ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath#endif 846ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath } 847ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath set_tsk_thread_flag(task, TIF_SINGLESTEP); 848ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath} 849ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath 8502a84b0d71973692b291f03a870c4d0d13f722d79Roland McGrathvoid user_disable_single_step(struct task_struct *task) 851865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt{ 852865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt struct pt_regs *regs = task->thread.regs; 853865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 854865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt if (regs != NULL) { 855172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 8563bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 8573bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * The logic to disable single stepping should be as 8583bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * simple as turning off the Instruction Complete flag. 8593bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * And, after doing so, if all debug flags are off, turn 8603bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * off DBCR0(IDM) and MSR(DE) .... Torez 8613bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 8623bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dbcr0 &= ~DBCR0_IC; 8633bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 8643bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set. 8653bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 8663bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, 8673bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dbcr1)) { 8683bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 8693bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * All debug events were off..... 8703bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 8713bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dbcr0 &= ~DBCR0_IDM; 87228477fb1ed1a00c67b382ae8f37f35708e3bf5ddDave Kleikamp regs->msr &= ~MSR_DE; 87328477fb1ed1a00c67b382ae8f37f35708e3bf5ddDave Kleikamp } 874865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#else 875ec097c84dff17511f2693e6ef6c3064dfbf0a3afRoland McGrath regs->msr &= ~(MSR_SE | MSR_BE); 876865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt#endif 877865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt } 878865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt clear_tsk_thread_flag(task, TIF_SINGLESTEP); 879865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt} 880865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt 8815aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#ifdef CONFIG_HAVE_HW_BREAKPOINT 882a8b0ca17b80e92faab46ee7179ba9e99ccb61233Peter Zijlstravoid ptrace_triggered(struct perf_event *bp, 8835aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad struct perf_sample_data *data, struct pt_regs *regs) 8845aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad{ 8855aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad struct perf_event_attr attr; 8865aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad 8875aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad /* 8885aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad * Disable the breakpoint request here since ptrace has defined a 8895aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad * one-shot behaviour for breakpoint exceptions in PPC64. 8905aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad * The SIGTRAP signal is generated automatically for us in do_dabr(). 8915aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad * We don't have to do anything about that here 8925aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad */ 8935aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad attr = bp->attr; 8945aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad attr.disabled = true; 8955aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad modify_user_hw_breakpoint(bp, &attr); 8965aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad} 8975aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 8985aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad 899d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machadoint ptrace_set_debugreg(struct task_struct *task, unsigned long addr, 900abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt unsigned long data) 901abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt{ 9025aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#ifdef CONFIG_HAVE_HW_BREAKPOINT 9035aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad int ret; 9045aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad struct thread_struct *thread = &(task->thread); 9055aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad struct perf_event *bp; 9065aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad struct perf_event_attr attr; 9075aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 9085aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad 909d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). 910d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * For embedded processors we support one DAC and no IAC's at the 911d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * moment. 912d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado */ 913abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt if (addr > 0) 914abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt return -EINVAL; 915abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt 9162325f0a0c3d76bb515f3312ab2b16afdbffcc594Kumar Gala /* The bottom 3 bits in dabr are flags */ 917abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt if ((data & ~0x7UL) >= TASK_SIZE) 918abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt return -EIO; 919abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt 920172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#ifndef CONFIG_PPC_ADV_DEBUG_REGS 921d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. 922d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * It was assumed, on previous implementations, that 3 bits were 923d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * passed together with the data address, fitting the design of the 924d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * DABR register, as follows: 925d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * 926d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * bit 0: Read flag 927d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * bit 1: Write flag 928d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * bit 2: Breakpoint translation 929d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * 930d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * Thus, we use them here as so. 931d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado */ 932d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado 933d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* Ensure breakpoint translation bit is set */ 934abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt if (data && !(data & DABR_TRANSLATION)) 935abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt return -EIO; 9365aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#ifdef CONFIG_HAVE_HW_BREAKPOINT 937925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker if (ptrace_get_breakpoints(task) < 0) 938925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker return -ESRCH; 939925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker 9405aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad bp = thread->ptrace_bps[0]; 9415aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) { 9425aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad if (bp) { 9435aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad unregister_hw_breakpoint(bp); 9445aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad thread->ptrace_bps[0] = NULL; 9455aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad } 946925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker ptrace_put_breakpoints(task); 9475aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad return 0; 9485aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad } 9495aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad if (bp) { 9505aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad attr = bp->attr; 9515aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN; 9525aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad arch_bp_generic_fields(data & 9535aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad (DABR_DATA_WRITE | DABR_DATA_READ), 9545aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad &attr.bp_type); 9555aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad ret = modify_user_hw_breakpoint(bp, &attr); 956925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker if (ret) { 957925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker ptrace_put_breakpoints(task); 9585aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad return ret; 959925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker } 9605aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad thread->ptrace_bps[0] = bp; 961925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker ptrace_put_breakpoints(task); 9625aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad thread->dabr = data; 9635aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad return 0; 9645aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad } 9655aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad 9665aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad /* Create a new breakpoint request if one doesn't exist already */ 9675aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad hw_breakpoint_init(&attr); 9685aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN; 9695aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad arch_bp_generic_fields(data & (DABR_DATA_WRITE | DABR_DATA_READ), 9705aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad &attr.bp_type); 9715aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad 9725aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, 9734dc0da86967d5463708631d02a70cfed5b104884Avi Kivity ptrace_triggered, NULL, task); 9745aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad if (IS_ERR(bp)) { 9755aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad thread->ptrace_bps[0] = NULL; 976925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker ptrace_put_breakpoints(task); 9775aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad return PTR_ERR(bp); 9785aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad } 9795aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad 980925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker ptrace_put_breakpoints(task); 981925f83c085e1bb08435556c5b4844a60de002e31Frederic Weisbecker 9825aae8a53708025d4e718f0d2e7c2f766779ddc71K.Prasad#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 983abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt 984d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* Move contents to the DABR register */ 985abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt task->thread.dabr = data; 986172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#else /* CONFIG_PPC_ADV_DEBUG_REGS */ 987d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* As described above, it was assumed 3 bits were passed with the data 988d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * address, but we will assume only the mode bits will be passed 989d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado * as to not cause alignment restrictions for DAC-based processors. 990d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado */ 991d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado 992d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* DAC's hold the whole address without any mode flags */ 9933bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dac1 = data & ~0x3UL; 9943bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 9953bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (task->thread.dac1 == 0) { 9963bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W); 9973bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, 9983bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dbcr1)) { 9993bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.regs->msr &= ~MSR_DE; 10003bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dbcr0 &= ~DBCR0_IDM; 10013bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 1002d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado return 0; 1003d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado } 1004d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado 1005d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* Read or Write bits must be set */ 1006d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado 1007d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado if (!(data & 0x3UL)) 1008d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado return -EINVAL; 1009d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado 1010d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 1011d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado register */ 10123bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp task->thread.dbcr0 |= DBCR0_IDM; 1013d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado 1014d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado /* Check for write and read flags and set DBCR0 1015d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado accordingly */ 10163bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(task) &= ~(DBCR_DAC1R|DBCR_DAC1W); 1017d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado if (data & 0x1UL) 10183bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(task) |= DBCR_DAC1R; 1019d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado if (data & 0x2UL) 10203bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(task) |= DBCR_DAC1W; 1021d6a61bfc06d6f2248f3e75f208d64e794082013cLuis Machado task->thread.regs->msr |= MSR_DE; 1022172ae2e7f8ff9053905a36672453a6d2ff95b182Dave Kleikamp#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 1023abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt return 0; 1024abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt} 1025abd0650541604d6c028bcbf5002e4a68aaf56e90Benjamin Herrenschmidt 1026865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt/* 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called by kernel/ptrace.c when detaching.. 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make sure single step bits etc are not set. 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ptrace_disable(struct task_struct *child) 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure the single step bit is not set. */ 10342a84b0d71973692b291f03a870c4d0d13f722d79Roland McGrath user_disable_single_step(child); 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10373bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 10383bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikampstatic long set_intruction_bp(struct task_struct *child, 10393bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp struct ppc_hw_breakpoint *bp_info) 10403bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp{ 10413bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int slot; 10423bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int slot1_in_use = ((child->thread.dbcr0 & DBCR0_IAC1) != 0); 10433bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int slot2_in_use = ((child->thread.dbcr0 & DBCR0_IAC2) != 0); 10443bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int slot3_in_use = ((child->thread.dbcr0 & DBCR0_IAC3) != 0); 10453bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int slot4_in_use = ((child->thread.dbcr0 & DBCR0_IAC4) != 0); 10463bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 10473bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (dbcr_iac_range(child) & DBCR_IAC12MODE) 10483bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot2_in_use = 1; 10493bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (dbcr_iac_range(child) & DBCR_IAC34MODE) 10503bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot4_in_use = 1; 10513bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 10523bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr >= TASK_SIZE) 10533bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EIO; 10543bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 10553bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) { 10563bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 10573bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* Make sure range is valid. */ 10583bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr2 >= TASK_SIZE) 10593bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EIO; 10603bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 10613bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* We need a pair of IAC regsisters */ 10623bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if ((!slot1_in_use) && (!slot2_in_use)) { 10633bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 1; 10643bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac1 = bp_info->addr; 10653bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac2 = bp_info->addr2; 10663bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IAC1; 10673bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr_mode == 10683bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) 10693bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_iac_range(child) |= DBCR_IAC12X; 10703bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp else 10713bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_iac_range(child) |= DBCR_IAC12I; 10723bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_IACS > 2 10733bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else if ((!slot3_in_use) && (!slot4_in_use)) { 10743bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 3; 10753bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac3 = bp_info->addr; 10763bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac4 = bp_info->addr2; 10773bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IAC3; 10783bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr_mode == 10793bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) 10803bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_iac_range(child) |= DBCR_IAC34X; 10813bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp else 10823bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_iac_range(child) |= DBCR_IAC34I; 10833bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 10843bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else 10853bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOSPC; 10863bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else { 10873bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* We only need one. If possible leave a pair free in 10883bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * case a range is needed later 10893bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 10903bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (!slot1_in_use) { 10913bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 10923bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * Don't use iac1 if iac1-iac2 are free and either 10933bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * iac3 or iac4 (but not both) are free 10943bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 10953bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (slot2_in_use || (slot3_in_use == slot4_in_use)) { 10963bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 1; 10973bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac1 = bp_info->addr; 10983bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IAC1; 10993bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp goto out; 11003bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 11013bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 11023bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (!slot2_in_use) { 11033bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 2; 11043bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac2 = bp_info->addr; 11053bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IAC2; 11063bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_IACS > 2 11073bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else if (!slot3_in_use) { 11083bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 3; 11093bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac3 = bp_info->addr; 11103bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IAC3; 11113bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else if (!slot4_in_use) { 11123bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 4; 11133bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac4 = bp_info->addr; 11143bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IAC4; 11153bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 11163bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else 11173bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOSPC; 11183bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 11193bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikampout: 11203bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IDM; 11213bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.regs->msr |= MSR_DE; 11223bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11233bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return slot; 11243bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp} 11253bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11263bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikampstatic int del_instruction_bp(struct task_struct *child, int slot) 11273bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp{ 11283bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp switch (slot) { 11293bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp case 1: 113030124d11097e371e42052144d8a3f4a78d26e09fDave Kleikamp if ((child->thread.dbcr0 & DBCR0_IAC1) == 0) 11313bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOENT; 11323bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11333bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (dbcr_iac_range(child) & DBCR_IAC12MODE) { 11343bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* address range - clear slots 1 & 2 */ 11353bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac2 = 0; 11363bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_iac_range(child) &= ~DBCR_IAC12MODE; 11373bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 11383bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac1 = 0; 11393bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 &= ~DBCR0_IAC1; 11403bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp break; 11413bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp case 2: 114230124d11097e371e42052144d8a3f4a78d26e09fDave Kleikamp if ((child->thread.dbcr0 & DBCR0_IAC2) == 0) 11433bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOENT; 11443bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11453bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (dbcr_iac_range(child) & DBCR_IAC12MODE) 11463bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* used in a range */ 11473bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 11483bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac2 = 0; 11493bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 &= ~DBCR0_IAC2; 11503bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp break; 11513bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_IACS > 2 11523bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp case 3: 115330124d11097e371e42052144d8a3f4a78d26e09fDave Kleikamp if ((child->thread.dbcr0 & DBCR0_IAC3) == 0) 11543bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOENT; 11553bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11563bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (dbcr_iac_range(child) & DBCR_IAC34MODE) { 11573bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* address range - clear slots 3 & 4 */ 11583bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac4 = 0; 11593bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_iac_range(child) &= ~DBCR_IAC34MODE; 11603bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 11613bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac3 = 0; 11623bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 &= ~DBCR0_IAC3; 11633bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp break; 11643bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp case 4: 116530124d11097e371e42052144d8a3f4a78d26e09fDave Kleikamp if ((child->thread.dbcr0 & DBCR0_IAC4) == 0) 11663bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOENT; 11673bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11683bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (dbcr_iac_range(child) & DBCR_IAC34MODE) 11693bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* Used in a range */ 11703bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 11713bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.iac4 = 0; 11723bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 &= ~DBCR0_IAC4; 11733bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp break; 11743bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 11753bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp default: 11763bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 11773bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 11783bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return 0; 11793bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp} 11803bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11813bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikampstatic int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) 11823bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp{ 11833bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int byte_enable = 11843bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (bp_info->condition_mode >> PPC_BREAKPOINT_CONDITION_BE_SHIFT) 11853bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp & 0xf; 11863bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int condition_mode = 11873bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp bp_info->condition_mode & PPC_BREAKPOINT_CONDITION_MODE; 11883bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int slot; 11893bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11903bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (byte_enable && (condition_mode == 0)) 11913bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 11923bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11933bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr >= TASK_SIZE) 11943bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EIO; 11953bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 11963bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) { 11973bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 1; 11983bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 11993bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(child) |= DBCR_DAC1R; 12003bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 12013bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(child) |= DBCR_DAC1W; 12023bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac1 = (unsigned long)bp_info->addr; 12033bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_DVCS > 0 12043bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (byte_enable) { 12053bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dvc1 = 12063bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (unsigned long)bp_info->condition_value; 12073bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 |= 12083bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp ((byte_enable << DBCR2_DVC1BE_SHIFT) | 12093bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (condition_mode << DBCR2_DVC1M_SHIFT)); 12103bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 12113bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12123bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE 12133bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else if (child->thread.dbcr2 & DBCR2_DAC12MODE) { 12143bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* Both dac1 and dac2 are part of a range */ 12153bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOSPC; 12163bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12173bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) { 12183bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp slot = 2; 12193bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 12203bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(child) |= DBCR_DAC2R; 12213bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 12223bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(child) |= DBCR_DAC2W; 12233bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac2 = (unsigned long)bp_info->addr; 12243bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_DVCS > 0 12253bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (byte_enable) { 12263bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dvc2 = 12273bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (unsigned long)bp_info->condition_value; 12283bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 |= 12293bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp ((byte_enable << DBCR2_DVC2BE_SHIFT) | 12303bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (condition_mode << DBCR2_DVC2M_SHIFT)); 12313bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 12323bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12333bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else 12343bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOSPC; 12353bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= DBCR0_IDM; 12363bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.regs->msr |= MSR_DE; 12373bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12383bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return slot + 4; 12393bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp} 12403bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12413bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikampstatic int del_dac(struct task_struct *child, int slot) 12423bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp{ 12433bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (slot == 1) { 124430124d11097e371e42052144d8a3f4a78d26e09fDave Kleikamp if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) 12453bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOENT; 12463bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12473bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac1 = 0; 12483bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W); 12493bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE 12503bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (child->thread.dbcr2 & DBCR2_DAC12MODE) { 12513bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac2 = 0; 12523bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 &= ~DBCR2_DAC12MODE; 12533bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 12543bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE); 12553bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12563bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_DVCS > 0 12573bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dvc1 = 0; 12583bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12593bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else if (slot == 2) { 126030124d11097e371e42052144d8a3f4a78d26e09fDave Kleikamp if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) 12613bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOENT; 12623bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12633bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE 12643bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (child->thread.dbcr2 & DBCR2_DAC12MODE) 12653bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* Part of a range */ 12663bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 12673bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE); 12683bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12693bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_DVCS > 0 12703bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dvc2 = 0; 12713bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 12723bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac2 = 0; 12733bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W); 12743bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else 12753bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 12763bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12773bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return 0; 12783bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp} 12793bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 12803bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12813bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE 12823bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikampstatic int set_dac_range(struct task_struct *child, 12833bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp struct ppc_hw_breakpoint *bp_info) 12843bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp{ 12853bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int mode = bp_info->addr_mode & PPC_BREAKPOINT_MODE_MASK; 12863bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12873bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* We don't allow range watchpoints to be used with DVC */ 12883bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->condition_mode) 12893bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 12903bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 12913bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 12923bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * Best effort to verify the address range. The user/supervisor bits 12933bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * prevent trapping in kernel space, but let's fail on an obvious bad 12943bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * range. The simple test on the mask is not fool-proof, and any 12953bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * exclusive range will spill over into kernel space. 12963bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 12973bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr >= TASK_SIZE) 12983bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EIO; 12993bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (mode == PPC_BREAKPOINT_MODE_MASK) { 13003bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 13013bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * dac2 is a bitmask. Don't allow a mask that makes a 13023bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * kernel space address from a valid dac1 value 13033bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 13043bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (~((unsigned long)bp_info->addr2) >= TASK_SIZE) 13053bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EIO; 13063bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } else { 13073bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 13083bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * For range breakpoints, addr2 must also be a valid address 13093bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 13103bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr2 >= TASK_SIZE) 13113bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EIO; 13123bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 13133bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 13143bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (child->thread.dbcr0 & 13153bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)) 13163bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOSPC; 13173bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 13183bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 13193bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM); 13203bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 13213bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM); 13223bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac1 = bp_info->addr; 13233bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dac2 = bp_info->addr2; 13243bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) 13253bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 |= DBCR2_DAC12M; 13263bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) 13273bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 |= DBCR2_DAC12MX; 13283bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp else /* PPC_BREAKPOINT_MODE_MASK */ 13293bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr2 |= DBCR2_DAC12MM; 13303bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.regs->msr |= MSR_DE; 13313bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 13323bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return 5; 13333bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp} 13343bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */ 13353bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 13363162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikampstatic long ppc_set_hwdebug(struct task_struct *child, 13373162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp struct ppc_hw_breakpoint *bp_info) 13383162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp{ 13394dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab#ifndef CONFIG_PPC_ADV_DEBUG_REGS 13404dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab unsigned long dabr; 13414dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab#endif 13424dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab 13433bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->version != 1) 13443bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -ENOTSUPP; 13453bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 13463bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp /* 13473bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * Check for invalid flags and combinations 13483bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp */ 13493bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if ((bp_info->trigger_type == 0) || 13503bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (bp_info->trigger_type & ~(PPC_BREAKPOINT_TRIGGER_EXECUTE | 13513bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_BREAKPOINT_TRIGGER_RW)) || 13523bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (bp_info->addr_mode & ~PPC_BREAKPOINT_MODE_MASK) || 13533bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (bp_info->condition_mode & 13543bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp ~(PPC_BREAKPOINT_CONDITION_MODE | 13553bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_BREAKPOINT_CONDITION_BE_ALL))) 13563bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 13573bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#if CONFIG_PPC_ADV_DEBUG_DVCS == 0 13583bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) 13593bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 13603bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 13613bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 13623bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) { 13633bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if ((bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE) || 13643bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)) 13653bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 13663bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return set_intruction_bp(child, bp_info); 13673bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 13683bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT) 13693bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return set_dac(child, bp_info); 13703bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 13713bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE 13723bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return set_dac_range(child, bp_info); 13733bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#else 13743bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return -EINVAL; 13753bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 13763bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#else /* !CONFIG_PPC_ADV_DEBUG_DVCS */ 13773162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp /* 13783bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp * We only support one data breakpoint 13793162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp */ 13804dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab if ((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0 || 13814dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab (bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0 || 13824dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT || 13834dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) 13843162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -EINVAL; 13853162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 13863162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp if (child->thread.dabr) 13873162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -ENOSPC; 13883162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 13893162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp if ((unsigned long)bp_info->addr >= TASK_SIZE) 13903162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -EIO; 13913162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 13924dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab dabr = (unsigned long)bp_info->addr & ~7UL; 13934dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab dabr |= DABR_TRANSLATION; 13944dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) 13954dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab dabr |= DABR_DATA_READ; 13964dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) 13974dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab dabr |= DABR_DATA_WRITE; 13984dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab 13994dfbf290aeb9d63a058d9d8237203b0b72bfbbe3Andreas Schwab child->thread.dabr = dabr; 14003bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 14013162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return 1; 14023bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ 14033162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp} 14043162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 14053162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikampstatic long ppc_del_hwdebug(struct task_struct *child, long addr, long data) 14063162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp{ 14073bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 14083bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp int rc; 14093bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 14103bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (data <= 4) 14113bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp rc = del_instruction_bp(child, (int)data); 14123bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp else 14133bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp rc = del_dac(child, (int)data - 4); 14143bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 14153bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (!rc) { 14163bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp if (!DBCR_ACTIVE_EVENTS(child->thread.dbcr0, 14173bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr1)) { 14183bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.dbcr0 &= ~DBCR0_IDM; 14193bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp child->thread.regs->msr &= ~MSR_DE; 14203bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 14213bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp } 14223bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp return rc; 14233bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#else 14243162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp if (data != 1) 14253162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -EINVAL; 14263162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp if (child->thread.dabr == 0) 14273162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -ENOENT; 14283162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 14293162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp child->thread.dabr = 0; 14303bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp 14313162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return 0; 14323bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 14333162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp} 14343162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 1435e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt/* 1436e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, 1437e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt * we mark them as obsolete now, they will be removed in a future version 1438e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt */ 14399b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kimstatic long arch_ptrace_old(struct task_struct *child, long request, 14409b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim unsigned long addr, unsigned long data) 1441e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt{ 1442f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim void __user *datavp = (void __user *) data; 1443f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim 1444c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath switch (request) { 1445c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ 1446c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_to_user(child, &user_ppc_native_view, 1447c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_GPR, 0, 32 * sizeof(long), 1448f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1449c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 1450c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ 1451c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_from_user(child, &user_ppc_native_view, 1452c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_GPR, 0, 32 * sizeof(long), 1453f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1454c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 1455c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ 1456c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_to_user(child, &user_ppc_native_view, 1457c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_FPR, 0, 32 * sizeof(double), 1458f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1459c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 1460c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */ 1461c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_from_user(child, &user_ppc_native_view, 1462c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_FPR, 0, 32 * sizeof(double), 1463f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1464e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt } 1465e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt 1466c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return -EPERM; 1467e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt} 1468e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt 14699b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kimlong arch_ptrace(struct task_struct *child, long request, 14709b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim unsigned long addr, unsigned long data) 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = -EPERM; 1473f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim void __user *datavp = (void __user *) data; 1474f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim unsigned long __user *datalp = datavp; 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (request) { 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read the word at location addr in the USER area. */ 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_PEEKUSR: { 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long index, tmp; 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* convert to index and check */ 1483e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#ifdef CONFIG_PPC32 14849b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim index = addr >> 2; 1485e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell if ((addr & 3) || (index > PT_FPSCR) 1486e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell || (child->thread.regs == NULL)) 1487e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#else 14889b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim index = addr >> 3; 1489e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell if ((addr & 7) || (index > PT_FPSCR)) 1490e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#endif 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHECK_FULL_REGS(child->thread.regs); 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (index < PT_FPR0) { 1495865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt tmp = ptrace_get_reg(child, (int) index); 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1497e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt unsigned int fpidx = index - PT_FPR0; 1498e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt 1499e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell flush_fp_to_thread(child); 1500e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt if (fpidx < (PT_FPSCR - PT_FPR0)) 1501e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt tmp = ((unsigned long *)child->thread.fpr) 1502e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt [fpidx * TS_FPRWIDTH]; 1503e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt else 1504e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt tmp = child->thread.fpscr.val; 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1506f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim ret = put_user(tmp, datalp); 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* write the word at location addr in the USER area */ 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_POKEUSR: { 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long index; 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EIO; 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* convert to index and check */ 1516e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#ifdef CONFIG_PPC32 15179b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim index = addr >> 2; 1518e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell if ((addr & 3) || (index > PT_FPSCR) 1519e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell || (child->thread.regs == NULL)) 1520e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#else 15219b05a69e0534ec70bc94921936ffa05b330507cbNamhyung Kim index = addr >> 3; 1522e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell if ((addr & 7) || (index > PT_FPSCR)) 1523e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#endif 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHECK_FULL_REGS(child->thread.regs); 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (index < PT_FPR0) { 1528865418d8e78b9c11c964157740b2596d6ffe9dfaBenjamin Herrenschmidt ret = ptrace_put_reg(child, index, data); 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1530e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt unsigned int fpidx = index - PT_FPR0; 1531e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt 1532e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell flush_fp_to_thread(child); 1533e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt if (fpidx < (PT_FPSCR - PT_FPR0)) 1534e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt ((unsigned long *)child->thread.fpr) 1535e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt [fpidx * TS_FPRWIDTH] = data; 1536e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt else 1537e69b742a6793dc5bf16f6eedca534d4bc10d68b2Benjamin Herrenschmidt child->thread.fpscr.val = data; 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15433162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp case PPC_PTRACE_GETHWDBGINFO: { 15443162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp struct ppc_debug_info dbginfo; 15453162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 15463162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.version = 1; 15473bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 15483bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.num_instruction_bps = CONFIG_PPC_ADV_DEBUG_IACS; 15493bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.num_data_bps = CONFIG_PPC_ADV_DEBUG_DACS; 15503bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.num_condition_regs = CONFIG_PPC_ADV_DEBUG_DVCS; 15513bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.data_bp_alignment = 4; 15523bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.sizeof_condition = 4; 15533bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.features = PPC_DEBUG_FEATURE_INSN_BP_RANGE | 15543bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_DEBUG_FEATURE_INSN_BP_MASK; 15553bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE 15563bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp dbginfo.features |= 15573bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_DEBUG_FEATURE_DATA_BP_RANGE | 15583bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp PPC_DEBUG_FEATURE_DATA_BP_MASK; 15593bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 15603bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#else /* !CONFIG_PPC_ADV_DEBUG_REGS */ 15613162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.num_instruction_bps = 0; 15623162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.num_data_bps = 1; 15633162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.num_condition_regs = 0; 15643162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp#ifdef CONFIG_PPC64 15653162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.data_bp_alignment = 8; 15663162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp#else 15673162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.data_bp_alignment = 4; 15683162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp#endif 15693162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.sizeof_condition = 0; 15703162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp dbginfo.features = 0; 15713bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 15723162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 1573f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim if (!access_ok(VERIFY_WRITE, datavp, 15743162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp sizeof(struct ppc_debug_info))) 15753162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -EFAULT; 1576f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim ret = __copy_to_user(datavp, &dbginfo, 1577f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim sizeof(struct ppc_debug_info)) ? 15783162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp -EFAULT : 0; 15793162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp break; 15803162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp } 15813162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 15823162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp case PPC_PTRACE_SETHWDEBUG: { 15833162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp struct ppc_hw_breakpoint bp_info; 15843162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 1585f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim if (!access_ok(VERIFY_READ, datavp, 15863162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp sizeof(struct ppc_hw_breakpoint))) 15873162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp return -EFAULT; 1588f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim ret = __copy_from_user(&bp_info, datavp, 15893162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp sizeof(struct ppc_hw_breakpoint)) ? 15903162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp -EFAULT : 0; 15913162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp if (!ret) 15923162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp ret = ppc_set_hwdebug(child, &bp_info); 15933162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp break; 15943162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp } 15953162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 15963162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp case PPC_PTRACE_DELHWDEBUG: { 15973162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp ret = ppc_del_hwdebug(child, addr, data); 15983162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp break; 15993162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp } 16003162d92dfb79a0b5fc03380b8819fa5f870ebf1eDave Kleikamp 1601e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell case PTRACE_GET_DEBUGREG: { 1602e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell ret = -EINVAL; 1603e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell /* We only support one DABR and no IABRS at the moment */ 1604e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell if (addr > 0) 1605e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell break; 16063bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#ifdef CONFIG_PPC_ADV_DEBUG_REGS 1607f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim ret = put_user(child->thread.dac1, datalp); 16083bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#else 1609f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim ret = put_user(child->thread.dabr, datalp); 16103bffb6529cf10d48a97ac0d6d789986894c25c37Dave Kleikamp#endif 1611e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell break; 1612e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell } 1613e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell 1614e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell case PTRACE_SET_DEBUGREG: 1615e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell ret = ptrace_set_debugreg(child, addr, data); 1616e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell break; 1617e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell 1618e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt#ifdef CONFIG_PPC64 1619e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt case PTRACE_GETREGS64: 1620e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt#endif 1621c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PTRACE_GETREGS: /* Get all pt_regs from the child. */ 1622c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_to_user(child, &user_ppc_native_view, 1623c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_GPR, 1624c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 0, sizeof(struct pt_regs), 1625f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1626e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell 1627e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt#ifdef CONFIG_PPC64 1628e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt case PTRACE_SETREGS64: 1629e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt#endif 1630c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PTRACE_SETREGS: /* Set all gp regs in the child. */ 1631c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_from_user(child, &user_ppc_native_view, 1632c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_GPR, 1633c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 0, sizeof(struct pt_regs), 1634f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1635c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 1636c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ 1637c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_to_user(child, &user_ppc_native_view, 1638c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_FPR, 1639c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 0, sizeof(elf_fpregset_t), 1640f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1641c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 1642c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */ 1643c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_from_user(child, &user_ppc_native_view, 1644c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_FPR, 1645c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 0, sizeof(elf_fpregset_t), 1646f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1647e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ALTIVEC 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETVRREGS: 1650c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_to_user(child, &user_ppc_native_view, 1651c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_VMX, 1652c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 0, (33 * sizeof(vector128) + 1653c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath sizeof(u32)), 1654f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETVRREGS: 1657c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_from_user(child, &user_ppc_native_view, 1658c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_VMX, 1659c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath 0, (33 * sizeof(vector128) + 1660c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath sizeof(u32)), 1661f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1663ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#ifdef CONFIG_VSX 1664ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling case PTRACE_GETVSRREGS: 1665ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling return copy_regset_to_user(child, &user_ppc_native_view, 1666ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling REGSET_VSX, 16671ac42ef844d7c0996f15c6f94f463ac94cb80818Michael Neuling 0, 32 * sizeof(double), 1668f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1669ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling 1670ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling case PTRACE_SETVSRREGS: 1671ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling return copy_regset_from_user(child, &user_ppc_native_view, 1672ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling REGSET_VSX, 16731ac42ef844d7c0996f15c6f94f463ac94cb80818Michael Neuling 0, 32 * sizeof(double), 1674f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 1675ce48b2100785e5ca629fb3aa8e3b50aca808f692Michael Neuling#endif 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SPE 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_GETEVRREGS: 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get the child spe register state. */ 1679c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_to_user(child, &user_ppc_native_view, 1680c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_SPE, 0, 35 * sizeof(u32), 1681f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PTRACE_SETEVRREGS: 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set the child spe register state. */ 1685c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath return copy_regset_from_user(child, &user_ppc_native_view, 1686c391cd0093a2c86a6d1bc256198caad29fff0f60Roland McGrath REGSET_SPE, 0, 35 * sizeof(u32), 1687f68d2048206389603d646b06e3cc16f1bbc3ff88Namhyung Kim datavp); 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1690e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt /* Old reverse args ptrace callss */ 1691e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ 1692e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ 1693e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ 1694e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */ 1695e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt ret = arch_ptrace_old(child, request, addr, data); 1696e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt break; 1697e17666ba48f78ff10162d7448e7c92d668d8faf6Benjamin Herrenschmidt 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ptrace_request(child, request, addr, data); 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17054f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath/* 17064f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath * We must return the syscall number to actually look up in the table. 17074f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath * This can be -1L to skip running any syscall at all. 17084f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath */ 17094f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrathlong do_syscall_trace_enter(struct pt_regs *regs) 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17114f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath long ret = 0; 1712ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse 1713e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell secure_computing(regs->gpr[0]); 1714e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell 17154f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath if (test_thread_flag(TIF_SYSCALL_TRACE) && 17164f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath tracehook_report_syscall_entry(regs)) 17174f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath /* 17184f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath * Tracing decided this syscall should not happen. 17194f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath * We'll return a bogus call number to get an ENOSYS 17204f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath * error, but leave the original number in regs->gpr[0]. 17214f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath */ 17224f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath ret = -1L; 1723ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse 172402424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 172502424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie trace_sys_enter(regs, regs->gpr[0]); 172602424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie 1727cfcd1705b61ecce1ab102b9593cf733fef314a19David Woodhouse#ifdef CONFIG_PPC64 1728b05d8447e7821695bc2fa3359431f7a664232743Eric Paris if (!is_32bit_task()) 1729b05d8447e7821695bc2fa3359431f7a664232743Eric Paris audit_syscall_entry(AUDIT_ARCH_PPC64, 1730b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[0], 1731b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[3], regs->gpr[4], 1732b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[5], regs->gpr[6]); 1733b05d8447e7821695bc2fa3359431f7a664232743Eric Paris else 1734e8a30302abc42a0c537b9326883523da9963deb6Stephen Rothwell#endif 1735b05d8447e7821695bc2fa3359431f7a664232743Eric Paris audit_syscall_entry(AUDIT_ARCH_PPC, 1736b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[0], 1737b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[3] & 0xffffffff, 1738b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[4] & 0xffffffff, 1739b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[5] & 0xffffffff, 1740b05d8447e7821695bc2fa3359431f7a664232743Eric Paris regs->gpr[6] & 0xffffffff); 17414f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath 17424f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath return ret ?: regs->gpr[0]; 1743ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse} 1744ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse 1745ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhousevoid do_syscall_trace_leave(struct pt_regs *regs) 1746ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse{ 17474f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath int step; 17484f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath 1749d7e7528bcd456f5c36ad4a202ccfb43c5aa98bc4Eric Paris audit_syscall_exit(regs); 1750ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse 175102424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 175202424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie trace_sys_exit(regs, regs->result); 175302424d8966d803e33cbe51469be56b5d177b4a37Ian Munsie 17544f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath step = test_thread_flag(TIF_SINGLESTEP); 17554f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 17564f72c4279eab1e5f3ed1ac4e55d4527617582392Roland McGrath tracehook_report_syscall_exit(regs, step); 1757ea9c102cb0a7969df5733d34f26e0b12c8a3c889David Woodhouse} 1758