YunQiang Su <syq@xxxxxxxxxx> 于2018年12月14日周五 下午11:56写道: > > On the Loongson-2G/2H/3A/3B there is a hardware flaw that ll/sc and > lld/scd is very weak ordering. We should add sync instructions before > each ll/lld and after the last sc/scd to workaround. Otherwise, this > flaw will cause deadlock occationally (e.g. when doing heavy load test > with LTP). > > We introduced an gcc/as option "-mfix-loongson3-llsc", this option > inserts sync before ll, and so some addresses in __ex_table will need > to be shift. > The binutils patch https://sourceware.org/ml/binutils/2018-12/msg00192.html The gcc patch https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01064.html > This is based on the patch from Huacai Chen. > --- > arch/mips/Makefile | 5 +++++ > arch/mips/include/asm/futex.h | 20 ++++++++++++-------- > 2 files changed, 17 insertions(+), 8 deletions(-) > > diff --git a/arch/mips/Makefile b/arch/mips/Makefile > index b6303e48d..360ee1c30 100644 > --- a/arch/mips/Makefile > +++ b/arch/mips/Makefile > @@ -194,6 +194,11 @@ cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon > endif > cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 > cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap > +ifeq ($(CONFIG_CPU_LOONGSON3),y) > +cflags-y += $(call cc-option,-mfix-loongson3-llsc,) > +else > +cflags-y += $(call cc-option,-mno-fix-loongson3-llsc,) > +endif > > cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) > cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) > diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h > index 8eff134b3..27fceaf1d 100644 > --- a/arch/mips/include/asm/futex.h > +++ b/arch/mips/include/asm/futex.h > @@ -18,6 +18,14 @@ > #include <asm/errno.h> > #include <asm/war.h> > > +#if defined(__mips_fix_loongson3_llsc) && defined(CONFIG_CPU_LOONGSON3) > +# define LL_SHIFT_UA __UA_ADDR "\t(1b+0), 4b \n" \ > + __UA_ADDR "\t(1b+4), 4b \n" \ > + __UA_ADDR "\t(2b+0), 4b \n" > +#else > +# define LL_SHIFT_UA __UA_ADDR "\t1b, 4b \n" \ > + __UA_ADDR "\t2b, 4b \n" > +#endif > #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ > { \ > if (cpu_has_llsc && R10000_LLSC_WAR) { \ > @@ -41,8 +49,7 @@ > " j 3b \n" \ > " .previous \n" \ > " .section __ex_table,\"a\" \n" \ > - " "__UA_ADDR "\t1b, 4b \n" \ > - " "__UA_ADDR "\t2b, 4b \n" \ > + LL_SHIFT_UA \ > " .previous \n" \ > : "=r" (ret), "=&r" (oldval), \ > "=" GCC_OFF_SMALL_ASM() (*uaddr) \ > @@ -70,8 +77,7 @@ > " j 3b \n" \ > " .previous \n" \ > " .section __ex_table,\"a\" \n" \ > - " "__UA_ADDR "\t1b, 4b \n" \ > - " "__UA_ADDR "\t2b, 4b \n" \ > + LL_SHIFT_UA \ > " .previous \n" \ > : "=r" (ret), "=&r" (oldval), \ > "=" GCC_OFF_SMALL_ASM() (*uaddr) \ > @@ -155,8 +161,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, > " j 3b \n" > " .previous \n" > " .section __ex_table,\"a\" \n" > - " "__UA_ADDR "\t1b, 4b \n" > - " "__UA_ADDR "\t2b, 4b \n" > + LL_SHIFT_UA > " .previous \n" > : "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr) > : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval), > @@ -185,8 +190,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, > " j 3b \n" > " .previous \n" > " .section __ex_table,\"a\" \n" > - " "__UA_ADDR "\t1b, 4b \n" > - " "__UA_ADDR "\t2b, 4b \n" > + LL_SHIFT_UA > " .previous \n" > : "+r" (ret), "=&r" (val), "=" GCC_OFF_SMALL_ASM() (*uaddr) > : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval), > -- > 2.20.0.rc2 >