>>>>> On Wed, 01 Sep 2004 09:51:16 +0100, Richard Sandiford <rsandifo@xxxxxxxxxx> said: >> Is this a get_user's problem or gcc's? rsandifo> The latter. gcc is putting the empty asm: rsandifo> __asm__ ("":"=r" (__gu_val)); rsandifo> into the delay slot of the call. Thank you for the detailed explanation. rsandifo> FWIW, I don't think the bug is specific to 3.3 or 3.4. It rsandifo> could probably trigger for other gcc versions too. It is rsandifo> highly dependent on scheduling though. Yes, this problem was originally found on gcc 3.2. rsandifo> The attached 3.4.x patch fixes the problem there, but if you rsandifo> want to work around it for old versions, just avoid using rsandifo> empty asms if you can, or make them volatile if you can't. Thank you. I create a patch for kernel with this workaround. # This patch assumes gcc 3.5 will be free from this problem :-) Could you apply, Ralf? diff -u linux-mips-cvs/include/asm-mips/paccess.h linux-mips/include/asm-mips/paccess.h --- linux-mips-cvs/include/asm-mips/paccess.h Mon Nov 24 20:22:01 2003 +++ linux-mips/include/asm-mips/paccess.h Wed Sep 1 22:49:30 2004 @@ -15,6 +15,7 @@ #include <linux/config.h> #include <linux/errno.h> +#include <asm/war.h> #ifdef CONFIG_MIPS32 #define __PA_ADDR ".word" @@ -37,7 +38,7 @@ long __gu_err; \ __typeof(*(ptr)) __gu_val; \ unsigned long __gu_addr; \ - __asm__("":"=r" (__gu_val)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__gu_val)); \ __gu_addr = (unsigned long) (ptr); \ __asm__("":"=r" (__gu_err)); \ switch (size) { \ @@ -78,7 +79,7 @@ long __pu_addr; \ __pu_val = (x); \ __pu_addr = (long) (ptr); \ - __asm__("":"=r" (__pu_err)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__pu_err)); \ switch (size) { \ case 1: __put_dbe_asm("sb"); break; \ case 2: __put_dbe_asm("sh"); break; \ diff -u linux-mips-cvs/include/asm-mips/uaccess.h linux-mips/include/asm-mips/uaccess.h --- linux-mips-cvs/include/asm-mips/uaccess.h Wed Mar 31 20:21:59 2004 +++ linux-mips/include/asm-mips/uaccess.h Wed Sep 1 23:24:15 2004 @@ -13,6 +13,7 @@ #include <linux/compiler.h> #include <linux/errno.h> #include <linux/thread_info.h> +#include <asm/war.h> /* * The fs value determines whether argument validity checking should be @@ -235,9 +236,9 @@ __typeof(*(ptr)) __gu_val; \ long __gu_addr; \ might_sleep(); \ - __asm__("":"=r" (__gu_val)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__gu_val)); \ __gu_addr = (long) (ptr); \ - __asm__("":"=r" (__gu_err)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__gu_err)); \ switch (size) { \ case 1: __get_user_asm("lb"); break; \ case 2: __get_user_asm("lh"); break; \ @@ -253,9 +254,9 @@ __typeof__(*(ptr)) __gu_val; \ long __gu_addr; \ might_sleep(); \ - __asm__("":"=r" (__gu_val)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__gu_val)); \ __gu_addr = (long) (ptr); \ - __asm__("":"=r" (__gu_err)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__gu_err)); \ if (access_ok(VERIFY_READ,__gu_addr,size)) { \ switch (size) { \ case 1: __get_user_asm("lb"); break; \ @@ -329,7 +330,7 @@ might_sleep(); \ __pu_val = (x); \ __pu_addr = (long) (ptr); \ - __asm__("":"=r" (__pu_err)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__pu_err)); \ switch (size) { \ case 1: __put_user_asm("sb"); break; \ case 2: __put_user_asm("sh"); break; \ @@ -348,7 +349,7 @@ might_sleep(); \ __pu_val = (x); \ __pu_addr = (long) (ptr); \ - __asm__("":"=r" (__pu_err)); \ + __asm__ GCC_ASM_PROTECT_DSLOT ("":"=r" (__pu_err)); \ if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \ switch (size) { \ case 1: __put_user_asm("sb"); break; \ diff -u linux-mips-cvs/include/asm-mips/war.h linux-mips/include/asm-mips/war.h --- linux-mips-cvs/include/asm-mips/war.h Sat Aug 21 00:34:12 2004 +++ linux-mips/include/asm-mips/war.h Wed Sep 1 23:22:29 2004 @@ -221,4 +221,10 @@ #define R10000_LLSC_WAR 0 #endif +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 4)) +#define GCC_ASM_PROTECT_DSLOT +#else +#define GCC_ASM_PROTECT_DSLOT __volatile__ +#endif + #endif /* _ASM_WAR_H */