hw-breakpoints: Rewrite the hw-breakpoints layer on top of perf events
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / kernel / hw_breakpoint.c
blob08f6d01632011719566e65f25fe423288aa6853a
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * Copyright (C) 2007 Alan Stern
17 * Copyright (C) IBM Corporation, 2009
18 * Copyright (C) 2009, Frederic Weisbecker <fweisbec@gmail.com>
22 * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
23 * using the CPU's debug registers.
24 * This file contains the arch-independent routines.
27 #include <linux/irqflags.h>
28 #include <linux/kallsyms.h>
29 #include <linux/notifier.h>
30 #include <linux/kprobes.h>
31 #include <linux/kdebug.h>
32 #include <linux/kernel.h>
33 #include <linux/module.h>
34 #include <linux/percpu.h>
35 #include <linux/sched.h>
36 #include <linux/init.h>
37 #include <linux/smp.h>
39 #include <linux/hw_breakpoint.h>
41 #include <asm/processor.h>
43 #ifdef CONFIG_X86
44 #include <asm/debugreg.h>
45 #endif
47 static atomic_t bp_slot;
49 int reserve_bp_slot(struct perf_event *bp)
51 if (atomic_inc_return(&bp_slot) == HBP_NUM) {
52 atomic_dec(&bp_slot);
54 return -ENOSPC;
57 return 0;
60 void release_bp_slot(struct perf_event *bp)
62 atomic_dec(&bp_slot);
65 int __register_perf_hw_breakpoint(struct perf_event *bp)
67 int ret;
69 ret = reserve_bp_slot(bp);
70 if (ret)
71 return ret;
73 if (!bp->attr.disabled)
74 ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task);
76 return ret;
79 int register_perf_hw_breakpoint(struct perf_event *bp)
81 bp->callback = perf_bp_event;
83 return __register_perf_hw_breakpoint(bp);
87 * Register a breakpoint bound to a task and a given cpu.
88 * If cpu is -1, the breakpoint is active for the task in every cpu
89 * If the task is -1, the breakpoint is active for every tasks in the given
90 * cpu.
92 static struct perf_event *
93 register_user_hw_breakpoint_cpu(unsigned long addr,
94 int len,
95 int type,
96 perf_callback_t triggered,
97 pid_t pid,
98 int cpu,
99 bool active)
101 struct perf_event_attr *attr;
102 struct perf_event *bp;
104 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
105 if (!attr)
106 return ERR_PTR(-ENOMEM);
108 attr->type = PERF_TYPE_BREAKPOINT;
109 attr->size = sizeof(*attr);
110 attr->bp_addr = addr;
111 attr->bp_len = len;
112 attr->bp_type = type;
114 * Such breakpoints are used by debuggers to trigger signals when
115 * we hit the excepted memory op. We can't miss such events, they
116 * must be pinned.
118 attr->pinned = 1;
120 if (!active)
121 attr->disabled = 1;
123 bp = perf_event_create_kernel_counter(attr, cpu, pid, triggered);
124 kfree(attr);
126 return bp;
130 * register_user_hw_breakpoint - register a hardware breakpoint for user space
131 * @addr: is the memory address that triggers the breakpoint
132 * @len: the length of the access to the memory (1 byte, 2 bytes etc...)
133 * @type: the type of the access to the memory (read/write/exec)
134 * @triggered: callback to trigger when we hit the breakpoint
135 * @tsk: pointer to 'task_struct' of the process to which the address belongs
136 * @active: should we activate it while registering it
139 struct perf_event *
140 register_user_hw_breakpoint(unsigned long addr,
141 int len,
142 int type,
143 perf_callback_t triggered,
144 struct task_struct *tsk,
145 bool active)
147 return register_user_hw_breakpoint_cpu(addr, len, type, triggered,
148 tsk->pid, -1, active);
150 EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
153 * modify_user_hw_breakpoint - modify a user-space hardware breakpoint
154 * @bp: the breakpoint structure to modify
155 * @addr: is the memory address that triggers the breakpoint
156 * @len: the length of the access to the memory (1 byte, 2 bytes etc...)
157 * @type: the type of the access to the memory (read/write/exec)
158 * @triggered: callback to trigger when we hit the breakpoint
159 * @tsk: pointer to 'task_struct' of the process to which the address belongs
160 * @active: should we activate it while registering it
162 struct perf_event *
163 modify_user_hw_breakpoint(struct perf_event *bp,
164 unsigned long addr,
165 int len,
166 int type,
167 perf_callback_t triggered,
168 struct task_struct *tsk,
169 bool active)
172 * FIXME: do it without unregistering
173 * - We don't want to lose our slot
174 * - If the new bp is incorrect, don't lose the older one
176 unregister_hw_breakpoint(bp);
178 return register_user_hw_breakpoint(addr, len, type, triggered,
179 tsk, active);
181 EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint);
184 * unregister_hw_breakpoint - unregister a user-space hardware breakpoint
185 * @bp: the breakpoint structure to unregister
187 void unregister_hw_breakpoint(struct perf_event *bp)
189 if (!bp)
190 return;
191 perf_event_release_kernel(bp);
193 EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
195 static struct perf_event *
196 register_kernel_hw_breakpoint_cpu(unsigned long addr,
197 int len,
198 int type,
199 perf_callback_t triggered,
200 int cpu,
201 bool active)
203 return register_user_hw_breakpoint_cpu(addr, len, type, triggered,
204 -1, cpu, active);
208 * register_wide_hw_breakpoint - register a wide breakpoint in the kernel
209 * @addr: is the memory address that triggers the breakpoint
210 * @len: the length of the access to the memory (1 byte, 2 bytes etc...)
211 * @type: the type of the access to the memory (read/write/exec)
212 * @triggered: callback to trigger when we hit the breakpoint
213 * @active: should we activate it while registering it
215 * @return a set of per_cpu pointers to perf events
217 struct perf_event **
218 register_wide_hw_breakpoint(unsigned long addr,
219 int len,
220 int type,
221 perf_callback_t triggered,
222 bool active)
224 struct perf_event **cpu_events, **pevent, *bp;
225 long err;
226 int cpu;
228 cpu_events = alloc_percpu(typeof(*cpu_events));
229 if (!cpu_events)
230 return ERR_PTR(-ENOMEM);
232 for_each_possible_cpu(cpu) {
233 pevent = per_cpu_ptr(cpu_events, cpu);
234 bp = register_kernel_hw_breakpoint_cpu(addr, len, type,
235 triggered, cpu, active);
237 *pevent = bp;
239 if (IS_ERR(bp) || !bp) {
240 err = PTR_ERR(bp);
241 goto fail;
245 return cpu_events;
247 fail:
248 for_each_possible_cpu(cpu) {
249 pevent = per_cpu_ptr(cpu_events, cpu);
250 if (IS_ERR(*pevent) || !*pevent)
251 break;
252 unregister_hw_breakpoint(*pevent);
254 free_percpu(cpu_events);
255 /* return the error if any */
256 return ERR_PTR(err);
260 * unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
261 * @cpu_events: the per cpu set of events to unregister
263 void unregister_wide_hw_breakpoint(struct perf_event **cpu_events)
265 int cpu;
266 struct perf_event **pevent;
268 for_each_possible_cpu(cpu) {
269 pevent = per_cpu_ptr(cpu_events, cpu);
270 unregister_hw_breakpoint(*pevent);
272 free_percpu(cpu_events);
276 static struct notifier_block hw_breakpoint_exceptions_nb = {
277 .notifier_call = hw_breakpoint_exceptions_notify,
278 /* we need to be notified first */
279 .priority = 0x7fffffff
282 static int __init init_hw_breakpoint(void)
284 return register_die_notifier(&hw_breakpoint_exceptions_nb);
286 core_initcall(init_hw_breakpoint);
289 struct pmu perf_ops_bp = {
290 .enable = arch_install_hw_breakpoint,
291 .disable = arch_uninstall_hw_breakpoint,
292 .read = hw_breakpoint_pmu_read,
293 .unthrottle = hw_breakpoint_pmu_unthrottle