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, &reg,
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, &reg,
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