diff options
| -rw-r--r-- | arch/powerpc/include/asm/system.h | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/process.c | 110 | ||||
| -rw-r--r-- | arch/powerpc/kernel/ptrace.c | 434 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_32.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 91 |
6 files changed, 582 insertions, 72 deletions
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h index aa59f5b794e8..a6297c67c3d6 100644 --- a/arch/powerpc/include/asm/system.h +++ b/arch/powerpc/include/asm/system.h | |||
| @@ -112,8 +112,13 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } | |||
| 112 | #endif | 112 | #endif |
| 113 | 113 | ||
| 114 | extern int set_dabr(unsigned long dabr); | 114 | extern int set_dabr(unsigned long dabr); |
| 115 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 116 | extern void do_send_trap(struct pt_regs *regs, unsigned long address, | ||
| 117 | unsigned long error_code, int signal_code, int brkpt); | ||
| 118 | #else | ||
| 115 | extern void do_dabr(struct pt_regs *regs, unsigned long address, | 119 | extern void do_dabr(struct pt_regs *regs, unsigned long address, |
| 116 | unsigned long error_code); | 120 | unsigned long error_code); |
| 121 | #endif | ||
| 117 | extern void print_backtrace(unsigned long *); | 122 | extern void print_backtrace(unsigned long *); |
| 118 | extern void show_regs(struct pt_regs * regs); | 123 | extern void show_regs(struct pt_regs * regs); |
| 119 | extern void flush_instruction_cache(void); | 124 | extern void flush_instruction_cache(void); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 9be77e3936fb..e4d71ced97ef 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -245,6 +245,24 @@ void discard_lazy_cpu_state(void) | |||
| 245 | } | 245 | } |
| 246 | #endif /* CONFIG_SMP */ | 246 | #endif /* CONFIG_SMP */ |
| 247 | 247 | ||
| 248 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 249 | void do_send_trap(struct pt_regs *regs, unsigned long address, | ||
| 250 | unsigned long error_code, int signal_code, int breakpt) | ||
| 251 | { | ||
| 252 | siginfo_t info; | ||
| 253 | |||
| 254 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
| 255 | 11, SIGSEGV) == NOTIFY_STOP) | ||
| 256 | return; | ||
| 257 | |||
| 258 | /* Deliver the signal to userspace */ | ||
| 259 | info.si_signo = SIGTRAP; | ||
| 260 | info.si_errno = breakpt; /* breakpoint or watchpoint id */ | ||
| 261 | info.si_code = signal_code; | ||
| 262 | info.si_addr = (void __user *)address; | ||
| 263 | force_sig_info(SIGTRAP, &info, current); | ||
| 264 | } | ||
| 265 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 248 | void do_dabr(struct pt_regs *regs, unsigned long address, | 266 | void do_dabr(struct pt_regs *regs, unsigned long address, |
| 249 | unsigned long error_code) | 267 | unsigned long error_code) |
| 250 | { | 268 | { |
| @@ -257,12 +275,6 @@ void do_dabr(struct pt_regs *regs, unsigned long address, | |||
| 257 | if (debugger_dabr_match(regs)) | 275 | if (debugger_dabr_match(regs)) |
| 258 | return; | 276 | return; |
| 259 | 277 | ||
| 260 | /* Clear the DAC and struct entries. One shot trigger */ | ||
| 261 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 262 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W | ||
| 263 | | DBCR0_IDM)); | ||
| 264 | #endif | ||
| 265 | |||
| 266 | /* Clear the DABR */ | 278 | /* Clear the DABR */ |
| 267 | set_dabr(0); | 279 | set_dabr(0); |
| 268 | 280 | ||
| @@ -273,9 +285,82 @@ void do_dabr(struct pt_regs *regs, unsigned long address, | |||
| 273 | info.si_addr = (void __user *)address; | 285 | info.si_addr = (void __user *)address; |
| 274 | force_sig_info(SIGTRAP, &info, current); | 286 | force_sig_info(SIGTRAP, &info, current); |
| 275 | } | 287 | } |
| 288 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 276 | 289 | ||
| 277 | static DEFINE_PER_CPU(unsigned long, current_dabr); | 290 | static DEFINE_PER_CPU(unsigned long, current_dabr); |
| 278 | 291 | ||
| 292 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 293 | /* | ||
| 294 | * Set the debug registers back to their default "safe" values. | ||
| 295 | */ | ||
| 296 | static void set_debug_reg_defaults(struct thread_struct *thread) | ||
| 297 | { | ||
| 298 | thread->iac1 = thread->iac2 = 0; | ||
| 299 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 300 | thread->iac3 = thread->iac4 = 0; | ||
| 301 | #endif | ||
| 302 | thread->dac1 = thread->dac2 = 0; | ||
| 303 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 304 | thread->dvc1 = thread->dvc2 = 0; | ||
| 305 | #endif | ||
| 306 | thread->dbcr0 = 0; | ||
| 307 | #ifdef CONFIG_BOOKE | ||
| 308 | /* | ||
| 309 | * Force User/Supervisor bits to b11 (user-only MSR[PR]=1) | ||
| 310 | */ | ||
| 311 | thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | \ | ||
| 312 | DBCR1_IAC3US | DBCR1_IAC4US; | ||
| 313 | /* | ||
| 314 | * Force Data Address Compare User/Supervisor bits to be User-only | ||
| 315 | * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0. | ||
| 316 | */ | ||
| 317 | thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; | ||
| 318 | #else | ||
| 319 | thread->dbcr1 = 0; | ||
| 320 | #endif | ||
| 321 | } | ||
| 322 | |||
| 323 | static void prime_debug_regs(struct thread_struct *thread) | ||
| 324 | { | ||
| 325 | mtspr(SPRN_IAC1, thread->iac1); | ||
| 326 | mtspr(SPRN_IAC2, thread->iac2); | ||
| 327 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 328 | mtspr(SPRN_IAC3, thread->iac3); | ||
| 329 | mtspr(SPRN_IAC4, thread->iac4); | ||
| 330 | #endif | ||
| 331 | mtspr(SPRN_DAC1, thread->dac1); | ||
| 332 | mtspr(SPRN_DAC2, thread->dac2); | ||
| 333 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 334 | mtspr(SPRN_DVC1, thread->dvc1); | ||
| 335 | mtspr(SPRN_DVC2, thread->dvc2); | ||
| 336 | #endif | ||
| 337 | mtspr(SPRN_DBCR0, thread->dbcr0); | ||
| 338 | mtspr(SPRN_DBCR1, thread->dbcr1); | ||
| 339 | #ifdef CONFIG_BOOKE | ||
| 340 | mtspr(SPRN_DBCR2, thread->dbcr2); | ||
| 341 | #endif | ||
| 342 | } | ||
| 343 | /* | ||
| 344 | * Unless neither the old or new thread are making use of the | ||
| 345 | * debug registers, set the debug registers from the values | ||
| 346 | * stored in the new thread. | ||
| 347 | */ | ||
| 348 | static void switch_booke_debug_regs(struct thread_struct *new_thread) | ||
| 349 | { | ||
| 350 | if ((current->thread.dbcr0 & DBCR0_IDM) | ||
| 351 | || (new_thread->dbcr0 & DBCR0_IDM)) | ||
| 352 | prime_debug_regs(new_thread); | ||
| 353 | } | ||
| 354 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 355 | static void set_debug_reg_defaults(struct thread_struct *thread) | ||
| 356 | { | ||
| 357 | if (thread->dabr) { | ||
| 358 | thread->dabr = 0; | ||
| 359 | set_dabr(0); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 363 | |||
| 279 | int set_dabr(unsigned long dabr) | 364 | int set_dabr(unsigned long dabr) |
| 280 | { | 365 | { |
| 281 | __get_cpu_var(current_dabr) = dabr; | 366 | __get_cpu_var(current_dabr) = dabr; |
| @@ -372,9 +457,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 372 | #endif /* CONFIG_SMP */ | 457 | #endif /* CONFIG_SMP */ |
| 373 | 458 | ||
| 374 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 459 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 375 | /* If new thread DAC (HW breakpoint) is the same then leave it */ | 460 | switch_booke_debug_regs(&new->thread); |
| 376 | if (new->thread.dabr) | ||
| 377 | set_dabr(new->thread.dabr); | ||
| 378 | #else | 461 | #else |
| 379 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | 462 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) |
| 380 | set_dabr(new->thread.dabr); | 463 | set_dabr(new->thread.dabr); |
| @@ -556,14 +639,7 @@ void flush_thread(void) | |||
| 556 | { | 639 | { |
| 557 | discard_lazy_cpu_state(); | 640 | discard_lazy_cpu_state(); |
| 558 | 641 | ||
| 559 | if (current->thread.dabr) { | 642 | set_debug_reg_defaults(¤t->thread); |
| 560 | current->thread.dabr = 0; | ||
| 561 | set_dabr(0); | ||
| 562 | |||
| 563 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 564 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W); | ||
| 565 | #endif | ||
| 566 | } | ||
| 567 | } | 643 | } |
| 568 | 644 | ||
| 569 | void | 645 | void |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 8847bd618cec..d9b05866615f 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -738,11 +738,22 @@ void user_disable_single_step(struct task_struct *task) | |||
| 738 | 738 | ||
| 739 | if (regs != NULL) { | 739 | if (regs != NULL) { |
| 740 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 740 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 741 | /* If DAC don't clear DBCRO_IDM or MSR_DE */ | 741 | /* |
| 742 | if (task->thread.dabr) | 742 | * The logic to disable single stepping should be as |
| 743 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT); | 743 | * simple as turning off the Instruction Complete flag. |
| 744 | else { | 744 | * And, after doing so, if all debug flags are off, turn |
| 745 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | 745 | * off DBCR0(IDM) and MSR(DE) .... Torez |
| 746 | */ | ||
| 747 | task->thread.dbcr0 &= ~DBCR0_IC; | ||
| 748 | /* | ||
| 749 | * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set. | ||
| 750 | */ | ||
| 751 | if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, | ||
| 752 | task->thread.dbcr1)) { | ||
| 753 | /* | ||
| 754 | * All debug events were off..... | ||
| 755 | */ | ||
| 756 | task->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 746 | regs->msr &= ~MSR_DE; | 757 | regs->msr &= ~MSR_DE; |
| 747 | } | 758 | } |
| 748 | #else | 759 | #else |
| @@ -767,7 +778,6 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
| 767 | return -EIO; | 778 | return -EIO; |
| 768 | 779 | ||
| 769 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | 780 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS |
| 770 | |||
| 771 | /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. | 781 | /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. |
| 772 | * It was assumed, on previous implementations, that 3 bits were | 782 | * It was assumed, on previous implementations, that 3 bits were |
| 773 | * passed together with the data address, fitting the design of the | 783 | * passed together with the data address, fitting the design of the |
| @@ -786,20 +796,22 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
| 786 | 796 | ||
| 787 | /* Move contents to the DABR register */ | 797 | /* Move contents to the DABR register */ |
| 788 | task->thread.dabr = data; | 798 | task->thread.dabr = data; |
| 789 | |||
| 790 | #else /* CONFIG_PPC_ADV_DEBUG_REGS */ | 799 | #else /* CONFIG_PPC_ADV_DEBUG_REGS */ |
| 791 | |||
| 792 | /* As described above, it was assumed 3 bits were passed with the data | 800 | /* As described above, it was assumed 3 bits were passed with the data |
| 793 | * address, but we will assume only the mode bits will be passed | 801 | * address, but we will assume only the mode bits will be passed |
| 794 | * as to not cause alignment restrictions for DAC-based processors. | 802 | * as to not cause alignment restrictions for DAC-based processors. |
| 795 | */ | 803 | */ |
| 796 | 804 | ||
| 797 | /* DAC's hold the whole address without any mode flags */ | 805 | /* DAC's hold the whole address without any mode flags */ |
| 798 | task->thread.dabr = data & ~0x3UL; | 806 | task->thread.dac1 = data & ~0x3UL; |
| 799 | 807 | ||
| 800 | if (task->thread.dabr == 0) { | 808 | if (task->thread.dac1 == 0) { |
| 801 | task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM); | 809 | dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W); |
| 802 | task->thread.regs->msr &= ~MSR_DE; | 810 | if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, |
| 811 | task->thread.dbcr1)) { | ||
| 812 | task->thread.regs->msr &= ~MSR_DE; | ||
| 813 | task->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 814 | } | ||
| 803 | return 0; | 815 | return 0; |
| 804 | } | 816 | } |
| 805 | 817 | ||
| @@ -810,15 +822,15 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
| 810 | 822 | ||
| 811 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 | 823 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 |
| 812 | register */ | 824 | register */ |
| 813 | task->thread.dbcr0 = DBCR0_IDM; | 825 | task->thread.dbcr0 |= DBCR0_IDM; |
| 814 | 826 | ||
| 815 | /* Check for write and read flags and set DBCR0 | 827 | /* Check for write and read flags and set DBCR0 |
| 816 | accordingly */ | 828 | accordingly */ |
| 829 | dbcr_dac(task) &= ~(DBCR_DAC1R|DBCR_DAC1W); | ||
| 817 | if (data & 0x1UL) | 830 | if (data & 0x1UL) |
| 818 | task->thread.dbcr0 |= DBSR_DAC1R; | 831 | dbcr_dac(task) |= DBCR_DAC1R; |
| 819 | if (data & 0x2UL) | 832 | if (data & 0x2UL) |
| 820 | task->thread.dbcr0 |= DBSR_DAC1W; | 833 | dbcr_dac(task) |= DBCR_DAC1W; |
| 821 | |||
| 822 | task->thread.regs->msr |= MSR_DE; | 834 | task->thread.regs->msr |= MSR_DE; |
| 823 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | 835 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ |
| 824 | return 0; | 836 | return 0; |
| @@ -835,11 +847,344 @@ void ptrace_disable(struct task_struct *child) | |||
| 835 | user_disable_single_step(child); | 847 | user_disable_single_step(child); |
| 836 | } | 848 | } |
| 837 | 849 | ||
| 850 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 851 | static long set_intruction_bp(struct task_struct *child, | ||
| 852 | struct ppc_hw_breakpoint *bp_info) | ||
| 853 | { | ||
| 854 | int slot; | ||
| 855 | int slot1_in_use = ((child->thread.dbcr0 & DBCR0_IAC1) != 0); | ||
| 856 | int slot2_in_use = ((child->thread.dbcr0 & DBCR0_IAC2) != 0); | ||
| 857 | int slot3_in_use = ((child->thread.dbcr0 & DBCR0_IAC3) != 0); | ||
| 858 | int slot4_in_use = ((child->thread.dbcr0 & DBCR0_IAC4) != 0); | ||
| 859 | |||
| 860 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | ||
| 861 | slot2_in_use = 1; | ||
| 862 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) | ||
| 863 | slot4_in_use = 1; | ||
| 864 | |||
| 865 | if (bp_info->addr >= TASK_SIZE) | ||
| 866 | return -EIO; | ||
| 867 | |||
| 868 | if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) { | ||
| 869 | |||
| 870 | /* Make sure range is valid. */ | ||
| 871 | if (bp_info->addr2 >= TASK_SIZE) | ||
| 872 | return -EIO; | ||
| 873 | |||
| 874 | /* We need a pair of IAC regsisters */ | ||
| 875 | if ((!slot1_in_use) && (!slot2_in_use)) { | ||
| 876 | slot = 1; | ||
| 877 | child->thread.iac1 = bp_info->addr; | ||
| 878 | child->thread.iac2 = bp_info->addr2; | ||
| 879 | child->thread.dbcr0 |= DBCR0_IAC1; | ||
| 880 | if (bp_info->addr_mode == | ||
| 881 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | ||
| 882 | dbcr_iac_range(child) |= DBCR_IAC12X; | ||
| 883 | else | ||
| 884 | dbcr_iac_range(child) |= DBCR_IAC12I; | ||
| 885 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 886 | } else if ((!slot3_in_use) && (!slot4_in_use)) { | ||
| 887 | slot = 3; | ||
| 888 | child->thread.iac3 = bp_info->addr; | ||
| 889 | child->thread.iac4 = bp_info->addr2; | ||
| 890 | child->thread.dbcr0 |= DBCR0_IAC3; | ||
| 891 | if (bp_info->addr_mode == | ||
| 892 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | ||
| 893 | dbcr_iac_range(child) |= DBCR_IAC34X; | ||
| 894 | else | ||
| 895 | dbcr_iac_range(child) |= DBCR_IAC34I; | ||
| 896 | #endif | ||
| 897 | } else | ||
| 898 | return -ENOSPC; | ||
| 899 | } else { | ||
| 900 | /* We only need one. If possible leave a pair free in | ||
| 901 | * case a range is needed later | ||
| 902 | */ | ||
| 903 | if (!slot1_in_use) { | ||
| 904 | /* | ||
| 905 | * Don't use iac1 if iac1-iac2 are free and either | ||
| 906 | * iac3 or iac4 (but not both) are free | ||
| 907 | */ | ||
| 908 | if (slot2_in_use || (slot3_in_use == slot4_in_use)) { | ||
| 909 | slot = 1; | ||
| 910 | child->thread.iac1 = bp_info->addr; | ||
| 911 | child->thread.dbcr0 |= DBCR0_IAC1; | ||
| 912 | goto out; | ||
| 913 | } | ||
| 914 | } | ||
| 915 | if (!slot2_in_use) { | ||
| 916 | slot = 2; | ||
| 917 | child->thread.iac2 = bp_info->addr; | ||
| 918 | child->thread.dbcr0 |= DBCR0_IAC2; | ||
| 919 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 920 | } else if (!slot3_in_use) { | ||
| 921 | slot = 3; | ||
| 922 | child->thread.iac3 = bp_info->addr; | ||
| 923 | child->thread.dbcr0 |= DBCR0_IAC3; | ||
| 924 | } else if (!slot4_in_use) { | ||
| 925 | slot = 4; | ||
| 926 | child->thread.iac4 = bp_info->addr; | ||
| 927 | child->thread.dbcr0 |= DBCR0_IAC4; | ||
| 928 | #endif | ||
| 929 | } else | ||
| 930 | return -ENOSPC; | ||
| 931 | } | ||
| 932 | out: | ||
| 933 | child->thread.dbcr0 |= DBCR0_IDM; | ||
| 934 | child->thread.regs->msr |= MSR_DE; | ||
| 935 | |||
| 936 | return slot; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int del_instruction_bp(struct task_struct *child, int slot) | ||
| 940 | { | ||
| 941 | switch (slot) { | ||
| 942 | case 1: | ||
| 943 | if (child->thread.iac1 == 0) | ||
| 944 | return -ENOENT; | ||
| 945 | |||
| 946 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) { | ||
| 947 | /* address range - clear slots 1 & 2 */ | ||
| 948 | child->thread.iac2 = 0; | ||
| 949 | dbcr_iac_range(child) &= ~DBCR_IAC12MODE; | ||
| 950 | } | ||
| 951 | child->thread.iac1 = 0; | ||
| 952 | child->thread.dbcr0 &= ~DBCR0_IAC1; | ||
| 953 | break; | ||
| 954 | case 2: | ||
| 955 | if (child->thread.iac2 == 0) | ||
| 956 | return -ENOENT; | ||
| 957 | |||
| 958 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | ||
| 959 | /* used in a range */ | ||
| 960 | return -EINVAL; | ||
| 961 | child->thread.iac2 = 0; | ||
| 962 | child->thread.dbcr0 &= ~DBCR0_IAC2; | ||
| 963 | break; | ||
| 964 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 965 | case 3: | ||
| 966 | if (child->thread.iac3 == 0) | ||
| 967 | return -ENOENT; | ||
| 968 | |||
| 969 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) { | ||
| 970 | /* address range - clear slots 3 & 4 */ | ||
| 971 | child->thread.iac4 = 0; | ||
| 972 | dbcr_iac_range(child) &= ~DBCR_IAC34MODE; | ||
| 973 | } | ||
| 974 | child->thread.iac3 = 0; | ||
| 975 | child->thread.dbcr0 &= ~DBCR0_IAC3; | ||
| 976 | break; | ||
| 977 | case 4: | ||
| 978 | if (child->thread.iac4 == 0) | ||
| 979 | return -ENOENT; | ||
| 980 | |||
| 981 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) | ||
| 982 | /* Used in a range */ | ||
| 983 | return -EINVAL; | ||
| 984 | child->thread.iac4 = 0; | ||
| 985 | child->thread.dbcr0 &= ~DBCR0_IAC4; | ||
| 986 | break; | ||
| 987 | #endif | ||
| 988 | default: | ||
| 989 | return -EINVAL; | ||
| 990 | } | ||
| 991 | return 0; | ||
| 992 | } | ||
| 993 | |||
| 994 | static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) | ||
| 995 | { | ||
| 996 | int byte_enable = | ||
| 997 | (bp_info->condition_mode >> PPC_BREAKPOINT_CONDITION_BE_SHIFT) | ||
| 998 | & 0xf; | ||
| 999 | int condition_mode = | ||
| 1000 | bp_info->condition_mode & PPC_BREAKPOINT_CONDITION_MODE; | ||
| 1001 | int slot; | ||
| 1002 | |||
| 1003 | if (byte_enable && (condition_mode == 0)) | ||
| 1004 | return -EINVAL; | ||
| 1005 | |||
| 1006 | if (bp_info->addr >= TASK_SIZE) | ||
| 1007 | return -EIO; | ||
| 1008 | |||
| 1009 | if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) { | ||
| 1010 | slot = 1; | ||
| 1011 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 1012 | dbcr_dac(child) |= DBCR_DAC1R; | ||
| 1013 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 1014 | dbcr_dac(child) |= DBCR_DAC1W; | ||
| 1015 | child->thread.dac1 = (unsigned long)bp_info->addr; | ||
| 1016 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1017 | if (byte_enable) { | ||
| 1018 | child->thread.dvc1 = | ||
| 1019 | (unsigned long)bp_info->condition_value; | ||
| 1020 | child->thread.dbcr2 |= | ||
| 1021 | ((byte_enable << DBCR2_DVC1BE_SHIFT) | | ||
| 1022 | (condition_mode << DBCR2_DVC1M_SHIFT)); | ||
| 1023 | } | ||
| 1024 | #endif | ||
| 1025 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1026 | } else if (child->thread.dbcr2 & DBCR2_DAC12MODE) { | ||
| 1027 | /* Both dac1 and dac2 are part of a range */ | ||
| 1028 | return -ENOSPC; | ||
| 1029 | #endif | ||
| 1030 | } else if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) { | ||
| 1031 | slot = 2; | ||
| 1032 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 1033 | dbcr_dac(child) |= DBCR_DAC2R; | ||
| 1034 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 1035 | dbcr_dac(child) |= DBCR_DAC2W; | ||
| 1036 | child->thread.dac2 = (unsigned long)bp_info->addr; | ||
| 1037 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1038 | if (byte_enable) { | ||
| 1039 | child->thread.dvc2 = | ||
| 1040 | (unsigned long)bp_info->condition_value; | ||
| 1041 | child->thread.dbcr2 |= | ||
| 1042 | ((byte_enable << DBCR2_DVC2BE_SHIFT) | | ||
| 1043 | (condition_mode << DBCR2_DVC2M_SHIFT)); | ||
| 1044 | } | ||
| 1045 | #endif | ||
| 1046 | } else | ||
| 1047 | return -ENOSPC; | ||
| 1048 | child->thread.dbcr0 |= DBCR0_IDM; | ||
| 1049 | child->thread.regs->msr |= MSR_DE; | ||
| 1050 | |||
| 1051 | return slot + 4; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | static int del_dac(struct task_struct *child, int slot) | ||
| 1055 | { | ||
| 1056 | if (slot == 1) { | ||
| 1057 | if (child->thread.dac1 == 0) | ||
| 1058 | return -ENOENT; | ||
| 1059 | |||
| 1060 | child->thread.dac1 = 0; | ||
| 1061 | dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W); | ||
| 1062 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1063 | if (child->thread.dbcr2 & DBCR2_DAC12MODE) { | ||
| 1064 | child->thread.dac2 = 0; | ||
| 1065 | child->thread.dbcr2 &= ~DBCR2_DAC12MODE; | ||
| 1066 | } | ||
| 1067 | child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE); | ||
| 1068 | #endif | ||
| 1069 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1070 | child->thread.dvc1 = 0; | ||
| 1071 | #endif | ||
| 1072 | } else if (slot == 2) { | ||
| 1073 | if (child->thread.dac1 == 0) | ||
| 1074 | return -ENOENT; | ||
| 1075 | |||
| 1076 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1077 | if (child->thread.dbcr2 & DBCR2_DAC12MODE) | ||
| 1078 | /* Part of a range */ | ||
| 1079 | return -EINVAL; | ||
| 1080 | child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE); | ||
| 1081 | #endif | ||
| 1082 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1083 | child->thread.dvc2 = 0; | ||
| 1084 | #endif | ||
| 1085 | child->thread.dac2 = 0; | ||
| 1086 | dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W); | ||
| 1087 | } else | ||
| 1088 | return -EINVAL; | ||
| 1089 | |||
| 1090 | return 0; | ||
| 1091 | } | ||
| 1092 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 1093 | |||
| 1094 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1095 | static int set_dac_range(struct task_struct *child, | ||
| 1096 | struct ppc_hw_breakpoint *bp_info) | ||
| 1097 | { | ||
| 1098 | int mode = bp_info->addr_mode & PPC_BREAKPOINT_MODE_MASK; | ||
| 1099 | |||
| 1100 | /* We don't allow range watchpoints to be used with DVC */ | ||
| 1101 | if (bp_info->condition_mode) | ||
| 1102 | return -EINVAL; | ||
| 1103 | |||
| 1104 | /* | ||
| 1105 | * Best effort to verify the address range. The user/supervisor bits | ||
| 1106 | * prevent trapping in kernel space, but let's fail on an obvious bad | ||
| 1107 | * range. The simple test on the mask is not fool-proof, and any | ||
| 1108 | * exclusive range will spill over into kernel space. | ||
| 1109 | */ | ||
| 1110 | if (bp_info->addr >= TASK_SIZE) | ||
| 1111 | return -EIO; | ||
| 1112 | if (mode == PPC_BREAKPOINT_MODE_MASK) { | ||
| 1113 | /* | ||
| 1114 | * dac2 is a bitmask. Don't allow a mask that makes a | ||
| 1115 | * kernel space address from a valid dac1 value | ||
| 1116 | */ | ||
| 1117 | if (~((unsigned long)bp_info->addr2) >= TASK_SIZE) | ||
| 1118 | return -EIO; | ||
| 1119 | } else { | ||
| 1120 | /* | ||
| 1121 | * For range breakpoints, addr2 must also be a valid address | ||
| 1122 | */ | ||
| 1123 | if (bp_info->addr2 >= TASK_SIZE) | ||
| 1124 | return -EIO; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | if (child->thread.dbcr0 & | ||
| 1128 | (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)) | ||
| 1129 | return -ENOSPC; | ||
| 1130 | |||
| 1131 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 1132 | child->thread.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM); | ||
| 1133 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 1134 | child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM); | ||
| 1135 | child->thread.dac1 = bp_info->addr; | ||
| 1136 | child->thread.dac2 = bp_info->addr2; | ||
| 1137 | if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) | ||
| 1138 | child->thread.dbcr2 |= DBCR2_DAC12M; | ||
| 1139 | else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | ||
| 1140 | child->thread.dbcr2 |= DBCR2_DAC12MX; | ||
| 1141 | else /* PPC_BREAKPOINT_MODE_MASK */ | ||
| 1142 | child->thread.dbcr2 |= DBCR2_DAC12MM; | ||
| 1143 | child->thread.regs->msr |= MSR_DE; | ||
| 1144 | |||
| 1145 | return 5; | ||
| 1146 | } | ||
| 1147 | #endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */ | ||
| 1148 | |||
| 838 | static long ppc_set_hwdebug(struct task_struct *child, | 1149 | static long ppc_set_hwdebug(struct task_struct *child, |
| 839 | struct ppc_hw_breakpoint *bp_info) | 1150 | struct ppc_hw_breakpoint *bp_info) |
| 840 | { | 1151 | { |
| 1152 | if (bp_info->version != 1) | ||
| 1153 | return -ENOTSUPP; | ||
| 1154 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1155 | /* | ||
| 1156 | * Check for invalid flags and combinations | ||
| 1157 | */ | ||
| 1158 | if ((bp_info->trigger_type == 0) || | ||
| 1159 | (bp_info->trigger_type & ~(PPC_BREAKPOINT_TRIGGER_EXECUTE | | ||
| 1160 | PPC_BREAKPOINT_TRIGGER_RW)) || | ||
| 1161 | (bp_info->addr_mode & ~PPC_BREAKPOINT_MODE_MASK) || | ||
| 1162 | (bp_info->condition_mode & | ||
| 1163 | ~(PPC_BREAKPOINT_CONDITION_MODE | | ||
| 1164 | PPC_BREAKPOINT_CONDITION_BE_ALL))) | ||
| 1165 | return -EINVAL; | ||
| 1166 | #if CONFIG_PPC_ADV_DEBUG_DVCS == 0 | ||
| 1167 | if (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) | ||
| 1168 | return -EINVAL; | ||
| 1169 | #endif | ||
| 1170 | |||
| 1171 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) { | ||
| 1172 | if ((bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE) || | ||
| 1173 | (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)) | ||
| 1174 | return -EINVAL; | ||
| 1175 | return set_intruction_bp(child, bp_info); | ||
| 1176 | } | ||
| 1177 | if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT) | ||
| 1178 | return set_dac(child, bp_info); | ||
| 1179 | |||
| 1180 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1181 | return set_dac_range(child, bp_info); | ||
| 1182 | #else | ||
| 1183 | return -EINVAL; | ||
| 1184 | #endif | ||
| 1185 | #else /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | ||
| 841 | /* | 1186 | /* |
| 842 | * We currently support one data breakpoint | 1187 | * We only support one data breakpoint |
| 843 | */ | 1188 | */ |
| 844 | if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) || | 1189 | if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) || |
| 845 | ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) || | 1190 | ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) || |
| @@ -855,30 +1200,39 @@ static long ppc_set_hwdebug(struct task_struct *child, | |||
| 855 | return -EIO; | 1200 | return -EIO; |
| 856 | 1201 | ||
| 857 | child->thread.dabr = (unsigned long)bp_info->addr; | 1202 | child->thread.dabr = (unsigned long)bp_info->addr; |
| 858 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1203 | |
| 859 | child->thread.dbcr0 = DBCR0_IDM; | ||
| 860 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 861 | child->thread.dbcr0 |= DBSR_DAC1R; | ||
| 862 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 863 | child->thread.dbcr0 |= DBSR_DAC1W; | ||
| 864 | child->thread.regs->msr |= MSR_DE; | ||
| 865 | #endif | ||
| 866 | return 1; | 1204 | return 1; |
| 1205 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | ||
| 867 | } | 1206 | } |
| 868 | 1207 | ||
| 869 | static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) | 1208 | static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) |
| 870 | { | 1209 | { |
| 1210 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1211 | int rc; | ||
| 1212 | |||
| 1213 | if (data <= 4) | ||
| 1214 | rc = del_instruction_bp(child, (int)data); | ||
| 1215 | else | ||
| 1216 | rc = del_dac(child, (int)data - 4); | ||
| 1217 | |||
| 1218 | if (!rc) { | ||
| 1219 | if (!DBCR_ACTIVE_EVENTS(child->thread.dbcr0, | ||
| 1220 | child->thread.dbcr1)) { | ||
| 1221 | child->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 1222 | child->thread.regs->msr &= ~MSR_DE; | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | return rc; | ||
| 1226 | #else | ||
| 871 | if (data != 1) | 1227 | if (data != 1) |
| 872 | return -EINVAL; | 1228 | return -EINVAL; |
| 873 | if (child->thread.dabr == 0) | 1229 | if (child->thread.dabr == 0) |
| 874 | return -ENOENT; | 1230 | return -ENOENT; |
| 875 | 1231 | ||
| 876 | child->thread.dabr = 0; | 1232 | child->thread.dabr = 0; |
| 877 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1233 | |
| 878 | child->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM); | ||
| 879 | child->thread.regs->msr &= ~MSR_DE; | ||
| 880 | #endif | ||
| 881 | return 0; | 1234 | return 0; |
| 1235 | #endif | ||
| 882 | } | 1236 | } |
| 883 | 1237 | ||
| 884 | /* | 1238 | /* |
| @@ -978,6 +1332,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 978 | struct ppc_debug_info dbginfo; | 1332 | struct ppc_debug_info dbginfo; |
| 979 | 1333 | ||
| 980 | dbginfo.version = 1; | 1334 | dbginfo.version = 1; |
| 1335 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1336 | dbginfo.num_instruction_bps = CONFIG_PPC_ADV_DEBUG_IACS; | ||
| 1337 | dbginfo.num_data_bps = CONFIG_PPC_ADV_DEBUG_DACS; | ||
| 1338 | dbginfo.num_condition_regs = CONFIG_PPC_ADV_DEBUG_DVCS; | ||
| 1339 | dbginfo.data_bp_alignment = 4; | ||
| 1340 | dbginfo.sizeof_condition = 4; | ||
| 1341 | dbginfo.features = PPC_DEBUG_FEATURE_INSN_BP_RANGE | | ||
| 1342 | PPC_DEBUG_FEATURE_INSN_BP_MASK; | ||
| 1343 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1344 | dbginfo.features |= | ||
| 1345 | PPC_DEBUG_FEATURE_DATA_BP_RANGE | | ||
| 1346 | PPC_DEBUG_FEATURE_DATA_BP_MASK; | ||
| 1347 | #endif | ||
| 1348 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 981 | dbginfo.num_instruction_bps = 0; | 1349 | dbginfo.num_instruction_bps = 0; |
| 982 | dbginfo.num_data_bps = 1; | 1350 | dbginfo.num_data_bps = 1; |
| 983 | dbginfo.num_condition_regs = 0; | 1351 | dbginfo.num_condition_regs = 0; |
| @@ -988,6 +1356,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 988 | #endif | 1356 | #endif |
| 989 | dbginfo.sizeof_condition = 0; | 1357 | dbginfo.sizeof_condition = 0; |
| 990 | dbginfo.features = 0; | 1358 | dbginfo.features = 0; |
| 1359 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 991 | 1360 | ||
| 992 | if (!access_ok(VERIFY_WRITE, data, | 1361 | if (!access_ok(VERIFY_WRITE, data, |
| 993 | sizeof(struct ppc_debug_info))) | 1362 | sizeof(struct ppc_debug_info))) |
| @@ -1023,8 +1392,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 1023 | /* We only support one DABR and no IABRS at the moment */ | 1392 | /* We only support one DABR and no IABRS at the moment */ |
| 1024 | if (addr > 0) | 1393 | if (addr > 0) |
| 1025 | break; | 1394 | break; |
| 1395 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1396 | ret = put_user(child->thread.dac1, | ||
| 1397 | (unsigned long __user *)data); | ||
| 1398 | #else | ||
| 1026 | ret = put_user(child->thread.dabr, | 1399 | ret = put_user(child->thread.dabr, |
| 1027 | (unsigned long __user *)data); | 1400 | (unsigned long __user *)data); |
| 1401 | #endif | ||
| 1028 | break; | 1402 | break; |
| 1029 | } | 1403 | } |
| 1030 | 1404 | ||
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index ad7044b5a2c7..a0afb555a7c9 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -140,17 +140,15 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) | |||
| 140 | return 0; /* no signals delivered */ | 140 | return 0; /* no signals delivered */ |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 143 | /* | 144 | /* |
| 144 | * Reenable the DABR before delivering the signal to | 145 | * Reenable the DABR before delivering the signal to |
| 145 | * user space. The DABR will have been cleared if it | 146 | * user space. The DABR will have been cleared if it |
| 146 | * triggered inside the kernel. | 147 | * triggered inside the kernel. |
| 147 | */ | 148 | */ |
| 148 | if (current->thread.dabr) { | 149 | if (current->thread.dabr) |
| 149 | set_dabr(current->thread.dabr); | 150 | set_dabr(current->thread.dabr); |
| 150 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 151 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | ||
| 152 | #endif | 151 | #endif |
| 153 | } | ||
| 154 | 152 | ||
| 155 | if (is32) { | 153 | if (is32) { |
| 156 | if (ka.sa.sa_flags & SA_SIGINFO) | 154 | if (ka.sa.sa_flags & SA_SIGINFO) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index e4883ae36277..266610119f66 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
| @@ -1092,8 +1092,12 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1092 | new_msr |= MSR_DE; | 1092 | new_msr |= MSR_DE; |
| 1093 | new_dbcr0 |= (DBCR0_IDM | DBCR0_IC); | 1093 | new_dbcr0 |= (DBCR0_IDM | DBCR0_IC); |
| 1094 | } else { | 1094 | } else { |
| 1095 | new_msr &= ~MSR_DE; | 1095 | new_dbcr0 &= ~DBCR0_IC; |
| 1096 | new_dbcr0 &= ~(DBCR0_IDM | DBCR0_IC); | 1096 | if (!DBCR_ACTIVE_EVENTS(new_dbcr0, |
| 1097 | current->thread.dbcr1)) { | ||
| 1098 | new_msr &= ~MSR_DE; | ||
| 1099 | new_dbcr0 &= ~DBCR0_IDM; | ||
| 1100 | } | ||
| 1097 | } | 1101 | } |
| 1098 | #else | 1102 | #else |
| 1099 | if (op.dbg_value) | 1103 | if (op.dbg_value) |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 4e293b75f951..987437e04e61 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -1034,9 +1034,68 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
| 1034 | #endif /* CONFIG_8xx */ | 1034 | #endif /* CONFIG_8xx */ |
| 1035 | 1035 | ||
| 1036 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1036 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1037 | static void handle_debug(struct pt_regs *regs, unsigned long debug_status) | ||
| 1038 | { | ||
| 1039 | int changed = 0; | ||
| 1040 | /* | ||
| 1041 | * Determine the cause of the debug event, clear the | ||
| 1042 | * event flags and send a trap to the handler. Torez | ||
| 1043 | */ | ||
| 1044 | if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | ||
| 1045 | dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W); | ||
| 1046 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1047 | current->thread.dbcr2 &= ~DBCR2_DAC12MODE; | ||
| 1048 | #endif | ||
| 1049 | do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT, | ||
| 1050 | 5); | ||
| 1051 | changed |= 0x01; | ||
| 1052 | } else if (debug_status & (DBSR_DAC2R | DBSR_DAC2W)) { | ||
| 1053 | dbcr_dac(current) &= ~(DBCR_DAC2R | DBCR_DAC2W); | ||
| 1054 | do_send_trap(regs, mfspr(SPRN_DAC2), debug_status, TRAP_HWBKPT, | ||
| 1055 | 6); | ||
| 1056 | changed |= 0x01; | ||
| 1057 | } else if (debug_status & DBSR_IAC1) { | ||
| 1058 | current->thread.dbcr0 &= ~DBCR0_IAC1; | ||
| 1059 | dbcr_iac_range(current) &= ~DBCR_IAC12MODE; | ||
| 1060 | do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT, | ||
| 1061 | 1); | ||
| 1062 | changed |= 0x01; | ||
| 1063 | } else if (debug_status & DBSR_IAC2) { | ||
| 1064 | current->thread.dbcr0 &= ~DBCR0_IAC2; | ||
| 1065 | do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT, | ||
| 1066 | 2); | ||
| 1067 | changed |= 0x01; | ||
| 1068 | } else if (debug_status & DBSR_IAC3) { | ||
| 1069 | current->thread.dbcr0 &= ~DBCR0_IAC3; | ||
| 1070 | dbcr_iac_range(current) &= ~DBCR_IAC34MODE; | ||
| 1071 | do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT, | ||
| 1072 | 3); | ||
| 1073 | changed |= 0x01; | ||
| 1074 | } else if (debug_status & DBSR_IAC4) { | ||
| 1075 | current->thread.dbcr0 &= ~DBCR0_IAC4; | ||
| 1076 | do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT, | ||
| 1077 | 4); | ||
| 1078 | changed |= 0x01; | ||
| 1079 | } | ||
| 1080 | /* | ||
| 1081 | * At the point this routine was called, the MSR(DE) was turned off. | ||
| 1082 | * Check all other debug flags and see if that bit needs to be turned | ||
| 1083 | * back on or not. | ||
| 1084 | */ | ||
| 1085 | if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1)) | ||
| 1086 | regs->msr |= MSR_DE; | ||
| 1087 | else | ||
| 1088 | /* Make sure the IDM flag is off */ | ||
| 1089 | current->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 1090 | |||
| 1091 | if (changed & 0x01) | ||
| 1092 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | ||
| 1093 | } | ||
| 1037 | 1094 | ||
| 1038 | void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | 1095 | void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) |
| 1039 | { | 1096 | { |
| 1097 | current->thread.dbsr = debug_status; | ||
| 1098 | |||
| 1040 | /* Hack alert: On BookE, Branch Taken stops on the branch itself, while | 1099 | /* Hack alert: On BookE, Branch Taken stops on the branch itself, while |
| 1041 | * on server, it stops on the target of the branch. In order to simulate | 1100 | * on server, it stops on the target of the branch. In order to simulate |
| 1042 | * the server behaviour, we thus restart right away with a single step | 1101 | * the server behaviour, we thus restart right away with a single step |
| @@ -1080,27 +1139,21 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | |||
| 1080 | if (debugger_sstep(regs)) | 1139 | if (debugger_sstep(regs)) |
| 1081 | return; | 1140 | return; |
| 1082 | 1141 | ||
| 1083 | if (user_mode(regs)) | ||
| 1084 | current->thread.dbcr0 &= ~(DBCR0_IC); | ||
| 1085 | |||
| 1086 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); | ||
| 1087 | } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | ||
| 1088 | regs->msr &= ~MSR_DE; | ||
| 1089 | |||
| 1090 | if (user_mode(regs)) { | 1142 | if (user_mode(regs)) { |
| 1091 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | | 1143 | current->thread.dbcr0 &= ~DBCR0_IC; |
| 1092 | DBCR0_IDM); | 1144 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1093 | } else { | 1145 | if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, |
| 1094 | /* Disable DAC interupts */ | 1146 | current->thread.dbcr1)) |
| 1095 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | | 1147 | regs->msr |= MSR_DE; |
| 1096 | DBSR_DAC1W | DBCR0_IDM)); | 1148 | else |
| 1097 | 1149 | /* Make sure the IDM bit is off */ | |
| 1098 | /* Clear the DAC event */ | 1150 | current->thread.dbcr0 &= ~DBCR0_IDM; |
| 1099 | mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W)); | 1151 | #endif |
| 1100 | } | 1152 | } |
| 1101 | /* Setup and send the trap to the handler */ | 1153 | |
| 1102 | do_dabr(regs, mfspr(SPRN_DAC1), debug_status); | 1154 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); |
| 1103 | } | 1155 | } else |
| 1156 | handle_debug(regs, debug_status); | ||
| 1104 | } | 1157 | } |
| 1105 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | 1158 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ |
| 1106 | 1159 | ||
