diff options
author | Alexander Kuleshov <kuleshovmail@gmail.com> | 2016-01-25 14:41:46 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-02-01 04:45:14 -0500 |
commit | d99e1bd175f4291ddb6e62b22bb5bdbe3976389a (patch) | |
tree | 14aa5d1e624e2b252b1959e703c9b0b934059113 /arch/x86/kernel | |
parent | bb56968a37a44070de92d5690c4b08dd98a5d3f1 (diff) |
x86/entry/traps: Refactor preemption and interrupt flag handling
Make the preemption and interrupt flag handling more readable by
removing preempt_conditional_sti() and preempt_conditional_cli()
helpers and using preempt_disable() and
preempt_enable_no_resched() instead.
Rename contitional_sti() and conditional_cli() to the more
understandable cond_local_irq_enable() and
cond_local_irq_disable() respectively, while at it.
Suggested-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>
[ Boris: massage text. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: H Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1453750913-4781-2-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/traps.c | 47 |
1 files changed, 19 insertions, 28 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ade185a46b1d..410e8e2700c5 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -83,30 +83,16 @@ gate_desc idt_table[NR_VECTORS] __page_aligned_bss; | |||
83 | DECLARE_BITMAP(used_vectors, NR_VECTORS); | 83 | DECLARE_BITMAP(used_vectors, NR_VECTORS); |
84 | EXPORT_SYMBOL_GPL(used_vectors); | 84 | EXPORT_SYMBOL_GPL(used_vectors); |
85 | 85 | ||
86 | static inline void conditional_sti(struct pt_regs *regs) | 86 | static inline void cond_local_irq_enable(struct pt_regs *regs) |
87 | { | 87 | { |
88 | if (regs->flags & X86_EFLAGS_IF) | 88 | if (regs->flags & X86_EFLAGS_IF) |
89 | local_irq_enable(); | 89 | local_irq_enable(); |
90 | } | 90 | } |
91 | 91 | ||
92 | static inline void preempt_conditional_sti(struct pt_regs *regs) | 92 | static inline void cond_local_irq_disable(struct pt_regs *regs) |
93 | { | ||
94 | preempt_count_inc(); | ||
95 | if (regs->flags & X86_EFLAGS_IF) | ||
96 | local_irq_enable(); | ||
97 | } | ||
98 | |||
99 | static inline void conditional_cli(struct pt_regs *regs) | ||
100 | { | ||
101 | if (regs->flags & X86_EFLAGS_IF) | ||
102 | local_irq_disable(); | ||
103 | } | ||
104 | |||
105 | static inline void preempt_conditional_cli(struct pt_regs *regs) | ||
106 | { | 93 | { |
107 | if (regs->flags & X86_EFLAGS_IF) | 94 | if (regs->flags & X86_EFLAGS_IF) |
108 | local_irq_disable(); | 95 | local_irq_disable(); |
109 | preempt_count_dec(); | ||
110 | } | 96 | } |
111 | 97 | ||
112 | void ist_enter(struct pt_regs *regs) | 98 | void ist_enter(struct pt_regs *regs) |
@@ -286,7 +272,7 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str, | |||
286 | 272 | ||
287 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) != | 273 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) != |
288 | NOTIFY_STOP) { | 274 | NOTIFY_STOP) { |
289 | conditional_sti(regs); | 275 | cond_local_irq_enable(regs); |
290 | do_trap(trapnr, signr, str, regs, error_code, | 276 | do_trap(trapnr, signr, str, regs, error_code, |
291 | fill_trap_info(regs, signr, trapnr, &info)); | 277 | fill_trap_info(regs, signr, trapnr, &info)); |
292 | } | 278 | } |
@@ -368,7 +354,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) | |||
368 | if (notify_die(DIE_TRAP, "bounds", regs, error_code, | 354 | if (notify_die(DIE_TRAP, "bounds", regs, error_code, |
369 | X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP) | 355 | X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP) |
370 | return; | 356 | return; |
371 | conditional_sti(regs); | 357 | cond_local_irq_enable(regs); |
372 | 358 | ||
373 | if (!user_mode(regs)) | 359 | if (!user_mode(regs)) |
374 | die("bounds", regs, error_code); | 360 | die("bounds", regs, error_code); |
@@ -443,7 +429,7 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
443 | struct task_struct *tsk; | 429 | struct task_struct *tsk; |
444 | 430 | ||
445 | RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); | 431 | RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); |
446 | conditional_sti(regs); | 432 | cond_local_irq_enable(regs); |
447 | 433 | ||
448 | if (v8086_mode(regs)) { | 434 | if (v8086_mode(regs)) { |
449 | local_irq_enable(); | 435 | local_irq_enable(); |
@@ -517,9 +503,11 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) | |||
517 | * as we may switch to the interrupt stack. | 503 | * as we may switch to the interrupt stack. |
518 | */ | 504 | */ |
519 | debug_stack_usage_inc(); | 505 | debug_stack_usage_inc(); |
520 | preempt_conditional_sti(regs); | 506 | preempt_disable(); |
507 | cond_local_irq_enable(regs); | ||
521 | do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); | 508 | do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); |
522 | preempt_conditional_cli(regs); | 509 | cond_local_irq_disable(regs); |
510 | preempt_enable_no_resched(); | ||
523 | debug_stack_usage_dec(); | 511 | debug_stack_usage_dec(); |
524 | exit: | 512 | exit: |
525 | ist_exit(regs); | 513 | ist_exit(regs); |
@@ -648,12 +636,14 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) | |||
648 | debug_stack_usage_inc(); | 636 | debug_stack_usage_inc(); |
649 | 637 | ||
650 | /* It's safe to allow irq's after DR6 has been saved */ | 638 | /* It's safe to allow irq's after DR6 has been saved */ |
651 | preempt_conditional_sti(regs); | 639 | preempt_disable(); |
640 | cond_local_irq_enable(regs); | ||
652 | 641 | ||
653 | if (v8086_mode(regs)) { | 642 | if (v8086_mode(regs)) { |
654 | handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, | 643 | handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, |
655 | X86_TRAP_DB); | 644 | X86_TRAP_DB); |
656 | preempt_conditional_cli(regs); | 645 | cond_local_irq_disable(regs); |
646 | preempt_enable_no_resched(); | ||
657 | debug_stack_usage_dec(); | 647 | debug_stack_usage_dec(); |
658 | goto exit; | 648 | goto exit; |
659 | } | 649 | } |
@@ -673,7 +663,8 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) | |||
673 | si_code = get_si_code(tsk->thread.debugreg6); | 663 | si_code = get_si_code(tsk->thread.debugreg6); |
674 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) | 664 | if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) |
675 | send_sigtrap(tsk, regs, error_code, si_code); | 665 | send_sigtrap(tsk, regs, error_code, si_code); |
676 | preempt_conditional_cli(regs); | 666 | cond_local_irq_disable(regs); |
667 | preempt_enable_no_resched(); | ||
677 | debug_stack_usage_dec(); | 668 | debug_stack_usage_dec(); |
678 | 669 | ||
679 | exit: | 670 | exit: |
@@ -696,7 +687,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) | |||
696 | 687 | ||
697 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP) | 688 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP) |
698 | return; | 689 | return; |
699 | conditional_sti(regs); | 690 | cond_local_irq_enable(regs); |
700 | 691 | ||
701 | if (!user_mode(regs)) { | 692 | if (!user_mode(regs)) { |
702 | if (!fixup_exception(regs)) { | 693 | if (!fixup_exception(regs)) { |
@@ -743,7 +734,7 @@ do_simd_coprocessor_error(struct pt_regs *regs, long error_code) | |||
743 | dotraplinkage void | 734 | dotraplinkage void |
744 | do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) | 735 | do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) |
745 | { | 736 | { |
746 | conditional_sti(regs); | 737 | cond_local_irq_enable(regs); |
747 | } | 738 | } |
748 | 739 | ||
749 | dotraplinkage void | 740 | dotraplinkage void |
@@ -756,7 +747,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) | |||
756 | if (read_cr0() & X86_CR0_EM) { | 747 | if (read_cr0() & X86_CR0_EM) { |
757 | struct math_emu_info info = { }; | 748 | struct math_emu_info info = { }; |
758 | 749 | ||
759 | conditional_sti(regs); | 750 | cond_local_irq_enable(regs); |
760 | 751 | ||
761 | info.regs = regs; | 752 | info.regs = regs; |
762 | math_emulate(&info); | 753 | math_emulate(&info); |
@@ -765,7 +756,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) | |||
765 | #endif | 756 | #endif |
766 | fpu__restore(¤t->thread.fpu); /* interrupts still off */ | 757 | fpu__restore(¤t->thread.fpu); /* interrupts still off */ |
767 | #ifdef CONFIG_X86_32 | 758 | #ifdef CONFIG_X86_32 |
768 | conditional_sti(regs); | 759 | cond_local_irq_enable(regs); |
769 | #endif | 760 | #endif |
770 | } | 761 | } |
771 | NOKPROBE_SYMBOL(do_device_not_available); | 762 | NOKPROBE_SYMBOL(do_device_not_available); |