aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorK.Prasad <prasad@linux.vnet.ibm.com>2009-06-01 14:15:48 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-06-02 16:46:59 -0400
commit72f674d203cd230426437cdcf7dd6f681dad8b0d (patch)
treeeae0f2ad35b579d84232f71415ffb3e4f6fb8c05 /arch/x86
parentda0cdc14f5f7e0faee6b2393fefed056cdb17146 (diff)
hw-breakpoints: modify Ptrace routines to access breakpoint registers
This patch modifies the ptrace code to use the new wrapper routines around the debug/breakpoint registers. [ Impact: adapt x86 ptrace to the new breakpoint Api ] Original-patch-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com> Signed-off-by: Maneesh Soni <maneesh@linux.vnet.ibm.com> Reviewed-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/ptrace.c231
1 files changed, 141 insertions, 90 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 313be40be55a..b457f78b7dbf 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -34,6 +34,7 @@
34#include <asm/prctl.h> 34#include <asm/prctl.h>
35#include <asm/proto.h> 35#include <asm/proto.h>
36#include <asm/ds.h> 36#include <asm/ds.h>
37#include <asm/hw_breakpoint.h>
37 38
38#include <trace/syscall.h> 39#include <trace/syscall.h>
39 40
@@ -136,11 +137,6 @@ static int set_segment_reg(struct task_struct *task,
136 return 0; 137 return 0;
137} 138}
138 139
139static unsigned long debugreg_addr_limit(struct task_struct *task)
140{
141 return TASK_SIZE - 3;
142}
143
144#else /* CONFIG_X86_64 */ 140#else /* CONFIG_X86_64 */
145 141
146#define FLAG_MASK (FLAG_MASK_32 | X86_EFLAGS_NT) 142#define FLAG_MASK (FLAG_MASK_32 | X86_EFLAGS_NT)
@@ -265,15 +261,6 @@ static int set_segment_reg(struct task_struct *task,
265 return 0; 261 return 0;
266} 262}
267 263
268static unsigned long debugreg_addr_limit(struct task_struct *task)
269{
270#ifdef CONFIG_IA32_EMULATION
271 if (test_tsk_thread_flag(task, TIF_IA32))
272 return IA32_PAGE_OFFSET - 3;
273#endif
274 return TASK_SIZE_MAX - 7;
275}
276
277#endif /* CONFIG_X86_32 */ 264#endif /* CONFIG_X86_32 */
278 265
279static unsigned long get_flags(struct task_struct *task) 266static unsigned long get_flags(struct task_struct *task)
@@ -464,95 +451,159 @@ static int genregs_set(struct task_struct *target,
464} 451}
465 452
466/* 453/*
467 * This function is trivial and will be inlined by the compiler. 454 * Decode the length and type bits for a particular breakpoint as
468 * Having it separates the implementation details of debug 455 * stored in debug register 7. Return the "enabled" status.
469 * registers from the interface details of ptrace.
470 */ 456 */
471static unsigned long ptrace_get_debugreg(struct task_struct *child, int n) 457static int decode_dr7(unsigned long dr7, int bpnum, unsigned *len,
458 unsigned *type)
472{ 459{
473 switch (n) { 460 int bp_info = dr7 >> (DR_CONTROL_SHIFT + bpnum * DR_CONTROL_SIZE);
474 case 0: return child->thread.debugreg[0]; 461
475 case 1: return child->thread.debugreg[1]; 462 *len = (bp_info & 0xc) | 0x40;
476 case 2: return child->thread.debugreg[2]; 463 *type = (bp_info & 0x3) | 0x80;
477 case 3: return child->thread.debugreg[3]; 464 return (dr7 >> (bpnum * DR_ENABLE_SIZE)) & 0x3;
478 case 6: return child->thread.debugreg6;
479 case 7: return child->thread.debugreg7;
480 }
481 return 0;
482} 465}
483 466
484static int ptrace_set_debugreg(struct task_struct *child, 467static void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
485 int n, unsigned long data)
486{ 468{
469 struct thread_struct *thread = &(current->thread);
487 int i; 470 int i;
488 471
489 if (unlikely(n == 4 || n == 5)) 472 /*
490 return -EIO; 473 * Store in the virtual DR6 register the fact that the breakpoint
474 * was hit so the thread's debugger will see it.
475 */
476 for (i = 0; i < hbp_kernel_pos; i++)
477 /*
478 * We will check bp->info.address against the address stored in
479 * thread's hbp structure and not debugreg[i]. This is to ensure
480 * that the corresponding bit for 'i' in DR7 register is enabled
481 */
482 if (bp->info.address == thread->hbp[i]->info.address)
483 break;
491 484
492 if (n < 4 && unlikely(data >= debugreg_addr_limit(child))) 485 thread->debugreg6 |= (DR_TRAP0 << i);
493 return -EIO; 486}
494 487
495 switch (n) { 488/*
496 case 0: child->thread.debugreg[0] = data; break; 489 * Handle ptrace writes to debug register 7.
497 case 1: child->thread.debugreg[1] = data; break; 490 */
498 case 2: child->thread.debugreg[2] = data; break; 491static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)
499 case 3: child->thread.debugreg[3] = data; break; 492{
493 struct thread_struct *thread = &(tsk->thread);
494 unsigned long old_dr7 = thread->debugreg7;
495 int i, orig_ret = 0, rc = 0;
496 int enabled, second_pass = 0;
497 unsigned len, type;
498 struct hw_breakpoint *bp;
499
500 data &= ~DR_CONTROL_RESERVED;
501restore:
502 /*
503 * Loop through all the hardware breakpoints, making the
504 * appropriate changes to each.
505 */
506 for (i = 0; i < HBP_NUM; i++) {
507 enabled = decode_dr7(data, i, &len, &type);
508 bp = thread->hbp[i];
509
510 if (!enabled) {
511 if (bp) {
512 /* Don't unregister the breakpoints right-away,
513 * unless all register_user_hw_breakpoint()
514 * requests have succeeded. This prevents
515 * any window of opportunity for debug
516 * register grabbing by other users.
517 */
518 if (!second_pass)
519 continue;
520 unregister_user_hw_breakpoint(tsk, bp);
521 kfree(bp);
522 }
523 continue;
524 }
525 if (!bp) {
526 rc = -ENOMEM;
527 bp = kzalloc(sizeof(struct hw_breakpoint), GFP_KERNEL);
528 if (bp) {
529 bp->info.address = thread->debugreg[i];
530 bp->triggered = ptrace_triggered;
531 bp->info.len = len;
532 bp->info.type = type;
533 rc = register_user_hw_breakpoint(tsk, bp);
534 if (rc)
535 kfree(bp);
536 }
537 } else
538 rc = modify_user_hw_breakpoint(tsk, bp);
539 if (rc)
540 break;
541 }
542 /*
543 * Make a second pass to free the remaining unused breakpoints
544 * or to restore the original breakpoints if an error occurred.
545 */
546 if (!second_pass) {
547 second_pass = 1;
548 if (rc < 0) {
549 orig_ret = rc;
550 data = old_dr7;
551 }
552 goto restore;
553 }
554 return ((orig_ret < 0) ? orig_ret : rc);
555}
500 556
501 case 6: 557/*
502 if ((data & ~0xffffffffUL) != 0) 558 * Handle PTRACE_PEEKUSR calls for the debug register area.
503 return -EIO; 559 */
504 child->thread.debugreg6 = data; 560unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)
505 break; 561{
562 struct thread_struct *thread = &(tsk->thread);
563 unsigned long val = 0;
564
565 if (n < HBP_NUM)
566 val = thread->debugreg[n];
567 else if (n == 6)
568 val = thread->debugreg6;
569 else if (n == 7)
570 val = thread->debugreg7;
571 return val;
572}
506 573
507 case 7: 574/*
508 /* 575 * Handle PTRACE_POKEUSR calls for the debug register area.
509 * Sanity-check data. Take one half-byte at once with 576 */
510 * check = (val >> (16 + 4*i)) & 0xf. It contains the 577int ptrace_set_debugreg(struct task_struct *tsk, int n, unsigned long val)
511 * R/Wi and LENi bits; bits 0 and 1 are R/Wi, and bits 578{
512 * 2 and 3 are LENi. Given a list of invalid values, 579 struct thread_struct *thread = &(tsk->thread);
513 * we do mask |= 1 << invalid_value, so that 580 int rc = 0;
514 * (mask >> check) & 1 is a correct test for invalid 581
515 * values. 582 /* There are no DR4 or DR5 registers */
516 * 583 if (n == 4 || n == 5)
517 * R/Wi contains the type of the breakpoint / 584 return -EIO;
518 * watchpoint, LENi contains the length of the watched 585
519 * data in the watchpoint case. 586 if (n == 6) {
520 * 587 tsk->thread.debugreg6 = val;
521 * The invalid values are: 588 goto ret_path;
522 * - LENi == 0x10 (undefined), so mask |= 0x0f00. [32-bit]
523 * - R/Wi == 0x10 (break on I/O reads or writes), so
524 * mask |= 0x4444.
525 * - R/Wi == 0x00 && LENi != 0x00, so we have mask |=
526 * 0x1110.
527 *
528 * Finally, mask = 0x0f00 | 0x4444 | 0x1110 == 0x5f54.
529 *
530 * See the Intel Manual "System Programming Guide",
531 * 15.2.4
532 *
533 * Note that LENi == 0x10 is defined on x86_64 in long
534 * mode (i.e. even for 32-bit userspace software, but
535 * 64-bit kernel), so the x86_64 mask value is 0x5454.
536 * See the AMD manual no. 24593 (AMD64 System Programming)
537 */
538#ifdef CONFIG_X86_32
539#define DR7_MASK 0x5f54
540#else
541#define DR7_MASK 0x5554
542#endif
543 data &= ~DR_CONTROL_RESERVED;
544 for (i = 0; i < 4; i++)
545 if ((DR7_MASK >> ((data >> (16 + 4*i)) & 0xf)) & 1)
546 return -EIO;
547 child->thread.debugreg7 = data;
548 if (data)
549 set_tsk_thread_flag(child, TIF_DEBUG);
550 else
551 clear_tsk_thread_flag(child, TIF_DEBUG);
552 break;
553 } 589 }
590 if (n < HBP_NUM) {
591 if (thread->hbp[n]) {
592 if (arch_check_va_in_userspace(val,
593 thread->hbp[n]->info.len) == 0) {
594 rc = -EIO;
595 goto ret_path;
596 }
597 thread->hbp[n]->info.address = val;
598 }
599 thread->debugreg[n] = val;
600 }
601 /* All that's left is DR7 */
602 if (n == 7)
603 rc = ptrace_write_dr7(tsk, val);
554 604
555 return 0; 605ret_path:
606 return rc;
556} 607}
557 608
558/* 609/*