(2012/02/02 6:06), Steven Rostedt wrote: > Preemption must be disabled before enabling interrupts in do_trap > on x86_64 because the stack in use for int3 and debug is a per CPU > stack set by th IST. But 32bit does not have an IST and the stack > still belongs to the current task and there is no problem in scheduling > out the task. > > Keep preemption enabled on X86_32 when enabling interrupts for > do_trap(). > > The name of the function is changed from preempt_conditional_sti/cli() > to conditional_sti/cli_ist(), to annotate that this function is used > when the stack is on the IST. > > Signed-off-by: Steven Rostedt <rostedt@xxxxxxxxxxx Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@xxxxxxxxxxx> Thanks! > > Index: linux-rt.git/arch/x86/kernel/traps.c > =================================================================== > --- linux-rt.git.orig/arch/x86/kernel/traps.c > +++ linux-rt.git/arch/x86/kernel/traps.c > @@ -87,9 +87,21 @@ static inline void conditional_sti(struc > 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. > + */ > inc_preempt_count(); > +#endif > if (regs->flags & X86_EFLAGS_IF) > local_irq_enable(); > } > @@ -100,11 +112,13 @@ static inline void conditional_cli(struc > 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 > dec_preempt_count(); > +#endif > } > > static void __kprobes > @@ -222,9 +236,9 @@ dotraplinkage void do_stack_segment(stru > if (notify_die(DIE_TRAP, "stack segment", regs, error_code, > 12, SIGBUS) == NOTIFY_STOP) > return; > - preempt_conditional_sti(regs); > + conditional_sti_ist(regs); > do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); > - preempt_conditional_cli(regs); > + conditional_cli_ist(regs); > } > > dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) > @@ -316,9 +330,9 @@ dotraplinkage void __kprobes do_int3(str > return; > #endif > > - preempt_conditional_sti(regs); > + conditional_sti_ist(regs); > do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); > - preempt_conditional_cli(regs); > + conditional_cli_ist(regs); > } > > #ifdef CONFIG_X86_64 > @@ -412,12 +426,12 @@ dotraplinkage void __kprobes do_debug(st > return; > > /* 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, 1); > - preempt_conditional_cli(regs); > + conditional_cli_ist(regs); > return; > } > > @@ -436,7 +450,7 @@ dotraplinkage void __kprobes do_debug(st > 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); > > return; > } > -- Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu.pt@xxxxxxxxxxx -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html