From 1c7544725324f350a2441b6fdd63205edfbe5c62 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 25 Mar 2004 05:59:54 -0800 Subject: [PATCH] [PATCH] ppc32: Fix racy access to TI_FLAGS The ppc32 syscall entry code could access the thread info flags in a racy way, thus potentially losing bits sets there at interrupt time or by another CPU, like NEED_RESCHED or SIGPENDING (ouch !). This fixes it by moving the potentially racy bit to a different field (I preferred that rather than turning the access into an atomic operation for performances reasons). --- arch/ppc/kernel/entry.S | 9 +++++---- include/asm-ppc/ptrace.h | 5 ++++- include/asm-ppc/thread_info.h | 21 +++++++++++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index f4cba07bc75c0..d05ff48582bf1 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -171,9 +171,10 @@ _GLOBAL(DoSyscall) bl do_show_syscall #endif /* SHOW_SYSCALLS */ rlwinm r10,r1,0,0,18 /* current_thread_info() */ + lwz r11,TI_LOCAL_FLAGS(r10) + rlwinm r11,r11,0,~_TIFL_FORCE_NOERROR + stw r11,TI_LOCAL_FLAGS(r10) lwz r11,TI_FLAGS(r10) - rlwinm r11,r11,0,~_TIF_FORCE_NOERROR - stw r11,TI_FLAGS(r10) andi. r11,r11,_TIF_SYSCALL_TRACE bne- syscall_dotrace syscall_dotrace_cont: @@ -196,8 +197,8 @@ ret_from_syscall: cmpl 0,r3,r11 rlwinm r12,r1,0,0,18 /* current_thread_info() */ blt+ 30f - lwz r11,TI_FLAGS(r12) - andi. r11,r11,_TIF_FORCE_NOERROR + lwz r11,TI_LOCAL_FLAGS(r12) + andi. r11,r11,_TIFL_FORCE_NOERROR bne 30f neg r3,r3 lwz r10,_CCR(r1) /* Set SO bit in CR */ diff --git a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h index a157e6ce6b67c..f13233eacb94e 100644 --- a/include/asm-ppc/ptrace.h +++ b/include/asm-ppc/ptrace.h @@ -49,7 +49,10 @@ struct pt_regs { #define instruction_pointer(regs) ((regs)->nip) #define user_mode(regs) (((regs)->msr & MSR_PR) != 0) -#define force_successful_syscall_return() set_thread_flag(TIF_FORCE_NOERROR) +#define force_successful_syscall_return() \ + do { \ + current_thread_info()->local_flags |= _TIFL_FORCE_NOERROR; \ + } while(0) /* * We use the least-significant bit of the trap field to indicate diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h index 440394a197c68..62aeec9804ea1 100644 --- a/include/asm-ppc/thread_info.h +++ b/include/asm-ppc/thread_info.h @@ -18,6 +18,7 @@ struct thread_info { struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ unsigned long flags; /* low level flags */ + unsigned long local_flags; /* non-racy flags */ int cpu; /* cpu we're on */ int preempt_count; struct restart_block restart_block; @@ -28,6 +29,7 @@ struct thread_info { .task = &tsk, \ .exec_domain = &default_exec_domain, \ .flags = 0, \ + .local_flags = 0, \ .cpu = 0, \ .preempt_count = 1, \ .restart_block = { \ @@ -69,8 +71,9 @@ static inline struct thread_info *current_thread_info(void) #define TI_TASK 0 #define TI_EXECDOMAIN 4 #define TI_FLAGS 8 -#define TI_CPU 12 -#define TI_PREEMPT 16 +#define TI_LOCAL_FLAGS 12 +#define TI_CPU 16 +#define TI_PREEMPT 20 #define PREEMPT_ACTIVE 0x4000000 @@ -83,16 +86,22 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling TIF_NEED_RESCHED */ -#define TIF_FORCE_NOERROR 5 /* don't return error from current - syscall even if result < 0 */ - /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<