diff options
| -rw-r--r-- | arch/x86/include/asm/processor.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/thread_info.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/kprobes.c | 14 | ||||
| -rw-r--r-- | arch/x86/kernel/process.c | 11 | ||||
| -rw-r--r-- | arch/x86/kernel/step.c | 24 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 5 |
6 files changed, 53 insertions, 9 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 5bec21a66dc..32428b410b5 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
| @@ -799,7 +799,7 @@ extern void cpu_init(void); | |||
| 799 | 799 | ||
| 800 | static inline unsigned long get_debugctlmsr(void) | 800 | static inline unsigned long get_debugctlmsr(void) |
| 801 | { | 801 | { |
| 802 | unsigned long debugctlmsr = 0; | 802 | unsigned long debugctlmsr = 0; |
| 803 | 803 | ||
| 804 | #ifndef CONFIG_X86_DEBUGCTLMSR | 804 | #ifndef CONFIG_X86_DEBUGCTLMSR |
| 805 | if (boot_cpu_data.x86 < 6) | 805 | if (boot_cpu_data.x86 < 6) |
| @@ -807,7 +807,7 @@ static inline unsigned long get_debugctlmsr(void) | |||
| 807 | #endif | 807 | #endif |
| 808 | rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); | 808 | rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); |
| 809 | 809 | ||
| 810 | return debugctlmsr; | 810 | return debugctlmsr; |
| 811 | } | 811 | } |
| 812 | 812 | ||
| 813 | static inline void update_debugctlmsr(unsigned long debugctlmsr) | 813 | static inline void update_debugctlmsr(unsigned long debugctlmsr) |
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index dc85e12d140..d017ed5502e 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
| @@ -92,6 +92,7 @@ struct thread_info { | |||
| 92 | #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ | 92 | #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ |
| 93 | #define TIF_FREEZE 23 /* is freezing for suspend */ | 93 | #define TIF_FREEZE 23 /* is freezing for suspend */ |
| 94 | #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ | 94 | #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ |
| 95 | #define TIF_BLOCKSTEP 25 /* set when we want DEBUGCTLMSR_BTF */ | ||
| 95 | #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ | 96 | #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ |
| 96 | #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ | 97 | #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ |
| 97 | 98 | ||
| @@ -113,6 +114,7 @@ struct thread_info { | |||
| 113 | #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) | 114 | #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) |
| 114 | #define _TIF_FREEZE (1 << TIF_FREEZE) | 115 | #define _TIF_FREEZE (1 << TIF_FREEZE) |
| 115 | #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) | 116 | #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) |
| 117 | #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) | ||
| 116 | #define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES) | 118 | #define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES) |
| 117 | #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) | 119 | #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) |
| 118 | 120 | ||
| @@ -143,7 +145,7 @@ struct thread_info { | |||
| 143 | 145 | ||
| 144 | /* flags to check in __switch_to() */ | 146 | /* flags to check in __switch_to() */ |
| 145 | #define _TIF_WORK_CTXSW \ | 147 | #define _TIF_WORK_CTXSW \ |
| 146 | (_TIF_IO_BITMAP|_TIF_NOTSC) | 148 | (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP) |
| 147 | 149 | ||
| 148 | #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) | 150 | #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) |
| 149 | #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG) | 151 | #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG) |
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 7a880ad3a20..f2f56c0967b 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
| @@ -422,12 +422,22 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | |||
| 422 | 422 | ||
| 423 | static void __kprobes clear_btf(void) | 423 | static void __kprobes clear_btf(void) |
| 424 | { | 424 | { |
| 425 | /* XXX */ | 425 | if (test_thread_flag(TIF_BLOCKSTEP)) { |
| 426 | unsigned long debugctl = get_debugctlmsr(); | ||
| 427 | |||
| 428 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
| 429 | update_debugctlmsr(debugctl); | ||
| 430 | } | ||
| 426 | } | 431 | } |
| 427 | 432 | ||
| 428 | static void __kprobes restore_btf(void) | 433 | static void __kprobes restore_btf(void) |
| 429 | { | 434 | { |
| 430 | /* XXX */ | 435 | if (test_thread_flag(TIF_BLOCKSTEP)) { |
| 436 | unsigned long debugctl = get_debugctlmsr(); | ||
| 437 | |||
| 438 | debugctl |= DEBUGCTLMSR_BTF; | ||
| 439 | update_debugctlmsr(debugctl); | ||
| 440 | } | ||
| 431 | } | 441 | } |
| 432 | 442 | ||
| 433 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 443 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 1a60beb32ed..8328009416d 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -195,6 +195,17 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
| 195 | prev = &prev_p->thread; | 195 | prev = &prev_p->thread; |
| 196 | next = &next_p->thread; | 196 | next = &next_p->thread; |
| 197 | 197 | ||
| 198 | if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^ | ||
| 199 | test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) { | ||
| 200 | unsigned long debugctl = get_debugctlmsr(); | ||
| 201 | |||
| 202 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
| 203 | if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) | ||
| 204 | debugctl |= DEBUGCTLMSR_BTF; | ||
| 205 | |||
| 206 | update_debugctlmsr(debugctl); | ||
| 207 | } | ||
| 208 | |||
| 198 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | 209 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ |
| 199 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | 210 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { |
| 200 | /* prev and next are different */ | 211 | /* prev and next are different */ |
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 7beba0769a8..58de45ee08b 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c | |||
| @@ -169,9 +169,19 @@ static void enable_step(struct task_struct *child, bool block) | |||
| 169 | * So noone should try to use debugger block stepping in a program | 169 | * So noone should try to use debugger block stepping in a program |
| 170 | * that uses user-mode single stepping itself. | 170 | * that uses user-mode single stepping itself. |
| 171 | */ | 171 | */ |
| 172 | if (!enable_single_step(child)) | 172 | if (enable_single_step(child) && block) { |
| 173 | return; | 173 | unsigned long debugctl = get_debugctlmsr(); |
| 174 | /* XXX */ | 174 | |
| 175 | debugctl |= DEBUGCTLMSR_BTF; | ||
| 176 | update_debugctlmsr(debugctl); | ||
| 177 | set_tsk_thread_flag(child, TIF_BLOCKSTEP); | ||
| 178 | } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { | ||
| 179 | unsigned long debugctl = get_debugctlmsr(); | ||
| 180 | |||
| 181 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
| 182 | update_debugctlmsr(debugctl); | ||
| 183 | clear_tsk_thread_flag(child, TIF_BLOCKSTEP); | ||
| 184 | } | ||
| 175 | } | 185 | } |
| 176 | 186 | ||
| 177 | void user_enable_single_step(struct task_struct *child) | 187 | void user_enable_single_step(struct task_struct *child) |
| @@ -189,7 +199,13 @@ void user_disable_single_step(struct task_struct *child) | |||
| 189 | /* | 199 | /* |
| 190 | * Make sure block stepping (BTF) is disabled. | 200 | * Make sure block stepping (BTF) is disabled. |
| 191 | */ | 201 | */ |
| 192 | /* XXX */ | 202 | if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { |
| 203 | unsigned long debugctl = get_debugctlmsr(); | ||
| 204 | |||
| 205 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
| 206 | update_debugctlmsr(debugctl); | ||
| 207 | clear_tsk_thread_flag(child, TIF_BLOCKSTEP); | ||
| 208 | } | ||
| 193 | 209 | ||
| 194 | /* Always clear TIF_SINGLESTEP... */ | 210 | /* Always clear TIF_SINGLESTEP... */ |
| 195 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | 211 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index e3da5d726a3..36f1bd9f8e7 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -544,6 +544,11 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
| 544 | /* DR6 may or may not be cleared by the CPU */ | 544 | /* DR6 may or may not be cleared by the CPU */ |
| 545 | set_debugreg(0, 6); | 545 | set_debugreg(0, 6); |
| 546 | 546 | ||
| 547 | /* | ||
| 548 | * The processor cleared BTF, so don't mark that we need it set. | ||
| 549 | */ | ||
| 550 | clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP); | ||
| 551 | |||
| 547 | /* Store the virtualized DR6 value */ | 552 | /* Store the virtualized DR6 value */ |
| 548 | tsk->thread.debugreg6 = dr6; | 553 | tsk->thread.debugreg6 = dr6; |
| 549 | 554 | ||
