Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/kernel/hw_breakpoint.c
10817 views
1
/*
2
* HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
3
* using the CPU's debug registers. Derived from
4
* "arch/x86/kernel/hw_breakpoint.c"
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
*
20
* Copyright 2010 IBM Corporation
21
* Author: K.Prasad <[email protected]>
22
*
23
*/
24
25
#include <linux/hw_breakpoint.h>
26
#include <linux/notifier.h>
27
#include <linux/kprobes.h>
28
#include <linux/percpu.h>
29
#include <linux/kernel.h>
30
#include <linux/module.h>
31
#include <linux/sched.h>
32
#include <linux/init.h>
33
#include <linux/smp.h>
34
35
#include <asm/hw_breakpoint.h>
36
#include <asm/processor.h>
37
#include <asm/sstep.h>
38
#include <asm/uaccess.h>
39
40
/*
41
* Stores the breakpoints currently in use on each breakpoint address
42
* register for every cpu
43
*/
44
static DEFINE_PER_CPU(struct perf_event *, bp_per_reg);
45
46
/*
47
* Returns total number of data or instruction breakpoints available.
48
*/
49
int hw_breakpoint_slots(int type)
50
{
51
if (type == TYPE_DATA)
52
return HBP_NUM;
53
return 0; /* no instruction breakpoints available */
54
}
55
56
/*
57
* Install a perf counter breakpoint.
58
*
59
* We seek a free debug address register and use it for this
60
* breakpoint.
61
*
62
* Atomic: we hold the counter->ctx->lock and we only handle variables
63
* and registers local to this cpu.
64
*/
65
int arch_install_hw_breakpoint(struct perf_event *bp)
66
{
67
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
68
struct perf_event **slot = &__get_cpu_var(bp_per_reg);
69
70
*slot = bp;
71
72
/*
73
* Do not install DABR values if the instruction must be single-stepped.
74
* If so, DABR will be populated in single_step_dabr_instruction().
75
*/
76
if (current->thread.last_hit_ubp != bp)
77
set_dabr(info->address | info->type | DABR_TRANSLATION);
78
79
return 0;
80
}
81
82
/*
83
* Uninstall the breakpoint contained in the given counter.
84
*
85
* First we search the debug address register it uses and then we disable
86
* it.
87
*
88
* Atomic: we hold the counter->ctx->lock and we only handle variables
89
* and registers local to this cpu.
90
*/
91
void arch_uninstall_hw_breakpoint(struct perf_event *bp)
92
{
93
struct perf_event **slot = &__get_cpu_var(bp_per_reg);
94
95
if (*slot != bp) {
96
WARN_ONCE(1, "Can't find the breakpoint");
97
return;
98
}
99
100
*slot = NULL;
101
set_dabr(0);
102
}
103
104
/*
105
* Perform cleanup of arch-specific counters during unregistration
106
* of the perf-event
107
*/
108
void arch_unregister_hw_breakpoint(struct perf_event *bp)
109
{
110
/*
111
* If the breakpoint is unregistered between a hw_breakpoint_handler()
112
* and the single_step_dabr_instruction(), then cleanup the breakpoint
113
* restoration variables to prevent dangling pointers.
114
*/
115
if (bp->ctx->task)
116
bp->ctx->task->thread.last_hit_ubp = NULL;
117
}
118
119
/*
120
* Check for virtual address in kernel space.
121
*/
122
int arch_check_bp_in_kernelspace(struct perf_event *bp)
123
{
124
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
125
126
return is_kernel_addr(info->address);
127
}
128
129
int arch_bp_generic_fields(int type, int *gen_bp_type)
130
{
131
switch (type) {
132
case DABR_DATA_READ:
133
*gen_bp_type = HW_BREAKPOINT_R;
134
break;
135
case DABR_DATA_WRITE:
136
*gen_bp_type = HW_BREAKPOINT_W;
137
break;
138
case (DABR_DATA_WRITE | DABR_DATA_READ):
139
*gen_bp_type = (HW_BREAKPOINT_W | HW_BREAKPOINT_R);
140
break;
141
default:
142
return -EINVAL;
143
}
144
return 0;
145
}
146
147
/*
148
* Validate the arch-specific HW Breakpoint register settings
149
*/
150
int arch_validate_hwbkpt_settings(struct perf_event *bp)
151
{
152
int ret = -EINVAL;
153
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
154
155
if (!bp)
156
return ret;
157
158
switch (bp->attr.bp_type) {
159
case HW_BREAKPOINT_R:
160
info->type = DABR_DATA_READ;
161
break;
162
case HW_BREAKPOINT_W:
163
info->type = DABR_DATA_WRITE;
164
break;
165
case HW_BREAKPOINT_R | HW_BREAKPOINT_W:
166
info->type = (DABR_DATA_READ | DABR_DATA_WRITE);
167
break;
168
default:
169
return ret;
170
}
171
172
info->address = bp->attr.bp_addr;
173
info->len = bp->attr.bp_len;
174
175
/*
176
* Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
177
* and breakpoint addresses are aligned to nearest double-word
178
* HW_BREAKPOINT_ALIGN by rounding off to the lower address, the
179
* 'symbolsize' should satisfy the check below.
180
*/
181
if (info->len >
182
(HW_BREAKPOINT_LEN - (info->address & HW_BREAKPOINT_ALIGN)))
183
return -EINVAL;
184
return 0;
185
}
186
187
/*
188
* Restores the breakpoint on the debug registers.
189
* Invoke this function if it is known that the execution context is
190
* about to change to cause loss of MSR_SE settings.
191
*/
192
void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
193
{
194
struct arch_hw_breakpoint *info;
195
196
if (likely(!tsk->thread.last_hit_ubp))
197
return;
198
199
info = counter_arch_bp(tsk->thread.last_hit_ubp);
200
regs->msr &= ~MSR_SE;
201
set_dabr(info->address | info->type | DABR_TRANSLATION);
202
tsk->thread.last_hit_ubp = NULL;
203
}
204
205
/*
206
* Handle debug exception notifications.
207
*/
208
int __kprobes hw_breakpoint_handler(struct die_args *args)
209
{
210
int rc = NOTIFY_STOP;
211
struct perf_event *bp;
212
struct pt_regs *regs = args->regs;
213
int stepped = 1;
214
struct arch_hw_breakpoint *info;
215
unsigned int instr;
216
unsigned long dar = regs->dar;
217
218
/* Disable breakpoints during exception handling */
219
set_dabr(0);
220
221
/*
222
* The counter may be concurrently released but that can only
223
* occur from a call_rcu() path. We can then safely fetch
224
* the breakpoint, use its callback, touch its counter
225
* while we are in an rcu_read_lock() path.
226
*/
227
rcu_read_lock();
228
229
bp = __get_cpu_var(bp_per_reg);
230
if (!bp)
231
goto out;
232
info = counter_arch_bp(bp);
233
234
/*
235
* Return early after invoking user-callback function without restoring
236
* DABR if the breakpoint is from ptrace which always operates in
237
* one-shot mode. The ptrace-ed process will receive the SIGTRAP signal
238
* generated in do_dabr().
239
*/
240
if (bp->overflow_handler == ptrace_triggered) {
241
perf_bp_event(bp, regs);
242
rc = NOTIFY_DONE;
243
goto out;
244
}
245
246
/*
247
* Verify if dar lies within the address range occupied by the symbol
248
* being watched to filter extraneous exceptions. If it doesn't,
249
* we still need to single-step the instruction, but we don't
250
* generate an event.
251
*/
252
info->extraneous_interrupt = !((bp->attr.bp_addr <= dar) &&
253
(dar - bp->attr.bp_addr < bp->attr.bp_len));
254
255
/* Do not emulate user-space instructions, instead single-step them */
256
if (user_mode(regs)) {
257
bp->ctx->task->thread.last_hit_ubp = bp;
258
regs->msr |= MSR_SE;
259
goto out;
260
}
261
262
stepped = 0;
263
instr = 0;
264
if (!__get_user_inatomic(instr, (unsigned int *) regs->nip))
265
stepped = emulate_step(regs, instr);
266
267
/*
268
* emulate_step() could not execute it. We've failed in reliably
269
* handling the hw-breakpoint. Unregister it and throw a warning
270
* message to let the user know about it.
271
*/
272
if (!stepped) {
273
WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
274
"0x%lx will be disabled.", info->address);
275
perf_event_disable(bp);
276
goto out;
277
}
278
/*
279
* As a policy, the callback is invoked in a 'trigger-after-execute'
280
* fashion
281
*/
282
if (!info->extraneous_interrupt)
283
perf_bp_event(bp, regs);
284
285
set_dabr(info->address | info->type | DABR_TRANSLATION);
286
out:
287
rcu_read_unlock();
288
return rc;
289
}
290
291
/*
292
* Handle single-step exceptions following a DABR hit.
293
*/
294
int __kprobes single_step_dabr_instruction(struct die_args *args)
295
{
296
struct pt_regs *regs = args->regs;
297
struct perf_event *bp = NULL;
298
struct arch_hw_breakpoint *bp_info;
299
300
bp = current->thread.last_hit_ubp;
301
/*
302
* Check if we are single-stepping as a result of a
303
* previous HW Breakpoint exception
304
*/
305
if (!bp)
306
return NOTIFY_DONE;
307
308
bp_info = counter_arch_bp(bp);
309
310
/*
311
* We shall invoke the user-defined callback function in the single
312
* stepping handler to confirm to 'trigger-after-execute' semantics
313
*/
314
if (!bp_info->extraneous_interrupt)
315
perf_bp_event(bp, regs);
316
317
set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);
318
current->thread.last_hit_ubp = NULL;
319
320
/*
321
* If the process was being single-stepped by ptrace, let the
322
* other single-step actions occur (e.g. generate SIGTRAP).
323
*/
324
if (test_thread_flag(TIF_SINGLESTEP))
325
return NOTIFY_DONE;
326
327
return NOTIFY_STOP;
328
}
329
330
/*
331
* Handle debug exception notifications.
332
*/
333
int __kprobes hw_breakpoint_exceptions_notify(
334
struct notifier_block *unused, unsigned long val, void *data)
335
{
336
int ret = NOTIFY_DONE;
337
338
switch (val) {
339
case DIE_DABR_MATCH:
340
ret = hw_breakpoint_handler(data);
341
break;
342
case DIE_SSTEP:
343
ret = single_step_dabr_instruction(data);
344
break;
345
}
346
347
return ret;
348
}
349
350
/*
351
* Release the user breakpoints used by ptrace
352
*/
353
void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
354
{
355
struct thread_struct *t = &tsk->thread;
356
357
unregister_hw_breakpoint(t->ptrace_bps[0]);
358
t->ptrace_bps[0] = NULL;
359
}
360
361
void hw_breakpoint_pmu_read(struct perf_event *bp)
362
{
363
/* TODO */
364
}
365
366