[PATCH] m32r: fix sys_tas system call for m32r
This patch fixes a sys_tas system call for m32r. - This patch fixes an Oops at sys_tas() in case CONFIG_SMP && CONFIG_PREEMPT. > Unable to handle kernel paging request at virtual address XXXXXXXX It is because a page fault happens at the spin_locked region in sys_tas() and in_atomic() checks preempt_count, but spin_lock() already counts up the preemt_count. arch/m32r/kernel/sys_m32r.c: 32 /* 33 * sys_tas() - test-and-set 34 * linuxthreads testing version 35 */ 36 #ifndef CONFIG_SMP 37 asmlinkage int sys_tas(int *addr) 38 { 39 int oldval; 40 unsigned long flags; 41 42 if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) 43 return -EFAULT; 44 local_irq_save(flags); 45 oldval = *addr; 46 *addr = 1; 47 local_irq_restore(flags); 48 return oldval; 49 } 50 #else /* CONFIG_SMP */ 51 #include <linux/spinlock.h> 52 53 static spinlock_t tas_lock = SPIN_LOCK_UNLOCKED; 54 55 asmlinkage int sys_tas(int *addr) 56 { 57 int oldval; 58 59 if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) 60 return -EFAULT; 61 62 spin_lock(&tas_lock); 63 oldval = *addr; /* <<< ATTENTION >>> * A page fault may happen here, because "addr" points an * user-space area. */ 64 *addr = 1; 65 spin_unlock(&tas_lock); 66 67 return oldval; 68 } 69 #endif /* CONFIG_SMP */ arch/mm/fault.c: 137 /* 138 * If we're in an interrupt or have no user context or are runni ng in an 139 * atomic region then we must not take the fault.. 140 */ 141 if (in_atomic() || !mm) 142 goto bad_area_nosemaphore; - sys_tas() is used for user-level mutual exclusion for the m32r, which is prepared to implement a linuxthreads library. The above problem may be happened in a program, which uses pthread_mutex_lock(), calls sys_tas(). The current m32r instruction set has no user-level locking functions for mutual exclusion. # I hope it will be fixed in the future... - This patch fixes the problem by using _raw_spin_lock() instead of spin_lock(). spin_lock() increments up preemt_count, on the contrary, _raw_sping_lock() does not. # I think this fix is just a temporary work around, and # it is preferable to be rewrite to make it simpler by using # asm() function or something... * arch/m32r/kernel/sys_m32r.c: - Fix sys_tas() for CONFIG_SMP && CONFIG_PREEMPT. Signed-off-by: Hayato Fujiwara <fujiwara@linux-m32r.org> Signed-off-by: Hirokazu Takata <takata@linux-m32r.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing
Please register or sign in to comment