[POWERPC] ptrace cleanups
[safe/jmp/linux-2.6] / arch / powerpc / kernel / ptrace-common.h
1 /*
2  *    Copyright (c) 2002 Stephen Rothwell, IBM Coproration
3  *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
4  *    Extracted from ptrace.c and ptrace32.c
5  *
6  * This file is subject to the terms and conditions of the GNU General
7  * Public License.  See the file README.legal in the main directory of
8  * this archive for more details.
9  */
10
11 #ifndef _POWERPC_PTRACE_COMMON_H
12 #define _POWERPC_PTRACE_COMMON_H
13
14 /*
15  * Get contents of register REGNO in task TASK.
16  */
17 static inline unsigned long get_reg(struct task_struct *task, int regno)
18 {
19         unsigned long tmp = 0;
20
21         if (task->thread.regs == NULL)
22                 return -EIO;
23
24         if (regno == PT_MSR) {
25                 tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
26                 return PT_MUNGE_MSR(tmp, task);
27         }
28
29         if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
30                 return ((unsigned long *)task->thread.regs)[regno];
31
32         return -EIO;
33 }
34
35 /*
36  * Write contents of register REGNO in task TASK.
37  */
38 static inline int put_reg(struct task_struct *task, int regno,
39                           unsigned long data)
40 {
41         if (task->thread.regs == NULL)
42                 return -EIO;
43
44         if (regno <= PT_MAX_PUT_REG) {
45                 if (regno == PT_MSR)
46                         data = (data & MSR_DEBUGCHANGE)
47                                 | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
48                 ((unsigned long *)task->thread.regs)[regno] = data;
49                 return 0;
50         }
51         return -EIO;
52 }
53
54
55 #ifdef CONFIG_ALTIVEC
56 /*
57  * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
58  * The transfer totals 34 quadword.  Quadwords 0-31 contain the
59  * corresponding vector registers.  Quadword 32 contains the vscr as the
60  * last word (offset 12) within that quadword.  Quadword 33 contains the
61  * vrsave as the first word (offset 0) within the quadword.
62  *
63  * This definition of the VMX state is compatible with the current PPC32
64  * ptrace interface.  This allows signal handling and ptrace to use the
65  * same structures.  This also simplifies the implementation of a bi-arch
66  * (combined (32- and 64-bit) gdb.
67  */
68
69 /*
70  * Get contents of AltiVec register state in task TASK
71  */
72 static inline int get_vrregs(unsigned long __user *data,
73                              struct task_struct *task)
74 {
75         unsigned long regsize;
76
77         /* copy AltiVec registers VR[0] .. VR[31] */
78         regsize = 32 * sizeof(vector128);
79         if (copy_to_user(data, task->thread.vr, regsize))
80                 return -EFAULT;
81         data += (regsize / sizeof(unsigned long));
82
83         /* copy VSCR */
84         regsize = 1 * sizeof(vector128);
85         if (copy_to_user(data, &task->thread.vscr, regsize))
86                 return -EFAULT;
87         data += (regsize / sizeof(unsigned long));
88
89         /* copy VRSAVE */
90         if (put_user(task->thread.vrsave, (u32 __user *)data))
91                 return -EFAULT;
92
93         return 0;
94 }
95
96 /*
97  * Write contents of AltiVec register state into task TASK.
98  */
99 static inline int set_vrregs(struct task_struct *task,
100                              unsigned long __user *data)
101 {
102         unsigned long regsize;
103
104         /* copy AltiVec registers VR[0] .. VR[31] */
105         regsize = 32 * sizeof(vector128);
106         if (copy_from_user(task->thread.vr, data, regsize))
107                 return -EFAULT;
108         data += (regsize / sizeof(unsigned long));
109
110         /* copy VSCR */
111         regsize = 1 * sizeof(vector128);
112         if (copy_from_user(&task->thread.vscr, data, regsize))
113                 return -EFAULT;
114         data += (regsize / sizeof(unsigned long));
115
116         /* copy VRSAVE */
117         if (get_user(task->thread.vrsave, (u32 __user *)data))
118                 return -EFAULT;
119
120         return 0;
121 }
122 #endif /* CONFIG_ALTIVEC */
123
124 static inline void set_single_step(struct task_struct *task)
125 {
126         struct pt_regs *regs = task->thread.regs;
127
128         if (regs != NULL) {
129 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
130                 task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC;
131                 regs->msr |= MSR_DE;
132 #else
133                 regs->msr |= MSR_SE;
134 #endif
135         }
136         set_tsk_thread_flag(task, TIF_SINGLESTEP);
137 }
138
139 static inline void clear_single_step(struct task_struct *task)
140 {
141         struct pt_regs *regs = task->thread.regs;
142
143         if (regs != NULL) {
144 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
145                 task->thread.dbcr0 = 0;
146                 regs->msr &= ~MSR_DE;
147 #else
148                 regs->msr &= ~MSR_SE;
149 #endif
150         }
151         clear_tsk_thread_flag(task, TIF_SINGLESTEP);
152 }
153
154 #endif /* _POWERPC_PTRACE_COMMON_H */