Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/avr32/kernel/ptrace.c
10817 views
1
/*
2
* Copyright (C) 2004-2006 Atmel Corporation
3
*
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 2 as
6
* published by the Free Software Foundation.
7
*/
8
#undef DEBUG
9
#include <linux/kernel.h>
10
#include <linux/sched.h>
11
#include <linux/mm.h>
12
#include <linux/ptrace.h>
13
#include <linux/errno.h>
14
#include <linux/user.h>
15
#include <linux/security.h>
16
#include <linux/unistd.h>
17
#include <linux/notifier.h>
18
19
#include <asm/traps.h>
20
#include <asm/uaccess.h>
21
#include <asm/ocd.h>
22
#include <asm/mmu_context.h>
23
#include <linux/kdebug.h>
24
25
static struct pt_regs *get_user_regs(struct task_struct *tsk)
26
{
27
return (struct pt_regs *)((unsigned long)task_stack_page(tsk) +
28
THREAD_SIZE - sizeof(struct pt_regs));
29
}
30
31
void user_enable_single_step(struct task_struct *tsk)
32
{
33
pr_debug("user_enable_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n",
34
tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr);
35
36
/*
37
* We can't schedule in Debug mode, so when TIF_BREAKPOINT is
38
* set, the system call or exception handler will do a
39
* breakpoint to enter monitor mode before returning to
40
* userspace.
41
*
42
* The monitor code will then notice that TIF_SINGLE_STEP is
43
* set and return to userspace with single stepping enabled.
44
* The CPU will then enter monitor mode again after exactly
45
* one instruction has been executed, and the monitor code
46
* will then send a SIGTRAP to the process.
47
*/
48
set_tsk_thread_flag(tsk, TIF_BREAKPOINT);
49
set_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
50
}
51
52
void user_disable_single_step(struct task_struct *child)
53
{
54
/* XXX(hch): a no-op here seems wrong.. */
55
}
56
57
/*
58
* Called by kernel/ptrace.c when detaching
59
*
60
* Make sure any single step bits, etc. are not set
61
*/
62
void ptrace_disable(struct task_struct *child)
63
{
64
clear_tsk_thread_flag(child, TIF_SINGLE_STEP);
65
clear_tsk_thread_flag(child, TIF_BREAKPOINT);
66
ocd_disable(child);
67
}
68
69
/*
70
* Read the word at offset "offset" into the task's "struct user". We
71
* actually access the pt_regs struct stored on the kernel stack.
72
*/
73
static int ptrace_read_user(struct task_struct *tsk, unsigned long offset,
74
unsigned long __user *data)
75
{
76
unsigned long *regs;
77
unsigned long value;
78
79
if (offset & 3 || offset >= sizeof(struct user)) {
80
printk("ptrace_read_user: invalid offset 0x%08lx\n", offset);
81
return -EIO;
82
}
83
84
regs = (unsigned long *)get_user_regs(tsk);
85
86
value = 0;
87
if (offset < sizeof(struct pt_regs))
88
value = regs[offset / sizeof(regs[0])];
89
90
pr_debug("ptrace_read_user(%s[%u], %#lx, %p) -> %#lx\n",
91
tsk->comm, tsk->pid, offset, data, value);
92
93
return put_user(value, data);
94
}
95
96
/*
97
* Write the word "value" to offset "offset" into the task's "struct
98
* user". We actually access the pt_regs struct stored on the kernel
99
* stack.
100
*/
101
static int ptrace_write_user(struct task_struct *tsk, unsigned long offset,
102
unsigned long value)
103
{
104
unsigned long *regs;
105
106
pr_debug("ptrace_write_user(%s[%u], %#lx, %#lx)\n",
107
tsk->comm, tsk->pid, offset, value);
108
109
if (offset & 3 || offset >= sizeof(struct user)) {
110
pr_debug(" invalid offset 0x%08lx\n", offset);
111
return -EIO;
112
}
113
114
if (offset >= sizeof(struct pt_regs))
115
return 0;
116
117
regs = (unsigned long *)get_user_regs(tsk);
118
regs[offset / sizeof(regs[0])] = value;
119
120
return 0;
121
}
122
123
static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
124
{
125
struct pt_regs *regs = get_user_regs(tsk);
126
127
return copy_to_user(uregs, regs, sizeof(*regs)) ? -EFAULT : 0;
128
}
129
130
static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
131
{
132
struct pt_regs newregs;
133
int ret;
134
135
ret = -EFAULT;
136
if (copy_from_user(&newregs, uregs, sizeof(newregs)) == 0) {
137
struct pt_regs *regs = get_user_regs(tsk);
138
139
ret = -EINVAL;
140
if (valid_user_regs(&newregs)) {
141
*regs = newregs;
142
ret = 0;
143
}
144
}
145
146
return ret;
147
}
148
149
long arch_ptrace(struct task_struct *child, long request,
150
unsigned long addr, unsigned long data)
151
{
152
int ret;
153
void __user *datap = (void __user *) data;
154
155
switch (request) {
156
/* Read the word at location addr in the child process */
157
case PTRACE_PEEKTEXT:
158
case PTRACE_PEEKDATA:
159
ret = generic_ptrace_peekdata(child, addr, data);
160
break;
161
162
case PTRACE_PEEKUSR:
163
ret = ptrace_read_user(child, addr, datap);
164
break;
165
166
/* Write the word in data at location addr */
167
case PTRACE_POKETEXT:
168
case PTRACE_POKEDATA:
169
ret = generic_ptrace_pokedata(child, addr, data);
170
break;
171
172
case PTRACE_POKEUSR:
173
ret = ptrace_write_user(child, addr, data);
174
break;
175
176
case PTRACE_GETREGS:
177
ret = ptrace_getregs(child, datap);
178
break;
179
180
case PTRACE_SETREGS:
181
ret = ptrace_setregs(child, datap);
182
break;
183
184
default:
185
ret = ptrace_request(child, request, addr, data);
186
break;
187
}
188
189
return ret;
190
}
191
192
asmlinkage void syscall_trace(void)
193
{
194
if (!test_thread_flag(TIF_SYSCALL_TRACE))
195
return;
196
if (!(current->ptrace & PT_PTRACED))
197
return;
198
199
/* The 0x80 provides a way for the tracing parent to
200
* distinguish between a syscall stop and SIGTRAP delivery */
201
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
202
? 0x80 : 0));
203
204
/*
205
* this isn't the same as continuing with a signal, but it
206
* will do for normal use. strace only continues with a
207
* signal if the stopping signal is not SIGTRAP. -brl
208
*/
209
if (current->exit_code) {
210
pr_debug("syscall_trace: sending signal %d to PID %u\n",
211
current->exit_code, current->pid);
212
send_sig(current->exit_code, current, 1);
213
current->exit_code = 0;
214
}
215
}
216
217
/*
218
* debug_trampoline() is an assembly stub which will store all user
219
* registers on the stack and execute a breakpoint instruction.
220
*
221
* If we single-step into an exception handler which runs with
222
* interrupts disabled the whole time so it doesn't have to check for
223
* pending work, its return address will be modified so that it ends
224
* up returning to debug_trampoline.
225
*
226
* If the exception handler decides to store the user context and
227
* enable interrupts after all, it will restore the original return
228
* address and status register value. Before it returns, it will
229
* notice that TIF_BREAKPOINT is set and execute a breakpoint
230
* instruction.
231
*/
232
extern void debug_trampoline(void);
233
234
asmlinkage struct pt_regs *do_debug(struct pt_regs *regs)
235
{
236
struct thread_info *ti;
237
unsigned long trampoline_addr;
238
u32 status;
239
u32 ctrl;
240
int code;
241
242
status = ocd_read(DS);
243
ti = current_thread_info();
244
code = TRAP_BRKPT;
245
246
pr_debug("do_debug: status=0x%08x PC=0x%08lx SR=0x%08lx tif=0x%08lx\n",
247
status, regs->pc, regs->sr, ti->flags);
248
249
if (!user_mode(regs)) {
250
unsigned long die_val = DIE_BREAKPOINT;
251
252
if (status & (1 << OCD_DS_SSS_BIT))
253
die_val = DIE_SSTEP;
254
255
if (notify_die(die_val, "ptrace", regs, 0, 0, SIGTRAP)
256
== NOTIFY_STOP)
257
return regs;
258
259
if ((status & (1 << OCD_DS_SWB_BIT))
260
&& test_and_clear_ti_thread_flag(
261
ti, TIF_BREAKPOINT)) {
262
/*
263
* Explicit breakpoint from trampoline or
264
* exception/syscall/interrupt handler.
265
*
266
* The real saved regs are on the stack right
267
* after the ones we saved on entry.
268
*/
269
regs++;
270
pr_debug(" -> TIF_BREAKPOINT done, adjusted regs:"
271
"PC=0x%08lx SR=0x%08lx\n",
272
regs->pc, regs->sr);
273
BUG_ON(!user_mode(regs));
274
275
if (test_thread_flag(TIF_SINGLE_STEP)) {
276
pr_debug("Going to do single step...\n");
277
return regs;
278
}
279
280
/*
281
* No TIF_SINGLE_STEP means we're done
282
* stepping over a syscall. Do the trap now.
283
*/
284
code = TRAP_TRACE;
285
} else if ((status & (1 << OCD_DS_SSS_BIT))
286
&& test_ti_thread_flag(ti, TIF_SINGLE_STEP)) {
287
288
pr_debug("Stepped into something, "
289
"setting TIF_BREAKPOINT...\n");
290
set_ti_thread_flag(ti, TIF_BREAKPOINT);
291
292
/*
293
* We stepped into an exception, interrupt or
294
* syscall handler. Some exception handlers
295
* don't check for pending work, so we need to
296
* set up a trampoline just in case.
297
*
298
* The exception entry code will undo the
299
* trampoline stuff if it does a full context
300
* save (which also means that it'll check for
301
* pending work later.)
302
*/
303
if ((regs->sr & MODE_MASK) == MODE_EXCEPTION) {
304
trampoline_addr
305
= (unsigned long)&debug_trampoline;
306
307
pr_debug("Setting up trampoline...\n");
308
ti->rar_saved = sysreg_read(RAR_EX);
309
ti->rsr_saved = sysreg_read(RSR_EX);
310
sysreg_write(RAR_EX, trampoline_addr);
311
sysreg_write(RSR_EX, (MODE_EXCEPTION
312
| SR_EM | SR_GM));
313
BUG_ON(ti->rsr_saved & MODE_MASK);
314
}
315
316
/*
317
* If we stepped into a system call, we
318
* shouldn't do a single step after we return
319
* since the return address is right after the
320
* "scall" instruction we were told to step
321
* over.
322
*/
323
if ((regs->sr & MODE_MASK) == MODE_SUPERVISOR) {
324
pr_debug("Supervisor; no single step\n");
325
clear_ti_thread_flag(ti, TIF_SINGLE_STEP);
326
}
327
328
ctrl = ocd_read(DC);
329
ctrl &= ~(1 << OCD_DC_SS_BIT);
330
ocd_write(DC, ctrl);
331
332
return regs;
333
} else {
334
printk(KERN_ERR "Unexpected OCD_DS value: 0x%08x\n",
335
status);
336
printk(KERN_ERR "Thread flags: 0x%08lx\n", ti->flags);
337
die("Unhandled debug trap in kernel mode",
338
regs, SIGTRAP);
339
}
340
} else if (status & (1 << OCD_DS_SSS_BIT)) {
341
/* Single step in user mode */
342
code = TRAP_TRACE;
343
344
ctrl = ocd_read(DC);
345
ctrl &= ~(1 << OCD_DC_SS_BIT);
346
ocd_write(DC, ctrl);
347
}
348
349
pr_debug("Sending SIGTRAP: code=%d PC=0x%08lx SR=0x%08lx\n",
350
code, regs->pc, regs->sr);
351
352
clear_thread_flag(TIF_SINGLE_STEP);
353
_exception(SIGTRAP, regs, code, instruction_pointer(regs));
354
355
return regs;
356
}
357
358