diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/powerpc/kernel/entry_32.S | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/process.c | 46 | ||||
| -rw-r--r-- | arch/powerpc/kernel/ptrace.c | 72 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/mm/fault.c | 25 |
6 files changed, 136 insertions, 35 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index da52269aec1e..81c8324a4a3c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
| @@ -148,7 +148,7 @@ transfer_to_handler: | |||
| 148 | /* Check to see if the dbcr0 register is set up to debug. Use the | 148 | /* Check to see if the dbcr0 register is set up to debug. Use the |
| 149 | internal debug mode bit to do this. */ | 149 | internal debug mode bit to do this. */ |
| 150 | lwz r12,THREAD_DBCR0(r12) | 150 | lwz r12,THREAD_DBCR0(r12) |
| 151 | andis. r12,r12,DBCR0_IDM@h | 151 | andis. r12,r12,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h |
| 152 | beq+ 3f | 152 | beq+ 3f |
| 153 | /* From user and task is ptraced - load up global dbcr0 */ | 153 | /* From user and task is ptraced - load up global dbcr0 */ |
| 154 | li r12,-1 /* clear all pending debug events */ | 154 | li r12,-1 /* clear all pending debug events */ |
| @@ -292,7 +292,7 @@ syscall_exit_cont: | |||
| 292 | /* If the process has its own DBCR0 value, load it up. The internal | 292 | /* If the process has its own DBCR0 value, load it up. The internal |
| 293 | debug mode bit tells us that dbcr0 should be loaded. */ | 293 | debug mode bit tells us that dbcr0 should be loaded. */ |
| 294 | lwz r0,THREAD+THREAD_DBCR0(r2) | 294 | lwz r0,THREAD+THREAD_DBCR0(r2) |
| 295 | andis. r10,r0,DBCR0_IDM@h | 295 | andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h |
| 296 | bnel- load_dbcr0 | 296 | bnel- load_dbcr0 |
| 297 | #endif | 297 | #endif |
| 298 | #ifdef CONFIG_44x | 298 | #ifdef CONFIG_44x |
| @@ -720,7 +720,7 @@ restore_user: | |||
| 720 | /* Check whether this process has its own DBCR0 value. The internal | 720 | /* Check whether this process has its own DBCR0 value. The internal |
| 721 | debug mode bit tells us that dbcr0 should be loaded. */ | 721 | debug mode bit tells us that dbcr0 should be loaded. */ |
| 722 | lwz r0,THREAD+THREAD_DBCR0(r2) | 722 | lwz r0,THREAD+THREAD_DBCR0(r2) |
| 723 | andis. r10,r0,DBCR0_IDM@h | 723 | andis. r10,r0,(DBCR0_IDM | DBSR_DAC1R | DBSR_DAC1W)@h |
| 724 | bnel- load_dbcr0 | 724 | bnel- load_dbcr0 |
| 725 | #endif | 725 | #endif |
| 726 | 726 | ||
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 219f3634115e..db2497ccc111 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -47,6 +47,8 @@ | |||
| 47 | #ifdef CONFIG_PPC64 | 47 | #ifdef CONFIG_PPC64 |
| 48 | #include <asm/firmware.h> | 48 | #include <asm/firmware.h> |
| 49 | #endif | 49 | #endif |
| 50 | #include <linux/kprobes.h> | ||
| 51 | #include <linux/kdebug.h> | ||
| 50 | 52 | ||
| 51 | extern unsigned long _get_SP(void); | 53 | extern unsigned long _get_SP(void); |
| 52 | 54 | ||
| @@ -239,6 +241,35 @@ void discard_lazy_cpu_state(void) | |||
| 239 | } | 241 | } |
| 240 | #endif /* CONFIG_SMP */ | 242 | #endif /* CONFIG_SMP */ |
| 241 | 243 | ||
| 244 | void do_dabr(struct pt_regs *regs, unsigned long address, | ||
| 245 | unsigned long error_code) | ||
| 246 | { | ||
| 247 | siginfo_t info; | ||
| 248 | |||
| 249 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
| 250 | 11, SIGSEGV) == NOTIFY_STOP) | ||
| 251 | return; | ||
| 252 | |||
| 253 | if (debugger_dabr_match(regs)) | ||
| 254 | return; | ||
| 255 | |||
| 256 | /* Clear the DAC and struct entries. One shot trigger */ | ||
| 257 | #if (defined(CONFIG_44x) || defined(CONFIG_BOOKE)) | ||
| 258 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W | ||
| 259 | | DBCR0_IDM)); | ||
| 260 | #endif | ||
| 261 | |||
| 262 | /* Clear the DABR */ | ||
| 263 | set_dabr(0); | ||
| 264 | |||
| 265 | /* Deliver the signal to userspace */ | ||
| 266 | info.si_signo = SIGTRAP; | ||
| 267 | info.si_errno = 0; | ||
| 268 | info.si_code = TRAP_HWBKPT; | ||
| 269 | info.si_addr = (void __user *)address; | ||
| 270 | force_sig_info(SIGTRAP, &info, current); | ||
| 271 | } | ||
| 272 | |||
| 242 | static DEFINE_PER_CPU(unsigned long, current_dabr); | 273 | static DEFINE_PER_CPU(unsigned long, current_dabr); |
| 243 | 274 | ||
| 244 | int set_dabr(unsigned long dabr) | 275 | int set_dabr(unsigned long dabr) |
| @@ -254,6 +285,11 @@ int set_dabr(unsigned long dabr) | |||
| 254 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) | 285 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) |
| 255 | mtspr(SPRN_DABR, dabr); | 286 | mtspr(SPRN_DABR, dabr); |
| 256 | #endif | 287 | #endif |
| 288 | |||
| 289 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 290 | mtspr(SPRN_DAC1, dabr); | ||
| 291 | #endif | ||
| 292 | |||
| 257 | return 0; | 293 | return 0; |
| 258 | } | 294 | } |
| 259 | 295 | ||
| @@ -337,6 +373,12 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 337 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | 373 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) |
| 338 | set_dabr(new->thread.dabr); | 374 | set_dabr(new->thread.dabr); |
| 339 | 375 | ||
| 376 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 377 | /* If new thread DAC (HW breakpoint) is the same then leave it */ | ||
| 378 | if (new->thread.dabr) | ||
| 379 | set_dabr(new->thread.dabr); | ||
| 380 | #endif | ||
| 381 | |||
| 340 | new_thread = &new->thread; | 382 | new_thread = &new->thread; |
| 341 | old_thread = ¤t->thread; | 383 | old_thread = ¤t->thread; |
| 342 | 384 | ||
| @@ -525,6 +567,10 @@ void flush_thread(void) | |||
| 525 | if (current->thread.dabr) { | 567 | if (current->thread.dabr) { |
| 526 | current->thread.dabr = 0; | 568 | current->thread.dabr = 0; |
| 527 | set_dabr(0); | 569 | set_dabr(0); |
| 570 | |||
| 571 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 572 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W); | ||
| 573 | #endif | ||
| 528 | } | 574 | } |
| 529 | } | 575 | } |
| 530 | 576 | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 8feb93e7890c..a5d0e78779c8 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task) | |||
| 703 | 703 | ||
| 704 | if (regs != NULL) { | 704 | if (regs != NULL) { |
| 705 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 705 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
| 706 | task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; | 706 | task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; |
| 707 | regs->msr |= MSR_DE; | 707 | regs->msr |= MSR_DE; |
| 708 | #else | 708 | #else |
| 709 | regs->msr |= MSR_SE; | 709 | regs->msr |= MSR_SE; |
| @@ -716,9 +716,16 @@ void user_disable_single_step(struct task_struct *task) | |||
| 716 | { | 716 | { |
| 717 | struct pt_regs *regs = task->thread.regs; | 717 | struct pt_regs *regs = task->thread.regs; |
| 718 | 718 | ||
| 719 | |||
| 720 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 721 | /* If DAC then do not single step, skip */ | ||
| 722 | if (task->thread.dabr) | ||
| 723 | return; | ||
| 724 | #endif | ||
| 725 | |||
| 719 | if (regs != NULL) { | 726 | if (regs != NULL) { |
| 720 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 727 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) |
| 721 | task->thread.dbcr0 = 0; | 728 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_IDM); |
| 722 | regs->msr &= ~MSR_DE; | 729 | regs->msr &= ~MSR_DE; |
| 723 | #else | 730 | #else |
| 724 | regs->msr &= ~MSR_SE; | 731 | regs->msr &= ~MSR_SE; |
| @@ -727,22 +734,75 @@ void user_disable_single_step(struct task_struct *task) | |||
| 727 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | 734 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); |
| 728 | } | 735 | } |
| 729 | 736 | ||
| 730 | static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | 737 | int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, |
| 731 | unsigned long data) | 738 | unsigned long data) |
| 732 | { | 739 | { |
| 733 | /* We only support one DABR and no IABRS at the moment */ | 740 | /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). |
| 741 | * For embedded processors we support one DAC and no IAC's at the | ||
| 742 | * moment. | ||
| 743 | */ | ||
| 734 | if (addr > 0) | 744 | if (addr > 0) |
| 735 | return -EINVAL; | 745 | return -EINVAL; |
| 736 | 746 | ||
| 737 | /* The bottom 3 bits are flags */ | ||
| 738 | if ((data & ~0x7UL) >= TASK_SIZE) | 747 | if ((data & ~0x7UL) >= TASK_SIZE) |
| 739 | return -EIO; | 748 | return -EIO; |
| 740 | 749 | ||
| 741 | /* Ensure translation is on */ | 750 | #ifdef CONFIG_PPC64 |
| 751 | |||
| 752 | /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. | ||
| 753 | * It was assumed, on previous implementations, that 3 bits were | ||
| 754 | * passed together with the data address, fitting the design of the | ||
| 755 | * DABR register, as follows: | ||
| 756 | * | ||
| 757 | * bit 0: Read flag | ||
| 758 | * bit 1: Write flag | ||
| 759 | * bit 2: Breakpoint translation | ||
| 760 | * | ||
| 761 | * Thus, we use them here as so. | ||
| 762 | */ | ||
| 763 | |||
| 764 | /* Ensure breakpoint translation bit is set */ | ||
| 742 | if (data && !(data & DABR_TRANSLATION)) | 765 | if (data && !(data & DABR_TRANSLATION)) |
| 743 | return -EIO; | 766 | return -EIO; |
| 744 | 767 | ||
| 768 | /* Move contents to the DABR register */ | ||
| 745 | task->thread.dabr = data; | 769 | task->thread.dabr = data; |
| 770 | |||
| 771 | #endif | ||
| 772 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 773 | |||
| 774 | /* As described above, it was assumed 3 bits were passed with the data | ||
| 775 | * address, but we will assume only the mode bits will be passed | ||
| 776 | * as to not cause alignment restrictions for DAC-based processors. | ||
| 777 | */ | ||
| 778 | |||
| 779 | /* DAC's hold the whole address without any mode flags */ | ||
| 780 | task->thread.dabr = data & ~0x3UL; | ||
| 781 | |||
| 782 | if (task->thread.dabr == 0) { | ||
| 783 | task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM); | ||
| 784 | task->thread.regs->msr &= ~MSR_DE; | ||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | |||
| 788 | /* Read or Write bits must be set */ | ||
| 789 | |||
| 790 | if (!(data & 0x3UL)) | ||
| 791 | return -EINVAL; | ||
| 792 | |||
| 793 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 | ||
| 794 | register */ | ||
| 795 | task->thread.dbcr0 = DBCR0_IDM; | ||
| 796 | |||
| 797 | /* Check for write and read flags and set DBCR0 | ||
| 798 | accordingly */ | ||
| 799 | if (data & 0x1UL) | ||
| 800 | task->thread.dbcr0 |= DBSR_DAC1R; | ||
| 801 | if (data & 0x2UL) | ||
| 802 | task->thread.dbcr0 |= DBSR_DAC1W; | ||
| 803 | |||
| 804 | task->thread.regs->msr |= MSR_DE; | ||
| 805 | #endif | ||
| 746 | return 0; | 806 | return 0; |
| 747 | } | 807 | } |
| 748 | 808 | ||
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index ad55488939c3..7aada783ec6a 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -145,8 +145,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
| 145 | * user space. The DABR will have been cleared if it | 145 | * user space. The DABR will have been cleared if it |
| 146 | * triggered inside the kernel. | 146 | * triggered inside the kernel. |
| 147 | */ | 147 | */ |
| 148 | if (current->thread.dabr) | 148 | if (current->thread.dabr) { |
| 149 | set_dabr(current->thread.dabr); | 149 | set_dabr(current->thread.dabr); |
| 150 | #if defined(CONFIG_44x) || defined(CONFIG_BOOKE) | ||
| 151 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | ||
| 152 | #endif | ||
| 153 | } | ||
| 150 | 154 | ||
| 151 | if (is32) { | 155 | if (is32) { |
| 152 | if (ka.sa.sa_flags & SA_SIGINFO) | 156 | if (ka.sa.sa_flags & SA_SIGINFO) |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 878fbddb6ae1..81ccb8dd1a54 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -1067,6 +1067,22 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | |||
| 1067 | } | 1067 | } |
| 1068 | 1068 | ||
| 1069 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); | 1069 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); |
| 1070 | } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | ||
| 1071 | regs->msr &= ~MSR_DE; | ||
| 1072 | |||
| 1073 | if (user_mode(regs)) { | ||
| 1074 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | | ||
| 1075 | DBCR0_IDM); | ||
| 1076 | } else { | ||
| 1077 | /* Disable DAC interupts */ | ||
| 1078 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | | ||
| 1079 | DBSR_DAC1W | DBCR0_IDM)); | ||
| 1080 | |||
| 1081 | /* Clear the DAC event */ | ||
| 1082 | mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W)); | ||
| 1083 | } | ||
| 1084 | /* Setup and send the trap to the handler */ | ||
| 1085 | do_dabr(regs, mfspr(SPRN_DAC1), debug_status); | ||
| 1070 | } | 1086 | } |
| 1071 | } | 1087 | } |
| 1072 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ | 1088 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 1707d00331fc..565b7a237c84 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -100,31 +100,6 @@ static int store_updates_sp(struct pt_regs *regs) | |||
| 100 | return 0; | 100 | return 0; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | ||
| 104 | static void do_dabr(struct pt_regs *regs, unsigned long address, | ||
| 105 | unsigned long error_code) | ||
| 106 | { | ||
| 107 | siginfo_t info; | ||
| 108 | |||
| 109 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
| 110 | 11, SIGSEGV) == NOTIFY_STOP) | ||
| 111 | return; | ||
| 112 | |||
| 113 | if (debugger_dabr_match(regs)) | ||
| 114 | return; | ||
| 115 | |||
| 116 | /* Clear the DABR */ | ||
| 117 | set_dabr(0); | ||
| 118 | |||
| 119 | /* Deliver the signal to userspace */ | ||
| 120 | info.si_signo = SIGTRAP; | ||
| 121 | info.si_errno = 0; | ||
| 122 | info.si_code = TRAP_HWBKPT; | ||
| 123 | info.si_addr = (void __user *)address; | ||
| 124 | force_sig_info(SIGTRAP, &info, current); | ||
| 125 | } | ||
| 126 | #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/ | ||
| 127 | |||
| 128 | /* | 103 | /* |
| 129 | * For 600- and 800-family processors, the error_code parameter is DSISR | 104 | * For 600- and 800-family processors, the error_code parameter is DSISR |
| 130 | * for a data fault, SRR1 for an instruction fault. For 400-family processors | 105 | * for a data fault, SRR1 for an instruction fault. For 400-family processors |
