]> rtime.felk.cvut.cz Git - zynq/linux.git/blobdiff - arch/x86/kernel/traps.c
Merge branch '4.0.8-rt6'
[zynq/linux.git] / arch / x86 / kernel / traps.c
index 4ff5d162ff9fd55381259ff8dd96f84064ecea72..e4d56e6e8401b12f9aae6832309d276f6ac6ded2 100644 (file)
@@ -88,9 +88,21 @@ static inline void conditional_sti(struct pt_regs *regs)
                local_irq_enable();
 }
 
-static inline void preempt_conditional_sti(struct pt_regs *regs)
+static inline void conditional_sti_ist(struct pt_regs *regs)
 {
+#ifdef CONFIG_X86_64
+       /*
+        * X86_64 uses a per CPU stack on the IST for certain traps
+        * like int3. The task can not be preempted when using one
+        * of these stacks, thus preemption must be disabled, otherwise
+        * the stack can be corrupted if the task is scheduled out,
+        * and another task comes in and uses this stack.
+        *
+        * On x86_32 the task keeps its own stack and it is OK if the
+        * task schedules out.
+        */
        preempt_count_inc();
+#endif
        if (regs->flags & X86_EFLAGS_IF)
                local_irq_enable();
 }
@@ -101,11 +113,13 @@ static inline void conditional_cli(struct pt_regs *regs)
                local_irq_disable();
 }
 
-static inline void preempt_conditional_cli(struct pt_regs *regs)
+static inline void conditional_cli_ist(struct pt_regs *regs)
 {
        if (regs->flags & X86_EFLAGS_IF)
                local_irq_disable();
+#ifdef CONFIG_X86_64
        preempt_count_dec();
+#endif
 }
 
 enum ctx_state ist_enter(struct pt_regs *regs)
@@ -539,9 +553,9 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
         * as we may switch to the interrupt stack.
         */
        debug_stack_usage_inc();
-       preempt_conditional_sti(regs);
+       conditional_sti_ist(regs);
        do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
-       preempt_conditional_cli(regs);
+       conditional_cli_ist(regs);
        debug_stack_usage_dec();
 exit:
        ist_exit(regs, prev_state);
@@ -671,12 +685,12 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        debug_stack_usage_inc();
 
        /* It's safe to allow irq's after DR6 has been saved */
-       preempt_conditional_sti(regs);
+       conditional_sti_ist(regs);
 
        if (regs->flags & X86_VM_MASK) {
                handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
                                        X86_TRAP_DB);
-               preempt_conditional_cli(regs);
+               conditional_cli_ist(regs);
                debug_stack_usage_dec();
                goto exit;
        }
@@ -696,7 +710,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        si_code = get_si_code(tsk->thread.debugreg6);
        if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
                send_sigtrap(tsk, regs, error_code, si_code);
-       preempt_conditional_cli(regs);
+       conditional_cli_ist(regs);
        debug_stack_usage_dec();
 
 exit: