diff options
-rw-r--r-- | arch/x86/kernel/process_32.c | 31 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace_32.c | 29 | ||||
-rw-r--r-- | arch/x86/kernel/signal_32.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/traps_32.c | 4 | ||||
-rw-r--r-- | arch/x86/power/cpu.c | 14 | ||||
-rw-r--r-- | include/asm-x86/processor_32.h | 7 |
6 files changed, 61 insertions, 28 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 53406461074f..3744cf63682c 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -445,7 +445,12 @@ void flush_thread(void) | |||
445 | { | 445 | { |
446 | struct task_struct *tsk = current; | 446 | struct task_struct *tsk = current; |
447 | 447 | ||
448 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); | 448 | tsk->thread.debugreg0 = 0; |
449 | tsk->thread.debugreg1 = 0; | ||
450 | tsk->thread.debugreg2 = 0; | ||
451 | tsk->thread.debugreg3 = 0; | ||
452 | tsk->thread.debugreg6 = 0; | ||
453 | tsk->thread.debugreg7 = 0; | ||
449 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 454 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
450 | clear_tsk_thread_flag(tsk, TIF_DEBUG); | 455 | clear_tsk_thread_flag(tsk, TIF_DEBUG); |
451 | /* | 456 | /* |
@@ -522,7 +527,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, | |||
522 | */ | 527 | */ |
523 | void dump_thread(struct pt_regs * regs, struct user * dump) | 528 | void dump_thread(struct pt_regs * regs, struct user * dump) |
524 | { | 529 | { |
525 | int i; | ||
526 | u16 gs; | 530 | u16 gs; |
527 | 531 | ||
528 | /* changed the size calculations - should hopefully work better. lbt */ | 532 | /* changed the size calculations - should hopefully work better. lbt */ |
@@ -533,8 +537,14 @@ void dump_thread(struct pt_regs * regs, struct user * dump) | |||
533 | dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; | 537 | dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; |
534 | dump->u_dsize -= dump->u_tsize; | 538 | dump->u_dsize -= dump->u_tsize; |
535 | dump->u_ssize = 0; | 539 | dump->u_ssize = 0; |
536 | for (i = 0; i < 8; i++) | 540 | dump->u_debugreg[0] = current->thread.debugreg0; |
537 | dump->u_debugreg[i] = current->thread.debugreg[i]; | 541 | dump->u_debugreg[1] = current->thread.debugreg1; |
542 | dump->u_debugreg[2] = current->thread.debugreg2; | ||
543 | dump->u_debugreg[3] = current->thread.debugreg3; | ||
544 | dump->u_debugreg[4] = 0; | ||
545 | dump->u_debugreg[5] = 0; | ||
546 | dump->u_debugreg[6] = current->thread.debugreg6; | ||
547 | dump->u_debugreg[7] = current->thread.debugreg7; | ||
538 | 548 | ||
539 | if (dump->start_stack < TASK_SIZE) | 549 | if (dump->start_stack < TASK_SIZE) |
540 | dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; | 550 | dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; |
@@ -612,13 +622,13 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
612 | wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0); | 622 | wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0); |
613 | 623 | ||
614 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | 624 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { |
615 | set_debugreg(next->debugreg[0], 0); | 625 | set_debugreg(next->debugreg0, 0); |
616 | set_debugreg(next->debugreg[1], 1); | 626 | set_debugreg(next->debugreg1, 1); |
617 | set_debugreg(next->debugreg[2], 2); | 627 | set_debugreg(next->debugreg2, 2); |
618 | set_debugreg(next->debugreg[3], 3); | 628 | set_debugreg(next->debugreg3, 3); |
619 | /* no 4 and 5 */ | 629 | /* no 4 and 5 */ |
620 | set_debugreg(next->debugreg[6], 6); | 630 | set_debugreg(next->debugreg6, 6); |
621 | set_debugreg(next->debugreg[7], 7); | 631 | set_debugreg(next->debugreg7, 7); |
622 | } | 632 | } |
623 | 633 | ||
624 | #ifdef CONFIG_SECCOMP | 634 | #ifdef CONFIG_SECCOMP |
@@ -869,4 +879,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
869 | unsigned long range_end = mm->brk + 0x02000000; | 879 | unsigned long range_end = mm->brk + 0x02000000; |
870 | return randomize_range(mm->brk, range_end, 0) ? : mm->brk; | 880 | return randomize_range(mm->brk, range_end, 0) ? : mm->brk; |
871 | } | 881 | } |
872 | |||
diff --git a/arch/x86/kernel/ptrace_32.c b/arch/x86/kernel/ptrace_32.c index 26071305de2c..fed83d066135 100644 --- a/arch/x86/kernel/ptrace_32.c +++ b/arch/x86/kernel/ptrace_32.c | |||
@@ -133,19 +133,39 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno) | |||
133 | */ | 133 | */ |
134 | static unsigned long ptrace_get_debugreg(struct task_struct *child, int n) | 134 | static unsigned long ptrace_get_debugreg(struct task_struct *child, int n) |
135 | { | 135 | { |
136 | return child->thread.debugreg[n]; | 136 | switch (n) { |
137 | case 0: return child->thread.debugreg0; | ||
138 | case 1: return child->thread.debugreg1; | ||
139 | case 2: return child->thread.debugreg2; | ||
140 | case 3: return child->thread.debugreg3; | ||
141 | case 6: return child->thread.debugreg6; | ||
142 | case 7: return child->thread.debugreg7; | ||
143 | } | ||
144 | return 0; | ||
137 | } | 145 | } |
138 | 146 | ||
139 | static int ptrace_set_debugreg(struct task_struct *child, | 147 | static int ptrace_set_debugreg(struct task_struct *child, |
140 | int n, unsigned long data) | 148 | int n, unsigned long data) |
141 | { | 149 | { |
150 | int i; | ||
151 | |||
142 | if (unlikely(n == 4 || n == 5)) | 152 | if (unlikely(n == 4 || n == 5)) |
143 | return -EIO; | 153 | return -EIO; |
144 | 154 | ||
145 | if (n < 4 && unlikely(data >= TASK_SIZE - 3)) | 155 | if (n < 4 && unlikely(data >= TASK_SIZE - 3)) |
146 | return -EIO; | 156 | return -EIO; |
147 | 157 | ||
148 | if (n == 7) { | 158 | switch (n) { |
159 | case 0: child->thread.debugreg0 = data; break; | ||
160 | case 1: child->thread.debugreg1 = data; break; | ||
161 | case 2: child->thread.debugreg2 = data; break; | ||
162 | case 3: child->thread.debugreg3 = data; break; | ||
163 | |||
164 | case 6: | ||
165 | child->thread.debugreg6 = data; | ||
166 | break; | ||
167 | |||
168 | case 7: | ||
149 | /* | 169 | /* |
150 | * Sanity-check data. Take one half-byte at once with | 170 | * Sanity-check data. Take one half-byte at once with |
151 | * check = (val >> (16 + 4*i)) & 0xf. It contains the | 171 | * check = (val >> (16 + 4*i)) & 0xf. It contains the |
@@ -176,19 +196,18 @@ static int ptrace_set_debugreg(struct task_struct *child, | |||
176 | * 64-bit kernel), so the x86_64 mask value is 0x5454. | 196 | * 64-bit kernel), so the x86_64 mask value is 0x5454. |
177 | * See the AMD manual no. 24593 (AMD64 System Programming) | 197 | * See the AMD manual no. 24593 (AMD64 System Programming) |
178 | */ | 198 | */ |
179 | int i; | ||
180 | data &= ~DR_CONTROL_RESERVED; | 199 | data &= ~DR_CONTROL_RESERVED; |
181 | for (i = 0; i < 4; i++) | 200 | for (i = 0; i < 4; i++) |
182 | if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) | 201 | if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) |
183 | return -EIO; | 202 | return -EIO; |
203 | child->thread.debugreg7 = data; | ||
184 | if (data) | 204 | if (data) |
185 | set_tsk_thread_flag(child, TIF_DEBUG); | 205 | set_tsk_thread_flag(child, TIF_DEBUG); |
186 | else | 206 | else |
187 | clear_tsk_thread_flag(child, TIF_DEBUG); | 207 | clear_tsk_thread_flag(child, TIF_DEBUG); |
208 | break; | ||
188 | } | 209 | } |
189 | 210 | ||
190 | child->thread.debugreg[n] = data; | ||
191 | |||
192 | return 0; | 211 | return 0; |
193 | } | 212 | } |
194 | 213 | ||
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 64cb3c05de69..2bf5c9aed106 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -605,8 +605,8 @@ static void fastcall do_signal(struct pt_regs *regs) | |||
605 | * have been cleared if the watchpoint triggered | 605 | * have been cleared if the watchpoint triggered |
606 | * inside the kernel. | 606 | * inside the kernel. |
607 | */ | 607 | */ |
608 | if (unlikely(current->thread.debugreg[7])) | 608 | if (unlikely(current->thread.debugreg7)) |
609 | set_debugreg(current->thread.debugreg[7], 7); | 609 | set_debugreg(current->thread.debugreg7, 7); |
610 | 610 | ||
611 | /* Whee! Actually deliver the signal. */ | 611 | /* Whee! Actually deliver the signal. */ |
612 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 612 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 931ef10960ee..27713553cc59 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
@@ -852,7 +852,7 @@ fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) | |||
852 | 852 | ||
853 | /* Mask out spurious debug traps due to lazy DR7 setting */ | 853 | /* Mask out spurious debug traps due to lazy DR7 setting */ |
854 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { | 854 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { |
855 | if (!tsk->thread.debugreg[7]) | 855 | if (!tsk->thread.debugreg7) |
856 | goto clear_dr7; | 856 | goto clear_dr7; |
857 | } | 857 | } |
858 | 858 | ||
@@ -860,7 +860,7 @@ fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) | |||
860 | goto debug_vm86; | 860 | goto debug_vm86; |
861 | 861 | ||
862 | /* Save debug status register where ptrace can see it */ | 862 | /* Save debug status register where ptrace can see it */ |
863 | tsk->thread.debugreg[6] = condition; | 863 | tsk->thread.debugreg6 = condition; |
864 | 864 | ||
865 | /* | 865 | /* |
866 | * Single-stepping through TF: make sure we ignore any events in | 866 | * Single-stepping through TF: make sure we ignore any events in |
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 998fd3ec0d68..5a98dc35addf 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c | |||
@@ -74,14 +74,14 @@ static void fix_processor_context(void) | |||
74 | /* | 74 | /* |
75 | * Now maybe reload the debug registers | 75 | * Now maybe reload the debug registers |
76 | */ | 76 | */ |
77 | if (current->thread.debugreg[7]){ | 77 | if (current->thread.debugreg7) { |
78 | set_debugreg(current->thread.debugreg[0], 0); | 78 | set_debugreg(current->thread.debugreg0, 0); |
79 | set_debugreg(current->thread.debugreg[1], 1); | 79 | set_debugreg(current->thread.debugreg1, 1); |
80 | set_debugreg(current->thread.debugreg[2], 2); | 80 | set_debugreg(current->thread.debugreg2, 2); |
81 | set_debugreg(current->thread.debugreg[3], 3); | 81 | set_debugreg(current->thread.debugreg3, 3); |
82 | /* no 4 and 5 */ | 82 | /* no 4 and 5 */ |
83 | set_debugreg(current->thread.debugreg[6], 6); | 83 | set_debugreg(current->thread.debugreg6, 6); |
84 | set_debugreg(current->thread.debugreg[7], 7); | 84 | set_debugreg(current->thread.debugreg7, 7); |
85 | } | 85 | } |
86 | 86 | ||
87 | } | 87 | } |
diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h index c85400fe58c4..d50a4b48d441 100644 --- a/include/asm-x86/processor_32.h +++ b/include/asm-x86/processor_32.h | |||
@@ -353,7 +353,12 @@ struct thread_struct { | |||
353 | unsigned long fs; | 353 | unsigned long fs; |
354 | unsigned long gs; | 354 | unsigned long gs; |
355 | /* Hardware debugging registers */ | 355 | /* Hardware debugging registers */ |
356 | unsigned long debugreg[8]; /* %%db0-7 debug registers */ | 356 | unsigned long debugreg0; |
357 | unsigned long debugreg1; | ||
358 | unsigned long debugreg2; | ||
359 | unsigned long debugreg3; | ||
360 | unsigned long debugreg6; | ||
361 | unsigned long debugreg7; | ||
357 | /* fault info */ | 362 | /* fault info */ |
358 | unsigned long cr2, trap_no, error_code; | 363 | unsigned long cr2, trap_no, error_code; |
359 | /* floating point info */ | 364 | /* floating point info */ |