Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
powerpc
kernel
uprobes.c
Go to the documentation of this file.
1
/*
2
* User-space Probes (UProbes) for powerpc
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 as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
*
18
* Copyright IBM Corporation, 2007-2012
19
*
20
* Adapted from the x86 port by Ananth N Mavinakayanahalli <
[email protected]
>
21
*/
22
#include <linux/kernel.h>
23
#include <linux/sched.h>
24
#include <linux/ptrace.h>
25
#include <
linux/uprobes.h
>
26
#include <
linux/uaccess.h
>
27
#include <
linux/kdebug.h
>
28
29
#include <
asm/sstep.h
>
30
31
#define UPROBE_TRAP_NR UINT_MAX
32
40
int
arch_uprobe_analyze_insn
(
struct
arch_uprobe
*auprobe,
41
struct
mm_struct
*mm,
unsigned
long
addr
)
42
{
43
if
(addr & 0x03)
44
return
-
EINVAL
;
45
46
/*
47
* We currently don't support a uprobe on an already
48
* existing breakpoint instruction underneath
49
*/
50
if
(is_trap(auprobe->
ainsn
))
51
return
-
ENOTSUPP
;
52
return
0;
53
}
54
55
/*
56
* arch_uprobe_pre_xol - prepare to execute out of line.
57
* @auprobe: the probepoint information.
58
* @regs: reflects the saved user state of current task.
59
*/
60
int
arch_uprobe_pre_xol
(
struct
arch_uprobe
*auprobe,
struct
pt_regs
*
regs
)
61
{
62
struct
arch_uprobe_task
*autask = &
current
->utask->autask;
63
64
autask->
saved_trap_nr
=
current
->thread.trap_nr;
65
current
->thread.trap_nr =
UPROBE_TRAP_NR
;
66
regs->
nip
=
current
->utask->xol_vaddr;
67
return
0;
68
}
69
76
unsigned
long
uprobe_get_swbp_addr
(
struct
pt_regs
*
regs
)
77
{
78
return
instruction_pointer
(regs);
79
}
80
81
/*
82
* If xol insn itself traps and generates a signal (SIGILL/SIGSEGV/etc),
83
* then detect the case where a singlestepped instruction jumps back to its
84
* own address. It is assumed that anything like do_page_fault/do_trap/etc
85
* sets thread.trap_nr != UINT_MAX.
86
*
87
* arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
88
* arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
89
* UPROBE_TRAP_NR == UINT_MAX set by arch_uprobe_pre_xol().
90
*/
91
bool
arch_uprobe_xol_was_trapped
(
struct
task_struct
*
t
)
92
{
93
if
(t->
thread
.trap_nr !=
UPROBE_TRAP_NR
)
94
return
true
;
95
96
return
false
;
97
}
98
99
/*
100
* Called after single-stepping. To avoid the SMP problems that can
101
* occur when we temporarily put back the original opcode to
102
* single-step, we single-stepped a copy of the instruction.
103
*
104
* This function prepares to resume execution after the single-step.
105
*/
106
int
arch_uprobe_post_xol
(
struct
arch_uprobe
*auprobe,
struct
pt_regs
*
regs
)
107
{
108
struct
uprobe_task *utask =
current
->utask;
109
110
WARN_ON_ONCE
(
current
->thread.trap_nr !=
UPROBE_TRAP_NR
);
111
112
current
->thread.trap_nr = utask->autask.saved_trap_nr;
113
114
/*
115
* On powerpc, except for loads and stores, most instructions
116
* including ones that alter code flow (branches, calls, returns)
117
* are emulated in the kernel. We get here only if the emulation
118
* support doesn't exist and have to fix-up the next instruction
119
* to be executed.
120
*/
121
regs->
nip
= utask->vaddr +
MAX_UINSN_BYTES
;
122
return
0;
123
}
124
125
/* callback routine for handling exceptions. */
126
int
arch_uprobe_exception_notify
(
struct
notifier_block
*
self
,
127
unsigned
long
val
,
void
*
data
)
128
{
129
struct
die_args
*
args
=
data
;
130
struct
pt_regs
*
regs
= args->
regs
;
131
132
/* regs == NULL is a kernel bug */
133
if
(
WARN_ON
(!regs))
134
return
NOTIFY_DONE;
135
136
/* We are only interested in userspace traps */
137
if
(!
user_mode
(regs))
138
return
NOTIFY_DONE;
139
140
switch
(val) {
141
case
DIE_BPT
:
142
if
(
uprobe_pre_sstep_notifier
(regs))
143
return
NOTIFY_STOP;
144
break
;
145
case
DIE_SSTEP
:
146
if
(
uprobe_post_sstep_notifier
(regs))
147
return
NOTIFY_STOP;
148
default
:
149
break
;
150
}
151
return
NOTIFY_DONE;
152
}
153
154
/*
155
* This function gets called when XOL instruction either gets trapped or
156
* the thread has a fatal signal, so reset the instruction pointer to its
157
* probed address.
158
*/
159
void
arch_uprobe_abort_xol
(
struct
arch_uprobe
*auprobe,
struct
pt_regs
*
regs
)
160
{
161
struct
uprobe_task *utask =
current
->utask;
162
163
current
->thread.trap_nr = utask->autask.saved_trap_nr;
164
instruction_pointer_set(regs, utask->vaddr);
165
}
166
167
/*
168
* See if the instruction can be emulated.
169
* Returns true if instruction was emulated, false otherwise.
170
*/
171
bool
arch_uprobe_skip_sstep
(
struct
arch_uprobe
*auprobe,
struct
pt_regs
*
regs
)
172
{
173
int
ret
;
174
175
/*
176
* emulate_step() returns 1 if the insn was successfully emulated.
177
* For all other cases, we need to single-step in hardware.
178
*/
179
ret =
emulate_step
(regs, auprobe->
ainsn
);
180
if
(ret > 0)
181
return
true
;
182
183
return
false
;
184
}
Generated on Thu Jan 10 2013 13:13:59 for Linux Kernel by
1.8.2