aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/kgdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/kgdb.c')
-rw-r--r--arch/x86/kernel/kgdb.c489
1 files changed, 311 insertions, 178 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index dd74fe7273b1..852b81967a37 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -42,73 +42,101 @@
42#include <linux/init.h> 42#include <linux/init.h>
43#include <linux/smp.h> 43#include <linux/smp.h>
44#include <linux/nmi.h> 44#include <linux/nmi.h>
45#include <linux/hw_breakpoint.h>
45 46
46#include <asm/debugreg.h> 47#include <asm/debugreg.h>
47#include <asm/apicdef.h> 48#include <asm/apicdef.h>
48#include <asm/system.h> 49#include <asm/system.h>
49
50#include <asm/apic.h> 50#include <asm/apic.h>
51 51
52/* 52struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
53 * Put the error code here just in case the user cares:
54 */
55static int gdb_x86errcode;
56
57/*
58 * Likewise, the vector number here (since GDB only gets the signal
59 * number through the usual means, and that's not very specific):
60 */
61static int gdb_x86vector = -1;
62
63/**
64 * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs
65 * @gdb_regs: A pointer to hold the registers in the order GDB wants.
66 * @regs: The &struct pt_regs of the current process.
67 *
68 * Convert the pt_regs in @regs into the format for registers that
69 * GDB expects, stored in @gdb_regs.
70 */
71void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
72{ 53{
73#ifndef CONFIG_X86_32 54#ifdef CONFIG_X86_32
74 u32 *gdb_regs32 = (u32 *)gdb_regs; 55 { "ax", 4, offsetof(struct pt_regs, ax) },
56 { "cx", 4, offsetof(struct pt_regs, cx) },
57 { "dx", 4, offsetof(struct pt_regs, dx) },
58 { "bx", 4, offsetof(struct pt_regs, bx) },
59 { "sp", 4, offsetof(struct pt_regs, sp) },
60 { "bp", 4, offsetof(struct pt_regs, bp) },
61 { "si", 4, offsetof(struct pt_regs, si) },
62 { "di", 4, offsetof(struct pt_regs, di) },
63 { "ip", 4, offsetof(struct pt_regs, ip) },
64 { "flags", 4, offsetof(struct pt_regs, flags) },
65 { "cs", 4, offsetof(struct pt_regs, cs) },
66 { "ss", 4, offsetof(struct pt_regs, ss) },
67 { "ds", 4, offsetof(struct pt_regs, ds) },
68 { "es", 4, offsetof(struct pt_regs, es) },
69 { "fs", 4, -1 },
70 { "gs", 4, -1 },
71#else
72 { "ax", 8, offsetof(struct pt_regs, ax) },
73 { "bx", 8, offsetof(struct pt_regs, bx) },
74 { "cx", 8, offsetof(struct pt_regs, cx) },
75 { "dx", 8, offsetof(struct pt_regs, dx) },
76 { "si", 8, offsetof(struct pt_regs, dx) },
77 { "di", 8, offsetof(struct pt_regs, di) },
78 { "bp", 8, offsetof(struct pt_regs, bp) },
79 { "sp", 8, offsetof(struct pt_regs, sp) },
80 { "r8", 8, offsetof(struct pt_regs, r8) },
81 { "r9", 8, offsetof(struct pt_regs, r9) },
82 { "r10", 8, offsetof(struct pt_regs, r10) },
83 { "r11", 8, offsetof(struct pt_regs, r11) },
84 { "r12", 8, offsetof(struct pt_regs, r12) },
85 { "r13", 8, offsetof(struct pt_regs, r13) },
86 { "r14", 8, offsetof(struct pt_regs, r14) },
87 { "r15", 8, offsetof(struct pt_regs, r15) },
88 { "ip", 8, offsetof(struct pt_regs, ip) },
89 { "flags", 4, offsetof(struct pt_regs, flags) },
90 { "cs", 4, offsetof(struct pt_regs, cs) },
91 { "ss", 4, offsetof(struct pt_regs, ss) },
75#endif 92#endif
76 gdb_regs[GDB_AX] = regs->ax; 93};
77 gdb_regs[GDB_BX] = regs->bx; 94
78 gdb_regs[GDB_CX] = regs->cx; 95int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
79 gdb_regs[GDB_DX] = regs->dx; 96{
80 gdb_regs[GDB_SI] = regs->si; 97 if (
81 gdb_regs[GDB_DI] = regs->di;
82 gdb_regs[GDB_BP] = regs->bp;
83 gdb_regs[GDB_PC] = regs->ip;
84#ifdef CONFIG_X86_32 98#ifdef CONFIG_X86_32
85 gdb_regs[GDB_PS] = regs->flags; 99 regno == GDB_SS || regno == GDB_FS || regno == GDB_GS ||
86 gdb_regs[GDB_DS] = regs->ds; 100#endif
87 gdb_regs[GDB_ES] = regs->es; 101 regno == GDB_SP || regno == GDB_ORIG_AX)
88 gdb_regs[GDB_CS] = regs->cs; 102 return 0;
89 gdb_regs[GDB_FS] = 0xFFFF; 103
90 gdb_regs[GDB_GS] = 0xFFFF; 104 if (dbg_reg_def[regno].offset != -1)
91 if (user_mode_vm(regs)) { 105 memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
92 gdb_regs[GDB_SS] = regs->ss; 106 dbg_reg_def[regno].size);
93 gdb_regs[GDB_SP] = regs->sp; 107 return 0;
94 } else { 108}
95 gdb_regs[GDB_SS] = __KERNEL_DS; 109
96 gdb_regs[GDB_SP] = kernel_stack_pointer(regs); 110char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
111{
112 if (regno == GDB_ORIG_AX) {
113 memcpy(mem, &regs->orig_ax, sizeof(regs->orig_ax));
114 return "orig_ax";
97 } 115 }
98#else 116 if (regno >= DBG_MAX_REG_NUM || regno < 0)
99 gdb_regs[GDB_R8] = regs->r8; 117 return NULL;
100 gdb_regs[GDB_R9] = regs->r9; 118
101 gdb_regs[GDB_R10] = regs->r10; 119 if (dbg_reg_def[regno].offset != -1)
102 gdb_regs[GDB_R11] = regs->r11; 120 memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
103 gdb_regs[GDB_R12] = regs->r12; 121 dbg_reg_def[regno].size);
104 gdb_regs[GDB_R13] = regs->r13; 122
105 gdb_regs[GDB_R14] = regs->r14; 123 switch (regno) {
106 gdb_regs[GDB_R15] = regs->r15; 124#ifdef CONFIG_X86_32
107 gdb_regs32[GDB_PS] = regs->flags; 125 case GDB_SS:
108 gdb_regs32[GDB_CS] = regs->cs; 126 if (!user_mode_vm(regs))
109 gdb_regs32[GDB_SS] = regs->ss; 127 *(unsigned long *)mem = __KERNEL_DS;
110 gdb_regs[GDB_SP] = kernel_stack_pointer(regs); 128 break;
129 case GDB_SP:
130 if (!user_mode_vm(regs))
131 *(unsigned long *)mem = kernel_stack_pointer(regs);
132 break;
133 case GDB_GS:
134 case GDB_FS:
135 *(unsigned long *)mem = 0xFFFF;
136 break;
111#endif 137#endif
138 }
139 return dbg_reg_def[regno].name;
112} 140}
113 141
114/** 142/**
@@ -161,83 +189,100 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
161 gdb_regs[GDB_SP] = p->thread.sp; 189 gdb_regs[GDB_SP] = p->thread.sp;
162} 190}
163 191
164/**
165 * gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs.
166 * @gdb_regs: A pointer to hold the registers we've received from GDB.
167 * @regs: A pointer to a &struct pt_regs to hold these values in.
168 *
169 * Convert the GDB regs in @gdb_regs into the pt_regs, and store them
170 * in @regs.
171 */
172void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
173{
174#ifndef CONFIG_X86_32
175 u32 *gdb_regs32 = (u32 *)gdb_regs;
176#endif
177 regs->ax = gdb_regs[GDB_AX];
178 regs->bx = gdb_regs[GDB_BX];
179 regs->cx = gdb_regs[GDB_CX];
180 regs->dx = gdb_regs[GDB_DX];
181 regs->si = gdb_regs[GDB_SI];
182 regs->di = gdb_regs[GDB_DI];
183 regs->bp = gdb_regs[GDB_BP];
184 regs->ip = gdb_regs[GDB_PC];
185#ifdef CONFIG_X86_32
186 regs->flags = gdb_regs[GDB_PS];
187 regs->ds = gdb_regs[GDB_DS];
188 regs->es = gdb_regs[GDB_ES];
189 regs->cs = gdb_regs[GDB_CS];
190#else
191 regs->r8 = gdb_regs[GDB_R8];
192 regs->r9 = gdb_regs[GDB_R9];
193 regs->r10 = gdb_regs[GDB_R10];
194 regs->r11 = gdb_regs[GDB_R11];
195 regs->r12 = gdb_regs[GDB_R12];
196 regs->r13 = gdb_regs[GDB_R13];
197 regs->r14 = gdb_regs[GDB_R14];
198 regs->r15 = gdb_regs[GDB_R15];
199 regs->flags = gdb_regs32[GDB_PS];
200 regs->cs = gdb_regs32[GDB_CS];
201 regs->ss = gdb_regs32[GDB_SS];
202#endif
203}
204
205static struct hw_breakpoint { 192static struct hw_breakpoint {
206 unsigned enabled; 193 unsigned enabled;
207 unsigned type;
208 unsigned len;
209 unsigned long addr; 194 unsigned long addr;
210} breakinfo[4]; 195 int len;
196 int type;
197 struct perf_event * __percpu *pev;
198} breakinfo[HBP_NUM];
199
200static unsigned long early_dr7;
211 201
212static void kgdb_correct_hw_break(void) 202static void kgdb_correct_hw_break(void)
213{ 203{
214 unsigned long dr7;
215 int correctit = 0;
216 int breakbit;
217 int breakno; 204 int breakno;
218 205
219 get_debugreg(dr7, 7); 206 for (breakno = 0; breakno < HBP_NUM; breakno++) {
220 for (breakno = 0; breakno < 4; breakno++) { 207 struct perf_event *bp;
221 breakbit = 2 << (breakno << 1); 208 struct arch_hw_breakpoint *info;
222 if (!(dr7 & breakbit) && breakinfo[breakno].enabled) { 209 int val;
223 correctit = 1; 210 int cpu = raw_smp_processor_id();
224 dr7 |= breakbit; 211 if (!breakinfo[breakno].enabled)
225 dr7 &= ~(0xf0000 << (breakno << 2)); 212 continue;
226 dr7 |= ((breakinfo[breakno].len << 2) | 213 if (dbg_is_early) {
227 breakinfo[breakno].type) <<
228 ((breakno << 2) + 16);
229 set_debugreg(breakinfo[breakno].addr, breakno); 214 set_debugreg(breakinfo[breakno].addr, breakno);
230 215 early_dr7 |= encode_dr7(breakno,
231 } else { 216 breakinfo[breakno].len,
232 if ((dr7 & breakbit) && !breakinfo[breakno].enabled) { 217 breakinfo[breakno].type);
233 correctit = 1; 218 set_debugreg(early_dr7, 7);
234 dr7 &= ~breakbit; 219 continue;
235 dr7 &= ~(0xf0000 << (breakno << 2));
236 }
237 } 220 }
221 bp = *per_cpu_ptr(breakinfo[breakno].pev, cpu);
222 info = counter_arch_bp(bp);
223 if (bp->attr.disabled != 1)
224 continue;
225 bp->attr.bp_addr = breakinfo[breakno].addr;
226 bp->attr.bp_len = breakinfo[breakno].len;
227 bp->attr.bp_type = breakinfo[breakno].type;
228 info->address = breakinfo[breakno].addr;
229 info->len = breakinfo[breakno].len;
230 info->type = breakinfo[breakno].type;
231 val = arch_install_hw_breakpoint(bp);
232 if (!val)
233 bp->attr.disabled = 0;
234 }
235 if (!dbg_is_early)
236 hw_breakpoint_restore();
237}
238
239static int hw_break_reserve_slot(int breakno)
240{
241 int cpu;
242 int cnt = 0;
243 struct perf_event **pevent;
244
245 if (dbg_is_early)
246 return 0;
247
248 for_each_online_cpu(cpu) {
249 cnt++;
250 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
251 if (dbg_reserve_bp_slot(*pevent))
252 goto fail;
253 }
254
255 return 0;
256
257fail:
258 for_each_online_cpu(cpu) {
259 cnt--;
260 if (!cnt)
261 break;
262 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
263 dbg_release_bp_slot(*pevent);
264 }
265 return -1;
266}
267
268static int hw_break_release_slot(int breakno)
269{
270 struct perf_event **pevent;
271 int cpu;
272
273 if (dbg_is_early)
274 return 0;
275
276 for_each_online_cpu(cpu) {
277 pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
278 if (dbg_release_bp_slot(*pevent))
279 /*
280 * The debugger is responisble for handing the retry on
281 * remove failure.
282 */
283 return -1;
238 } 284 }
239 if (correctit) 285 return 0;
240 set_debugreg(dr7, 7);
241} 286}
242 287
243static int 288static int
@@ -245,12 +290,16 @@ kgdb_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
245{ 290{
246 int i; 291 int i;
247 292
248 for (i = 0; i < 4; i++) 293 for (i = 0; i < HBP_NUM; i++)
249 if (breakinfo[i].addr == addr && breakinfo[i].enabled) 294 if (breakinfo[i].addr == addr && breakinfo[i].enabled)
250 break; 295 break;
251 if (i == 4) 296 if (i == HBP_NUM)
252 return -1; 297 return -1;
253 298
299 if (hw_break_release_slot(i)) {
300 printk(KERN_ERR "Cannot remove hw breakpoint at %lx\n", addr);
301 return -1;
302 }
254 breakinfo[i].enabled = 0; 303 breakinfo[i].enabled = 0;
255 304
256 return 0; 305 return 0;
@@ -259,46 +308,73 @@ kgdb_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
259static void kgdb_remove_all_hw_break(void) 308static void kgdb_remove_all_hw_break(void)
260{ 309{
261 int i; 310 int i;
311 int cpu = raw_smp_processor_id();
312 struct perf_event *bp;
262 313
263 for (i = 0; i < 4; i++) 314 for (i = 0; i < HBP_NUM; i++) {
264 memset(&breakinfo[i], 0, sizeof(struct hw_breakpoint)); 315 if (!breakinfo[i].enabled)
316 continue;
317 bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
318 if (bp->attr.disabled == 1)
319 continue;
320 if (dbg_is_early)
321 early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
322 breakinfo[i].type);
323 else
324 arch_uninstall_hw_breakpoint(bp);
325 bp->attr.disabled = 1;
326 }
265} 327}
266 328
267static int 329static int
268kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) 330kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
269{ 331{
270 unsigned type;
271 int i; 332 int i;
272 333
273 for (i = 0; i < 4; i++) 334 for (i = 0; i < HBP_NUM; i++)
274 if (!breakinfo[i].enabled) 335 if (!breakinfo[i].enabled)
275 break; 336 break;
276 if (i == 4) 337 if (i == HBP_NUM)
277 return -1; 338 return -1;
278 339
279 switch (bptype) { 340 switch (bptype) {
280 case BP_HARDWARE_BREAKPOINT: 341 case BP_HARDWARE_BREAKPOINT:
281 type = 0; 342 len = 1;
282 len = 1; 343 breakinfo[i].type = X86_BREAKPOINT_EXECUTE;
283 break; 344 break;
284 case BP_WRITE_WATCHPOINT: 345 case BP_WRITE_WATCHPOINT:
285 type = 1; 346 breakinfo[i].type = X86_BREAKPOINT_WRITE;
286 break; 347 break;
287 case BP_ACCESS_WATCHPOINT: 348 case BP_ACCESS_WATCHPOINT:
288 type = 3; 349 breakinfo[i].type = X86_BREAKPOINT_RW;
289 break; 350 break;
290 default: 351 default:
291 return -1; 352 return -1;
292 } 353 }
293 354 switch (len) {
294 if (len == 1 || len == 2 || len == 4) 355 case 1:
295 breakinfo[i].len = len - 1; 356 breakinfo[i].len = X86_BREAKPOINT_LEN_1;
296 else 357 break;
358 case 2:
359 breakinfo[i].len = X86_BREAKPOINT_LEN_2;
360 break;
361 case 4:
362 breakinfo[i].len = X86_BREAKPOINT_LEN_4;
363 break;
364#ifdef CONFIG_X86_64
365 case 8:
366 breakinfo[i].len = X86_BREAKPOINT_LEN_8;
367 break;
368#endif
369 default:
297 return -1; 370 return -1;
298 371 }
299 breakinfo[i].enabled = 1;
300 breakinfo[i].addr = addr; 372 breakinfo[i].addr = addr;
301 breakinfo[i].type = type; 373 if (hw_break_reserve_slot(i)) {
374 breakinfo[i].addr = 0;
375 return -1;
376 }
377 breakinfo[i].enabled = 1;
302 378
303 return 0; 379 return 0;
304} 380}
@@ -313,25 +389,26 @@ kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
313 */ 389 */
314void kgdb_disable_hw_debug(struct pt_regs *regs) 390void kgdb_disable_hw_debug(struct pt_regs *regs)
315{ 391{
392 int i;
393 int cpu = raw_smp_processor_id();
394 struct perf_event *bp;
395
316 /* Disable hardware debugging while we are in kgdb: */ 396 /* Disable hardware debugging while we are in kgdb: */
317 set_debugreg(0UL, 7); 397 set_debugreg(0UL, 7);
318} 398 for (i = 0; i < HBP_NUM; i++) {
319 399 if (!breakinfo[i].enabled)
320/** 400 continue;
321 * kgdb_post_primary_code - Save error vector/code numbers. 401 if (dbg_is_early) {
322 * @regs: Original pt_regs. 402 early_dr7 &= ~encode_dr7(i, breakinfo[i].len,
323 * @e_vector: Original error vector. 403 breakinfo[i].type);
324 * @err_code: Original error code. 404 continue;
325 * 405 }
326 * This is needed on architectures which support SMP and KGDB. 406 bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
327 * This function is called after all the slave cpus have been put 407 if (bp->attr.disabled == 1)
328 * to a know spin state and the primary CPU has control over KGDB. 408 continue;
329 */ 409 arch_uninstall_hw_breakpoint(bp);
330void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code) 410 bp->attr.disabled = 1;
331{ 411 }
332 /* primary processor is completely in the debugger */
333 gdb_x86vector = e_vector;
334 gdb_x86errcode = err_code;
335} 412}
336 413
337#ifdef CONFIG_SMP 414#ifdef CONFIG_SMP
@@ -378,9 +455,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
378 struct pt_regs *linux_regs) 455 struct pt_regs *linux_regs)
379{ 456{
380 unsigned long addr; 457 unsigned long addr;
381 unsigned long dr6;
382 char *ptr; 458 char *ptr;
383 int newPC;
384 459
385 switch (remcomInBuffer[0]) { 460 switch (remcomInBuffer[0]) {
386 case 'c': 461 case 'c':
@@ -391,8 +466,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
391 linux_regs->ip = addr; 466 linux_regs->ip = addr;
392 case 'D': 467 case 'D':
393 case 'k': 468 case 'k':
394 newPC = linux_regs->ip;
395
396 /* clear the trace bit */ 469 /* clear the trace bit */
397 linux_regs->flags &= ~X86_EFLAGS_TF; 470 linux_regs->flags &= ~X86_EFLAGS_TF;
398 atomic_set(&kgdb_cpu_doing_single_step, -1); 471 atomic_set(&kgdb_cpu_doing_single_step, -1);
@@ -404,20 +477,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
404 raw_smp_processor_id()); 477 raw_smp_processor_id());
405 } 478 }
406 479
407 get_debugreg(dr6, 6);
408 if (!(dr6 & 0x4000)) {
409 int breakno;
410
411 for (breakno = 0; breakno < 4; breakno++) {
412 if (dr6 & (1 << breakno) &&
413 breakinfo[breakno].type == 0) {
414 /* Set restore flag: */
415 linux_regs->flags |= X86_EFLAGS_RF;
416 break;
417 }
418 }
419 }
420 set_debugreg(0UL, 6);
421 kgdb_correct_hw_break(); 480 kgdb_correct_hw_break();
422 481
423 return 0; 482 return 0;
@@ -485,8 +544,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
485 break; 544 break;
486 545
487 case DIE_DEBUG: 546 case DIE_DEBUG:
488 if (atomic_read(&kgdb_cpu_doing_single_step) == 547 if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
489 raw_smp_processor_id()) {
490 if (user_mode(regs)) 548 if (user_mode(regs))
491 return single_step_cont(regs, args); 549 return single_step_cont(regs, args);
492 break; 550 break;
@@ -501,7 +559,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
501 return NOTIFY_DONE; 559 return NOTIFY_DONE;
502 } 560 }
503 561
504 if (kgdb_handle_exception(args->trapnr, args->signr, args->err, regs)) 562 if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs))
505 return NOTIFY_DONE; 563 return NOTIFY_DONE;
506 564
507 /* Must touch watchdog before return to normal operation */ 565 /* Must touch watchdog before return to normal operation */
@@ -509,6 +567,24 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
509 return NOTIFY_STOP; 567 return NOTIFY_STOP;
510} 568}
511 569
570int kgdb_ll_trap(int cmd, const char *str,
571 struct pt_regs *regs, long err, int trap, int sig)
572{
573 struct die_args args = {
574 .regs = regs,
575 .str = str,
576 .err = err,
577 .trapnr = trap,
578 .signr = sig,
579
580 };
581
582 if (!kgdb_io_module_registered)
583 return NOTIFY_DONE;
584
585 return __kgdb_notify(&args, cmd);
586}
587
512static int 588static int
513kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) 589kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
514{ 590{
@@ -542,6 +618,51 @@ int kgdb_arch_init(void)
542 return register_die_notifier(&kgdb_notifier); 618 return register_die_notifier(&kgdb_notifier);
543} 619}
544 620
621static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
622 struct perf_sample_data *data, struct pt_regs *regs)
623{
624 kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP);
625}
626
627void kgdb_arch_late(void)
628{
629 int i, cpu;
630 struct perf_event_attr attr;
631 struct perf_event **pevent;
632
633 /*
634 * Pre-allocate the hw breakpoint structions in the non-atomic
635 * portion of kgdb because this operation requires mutexs to
636 * complete.
637 */
638 hw_breakpoint_init(&attr);
639 attr.bp_addr = (unsigned long)kgdb_arch_init;
640 attr.bp_len = HW_BREAKPOINT_LEN_1;
641 attr.bp_type = HW_BREAKPOINT_W;
642 attr.disabled = 1;
643 for (i = 0; i < HBP_NUM; i++) {
644 if (breakinfo[i].pev)
645 continue;
646 breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
647 if (IS_ERR(breakinfo[i].pev)) {
648 printk(KERN_ERR "kgdb: Could not allocate hw"
649 "breakpoints\nDisabling the kernel debugger\n");
650 breakinfo[i].pev = NULL;
651 kgdb_arch_exit();
652 return;
653 }
654 for_each_online_cpu(cpu) {
655 pevent = per_cpu_ptr(breakinfo[i].pev, cpu);
656 pevent[0]->hw.sample_period = 1;
657 pevent[0]->overflow_handler = kgdb_hw_overflow_handler;
658 if (pevent[0]->destroy != NULL) {
659 pevent[0]->destroy = NULL;
660 release_bp_slot(*pevent);
661 }
662 }
663 }
664}
665
545/** 666/**
546 * kgdb_arch_exit - Perform any architecture specific uninitalization. 667 * kgdb_arch_exit - Perform any architecture specific uninitalization.
547 * 668 *
@@ -550,6 +671,13 @@ int kgdb_arch_init(void)
550 */ 671 */
551void kgdb_arch_exit(void) 672void kgdb_arch_exit(void)
552{ 673{
674 int i;
675 for (i = 0; i < 4; i++) {
676 if (breakinfo[i].pev) {
677 unregister_wide_hw_breakpoint(breakinfo[i].pev);
678 breakinfo[i].pev = NULL;
679 }
680 }
553 unregister_die_notifier(&kgdb_notifier); 681 unregister_die_notifier(&kgdb_notifier);
554} 682}
555 683
@@ -582,6 +710,11 @@ unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
582 return instruction_pointer(regs); 710 return instruction_pointer(regs);
583} 711}
584 712
713void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
714{
715 regs->ip = ip;
716}
717
585struct kgdb_arch arch_kgdb_ops = { 718struct kgdb_arch arch_kgdb_ops = {
586 /* Breakpoint instruction: */ 719 /* Breakpoint instruction: */
587 .gdb_bpt_instr = { 0xcc }, 720 .gdb_bpt_instr = { 0xcc },