All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] MIPS: Assorted microMIPS fixes
@ 2014-11-15 22:06 ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:06 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Hi,

 In an attempt to build a kernel that supports microMIPS userland and 
runs on QEMU I came across the problem that, due to apparently arbitrary 
decisions made sometime in the past, there is no such combination 
possible.

 I went ahead and fixed our configuration to support that, but in the 
course of doing that I came across numerous problems that I decided to 
address at the same time.  This mini patch series the result.  Most of 
the changes are actually independent of one another, although there is a 
syntactical overlap between 5/7 and 7/7, so these have to be applied in 
order.

 Of course I had to draw a line somewhere so as not to get distracted 
too much from the actual purpose I have the need to run such a 
configuration, so I left some further bugs I spotted for the next 
occasion.

 Ralf, please backport these fixes to stable branches as applicable; I 
can supply you with a 3.17 equivalent of 5/7 as this piece has changed 
significantly recently and I actually had to forward-port the original 
change that I made to address the issue.

  Maciej

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/7] MIPS: Assorted microMIPS fixes
@ 2014-11-15 22:06 ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:06 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Hi,

 In an attempt to build a kernel that supports microMIPS userland and 
runs on QEMU I came across the problem that, due to apparently arbitrary 
decisions made sometime in the past, there is no such combination 
possible.

 I went ahead and fixed our configuration to support that, but in the 
course of doing that I came across numerous problems that I decided to 
address at the same time.  This mini patch series the result.  Most of 
the changes are actually independent of one another, although there is a 
syntactical overlap between 5/7 and 7/7, so these have to be applied in 
order.

 Of course I had to draw a line somewhere so as not to get distracted 
too much from the actual purpose I have the need to run such a 
configuration, so I left some further bugs I spotted for the next 
occasion.

 Ralf, please backport these fixes to stable branches as applicable; I 
can supply you with a 3.17 equivalent of 5/7 as this piece has changed 
significantly recently and I actually had to forward-port the original 
change that I made to address the issue.

  Maciej

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/7] MIPS: Kconfig: Enable microMIPS support for Malta
@ 2014-11-15 22:07   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:07 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Add missing microMIPS support to Malta.  Currently the kernel only 
enables support for the instruction set for the SEAD-3 board despite the 
fact processor features have nothing to do with the board a processor is 
installed in.

In this case there is no way to run microMIPS software in a fully 
supported way under Linux on QEMU.  QEMU supports the emulation of a 
Malta board, but does not emulate SEAD-3.  Linux supports running 
microMIPS code on a SEAD-3 board, but hardcodes such support to off on 
an emulated Malta board even if the processor selected has the microMIPS 
instruction set implemented.

Adding support for the SEAD-3 to QEMU is a major project.  Flipping a 
bit in the kernel that shouldn't have been cleared in the first place is 
a trivial effort.  Thus the answer is plain...

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 Depending on a processor configuration and particular software run you 
may get away -- as long as your code doesn't trap into the kernel for 
emulation.  This makes things even more frustrating as the thing appears 
to run at first and then breaks in an odd place.

 Frankly I fail to see the point of having microMIPS disabled unless the 
processor implied by the platform is plain too old (e.g. the DECstation) 
or otherwise not ever supposed to support it (e.g. NetLogic or Octeon).  
But I'll leave that for another occasion, for now let's just fix the 
Malta that has an actual use.

 Hmm, we should probably have:

	BUG_ON(!cpu_has_mmips && (cpu_data[0].options & MIPS_CPU_MICROMIPS));

somewhere too, to avoid leading user code astray; we may consider more 
consistency checks like this for cpu-feature-overrides.h, but this one 
is at least semi-obvious.  Another, less invasive way could be the ELF 
loader refusing microMIPS executables if (!cpu_has_mmips), but that has 
the drawback the user won't notice until the last moment.

 We could have a similar `cpu_has_mips16' override too if people are so 
concerned with the kernel binary size increase with optional features, 
and consequently `cpu_has_mips', for pure-microMIPS processors.

 Please apply.

  Maciej

linux-malta-micromips.diff
Index: linux-3.18-rc4-malta/arch/mips/Kconfig
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/Kconfig	2014-11-15 05:55:54.441908087 +0000
+++ linux-3.18-rc4-malta/arch/mips/Kconfig	2014-11-15 05:55:56.441902868 +0000
@@ -340,6 +340,7 @@ config MIPS_MALTA
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_MICROMIPS
 	select SYS_SUPPORTS_MIPS_CMP
 	select SYS_SUPPORTS_MIPS_CPS
 	select SYS_SUPPORTS_MIPS16

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/7] MIPS: Kconfig: Enable microMIPS support for Malta
@ 2014-11-15 22:07   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:07 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Add missing microMIPS support to Malta.  Currently the kernel only 
enables support for the instruction set for the SEAD-3 board despite the 
fact processor features have nothing to do with the board a processor is 
installed in.

In this case there is no way to run microMIPS software in a fully 
supported way under Linux on QEMU.  QEMU supports the emulation of a 
Malta board, but does not emulate SEAD-3.  Linux supports running 
microMIPS code on a SEAD-3 board, but hardcodes such support to off on 
an emulated Malta board even if the processor selected has the microMIPS 
instruction set implemented.

Adding support for the SEAD-3 to QEMU is a major project.  Flipping a 
bit in the kernel that shouldn't have been cleared in the first place is 
a trivial effort.  Thus the answer is plain...

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 Depending on a processor configuration and particular software run you 
may get away -- as long as your code doesn't trap into the kernel for 
emulation.  This makes things even more frustrating as the thing appears 
to run at first and then breaks in an odd place.

 Frankly I fail to see the point of having microMIPS disabled unless the 
processor implied by the platform is plain too old (e.g. the DECstation) 
or otherwise not ever supposed to support it (e.g. NetLogic or Octeon).  
But I'll leave that for another occasion, for now let's just fix the 
Malta that has an actual use.

 Hmm, we should probably have:

	BUG_ON(!cpu_has_mmips && (cpu_data[0].options & MIPS_CPU_MICROMIPS));

somewhere too, to avoid leading user code astray; we may consider more 
consistency checks like this for cpu-feature-overrides.h, but this one 
is at least semi-obvious.  Another, less invasive way could be the ELF 
loader refusing microMIPS executables if (!cpu_has_mmips), but that has 
the drawback the user won't notice until the last moment.

 We could have a similar `cpu_has_mips16' override too if people are so 
concerned with the kernel binary size increase with optional features, 
and consequently `cpu_has_mips', for pure-microMIPS processors.

 Please apply.

  Maciej

linux-malta-micromips.diff
Index: linux-3.18-rc4-malta/arch/mips/Kconfig
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/Kconfig	2014-11-15 05:55:54.441908087 +0000
+++ linux-3.18-rc4-malta/arch/mips/Kconfig	2014-11-15 05:55:56.441902868 +0000
@@ -340,6 +340,7 @@ config MIPS_MALTA
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_MICROMIPS
 	select SYS_SUPPORTS_MIPS_CMP
 	select SYS_SUPPORTS_MIPS_CPS
 	select SYS_SUPPORTS_MIPS16

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 2/7] MIPS: mm: Only build one microassembler that is suitable
@ 2014-11-15 22:07   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:07 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

The microMIPS microassembler is only suitable for configurations where
the kernel itself is built to microMIPS machine code and not where only
user microMIPS software is supported.  The former is controlled with the
CPU_MICROMIPS configuration setting, whereas SYS_SUPPORTS_MICROMIPS is
used for the latter.

Not only that, but with a given microMIPS vs standard MIPS kernel 
configuration only one microassembler is needed, that matches the ISA 
selected -- CP0.Config3.ISAOnExc is mandatory on microMIPS processors, 
so there is never a need to mix microMIPS and standard MIPS code.

Consequently build only the microassembler that matches the ISA selected 
for the kernel.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
linux-mips-uasm-micromips.diff
Index: linux-3.17-stable-malta/arch/mips/mm/Makefile
===================================================================
--- linux-3.17-stable-malta.orig/arch/mips/mm/Makefile	2014-11-14 19:44:22.000000000 +0000
+++ linux-3.17-stable-malta/arch/mips/mm/Makefile	2014-11-14 19:44:52.031933464 +0000
@@ -4,7 +4,13 @@
 
 obj-y				+= cache.o dma-default.o extable.o fault.o \
 				   gup.o init.o mmap.o page.o page-funcs.o \
-				   tlbex.o tlbex-fault.o tlb-funcs.o uasm-mips.o
+				   tlbex.o tlbex-fault.o tlb-funcs.o
+
+ifdef CONFIG_CPU_MICROMIPS
+obj-y				+= uasm-micromips.o
+else
+obj-y				+= uasm-mips.o
+endif
 
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
@@ -22,5 +28,3 @@ obj-$(CONFIG_IP22_CPU_SCACHE)	+= sc-ip22
 obj-$(CONFIG_R5000_CPU_SCACHE)	+= sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
-
-obj-$(CONFIG_SYS_SUPPORTS_MICROMIPS) += uasm-micromips.o

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 2/7] MIPS: mm: Only build one microassembler that is suitable
@ 2014-11-15 22:07   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:07 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

The microMIPS microassembler is only suitable for configurations where
the kernel itself is built to microMIPS machine code and not where only
user microMIPS software is supported.  The former is controlled with the
CPU_MICROMIPS configuration setting, whereas SYS_SUPPORTS_MICROMIPS is
used for the latter.

Not only that, but with a given microMIPS vs standard MIPS kernel 
configuration only one microassembler is needed, that matches the ISA 
selected -- CP0.Config3.ISAOnExc is mandatory on microMIPS processors, 
so there is never a need to mix microMIPS and standard MIPS code.

Consequently build only the microassembler that matches the ISA selected 
for the kernel.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
linux-mips-uasm-micromips.diff
Index: linux-3.17-stable-malta/arch/mips/mm/Makefile
===================================================================
--- linux-3.17-stable-malta.orig/arch/mips/mm/Makefile	2014-11-14 19:44:22.000000000 +0000
+++ linux-3.17-stable-malta/arch/mips/mm/Makefile	2014-11-14 19:44:52.031933464 +0000
@@ -4,7 +4,13 @@
 
 obj-y				+= cache.o dma-default.o extable.o fault.o \
 				   gup.o init.o mmap.o page.o page-funcs.o \
-				   tlbex.o tlbex-fault.o tlb-funcs.o uasm-mips.o
+				   tlbex.o tlbex-fault.o tlb-funcs.o
+
+ifdef CONFIG_CPU_MICROMIPS
+obj-y				+= uasm-micromips.o
+else
+obj-y				+= uasm-mips.o
+endif
 
 obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
@@ -22,5 +28,3 @@ obj-$(CONFIG_IP22_CPU_SCACHE)	+= sc-ip22
 obj-$(CONFIG_R5000_CPU_SCACHE)	+= sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
-
-obj-$(CONFIG_SYS_SUPPORTS_MICROMIPS) += uasm-micromips.o

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 3/7] MIPS: signal.c: Fix an invalid cast in ISA mode bit handling
@ 2014-11-15 22:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Fix:

arch/mips/kernel/signal.c: In function 'handle_signal':
arch/mips/kernel/signal.c:533:21: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
  unsigned int tmp = (unsigned int)current->mm->context.vdso;
                     ^
arch/mips/kernel/signal.c:536:9: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
  vdso = (void *)tmp;
         ^
cc1: all warnings being treated as errors

when building a 64-bit kernel.

This is not really a supported configuration, but the cast is wrong 
either way, Linux makes the assumption that sizeof(void *) equals 
sizeof(unsigned long) and therefore the latter type is expected to be 
used where integer operations have to be applied to pointers for some 
reason.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
linux-umips-pointer-size.diff
Index: linux-3.17-stable-malta64/arch/mips/kernel/signal.c
===================================================================
--- linux-3.17-stable-malta64.orig/arch/mips/kernel/signal.c	2014-11-14 04:06:50.000000000 +0000
+++ linux-3.17-stable-malta64/arch/mips/kernel/signal.c	2014-11-14 16:55:05.891621120 +0000
@@ -530,7 +530,7 @@ static void handle_signal(struct ksignal
 	struct mips_abi *abi = current->thread.abi;
 #ifdef CONFIG_CPU_MICROMIPS
 	void *vdso;
-	unsigned int tmp = (unsigned int)current->mm->context.vdso;
+	unsigned long tmp = (unsigned long)current->mm->context.vdso;
 
 	set_isa16_mode(tmp);
 	vdso = (void *)tmp;

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 3/7] MIPS: signal.c: Fix an invalid cast in ISA mode bit handling
@ 2014-11-15 22:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Fix:

arch/mips/kernel/signal.c: In function 'handle_signal':
arch/mips/kernel/signal.c:533:21: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
  unsigned int tmp = (unsigned int)current->mm->context.vdso;
                     ^
arch/mips/kernel/signal.c:536:9: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
  vdso = (void *)tmp;
         ^
cc1: all warnings being treated as errors

when building a 64-bit kernel.

This is not really a supported configuration, but the cast is wrong 
either way, Linux makes the assumption that sizeof(void *) equals 
sizeof(unsigned long) and therefore the latter type is expected to be 
used where integer operations have to be applied to pointers for some 
reason.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
linux-umips-pointer-size.diff
Index: linux-3.17-stable-malta64/arch/mips/kernel/signal.c
===================================================================
--- linux-3.17-stable-malta64.orig/arch/mips/kernel/signal.c	2014-11-14 04:06:50.000000000 +0000
+++ linux-3.17-stable-malta64/arch/mips/kernel/signal.c	2014-11-14 16:55:05.891621120 +0000
@@ -530,7 +530,7 @@ static void handle_signal(struct ksignal
 	struct mips_abi *abi = current->thread.abi;
 #ifdef CONFIG_CPU_MICROMIPS
 	void *vdso;
-	unsigned int tmp = (unsigned int)current->mm->context.vdso;
+	unsigned long tmp = (unsigned long)current->mm->context.vdso;
 
 	set_isa16_mode(tmp);
 	vdso = (void *)tmp;

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 4/7] MIPS: Kconfig: Only allow 32-bit microMIPS builds
@ 2014-11-15 22:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Only allow 32-bit microMIPS builds, we're not ready yet for 64-bit 
microMIPS support.

QEMU does have support for the 64-bit microMIPS ISA and with minor 
tweaks it is possible to have a 64-bit processor emulated there that 
runs microMIPS code, so despite the lack of actual 64-bit microMIPS 
hardware there is a way to run 64-bit microMIPS Linux, but it can all be 
considered early development and we are not there yet.  Userland tools 
are lacking too, e.g. GCC produces bad code:

{standard input}: Assembler messages:
{standard input}:380: Warning: wrong size instruction in a 16-bit branch delay slot

And our build fails early on, so disable the configuration, for the sake 
of automatic random config checkers if nothing else.  Whoever needs to 
experiment with 64-bit microMIPS support can revert this change easily.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
linux-umips-32bit.diff
Index: linux-3.18-rc4-malta/arch/mips/Kconfig
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/Kconfig	2014-11-15 05:55:56.441902868 +0000
+++ linux-3.18-rc4-malta/arch/mips/Kconfig	2014-11-15 05:56:01.941907996 +0000
@@ -2115,7 +2115,7 @@ config CPU_HAS_SMARTMIPS
 	  here.
 
 config CPU_MICROMIPS
-	depends on SYS_SUPPORTS_MICROMIPS
+	depends on 32BIT && SYS_SUPPORTS_MICROMIPS
 	bool "Build kernel using microMIPS ISA"
 	help
 	  When this option is enabled the kernel will be built using the

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 4/7] MIPS: Kconfig: Only allow 32-bit microMIPS builds
@ 2014-11-15 22:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Only allow 32-bit microMIPS builds, we're not ready yet for 64-bit 
microMIPS support.

QEMU does have support for the 64-bit microMIPS ISA and with minor 
tweaks it is possible to have a 64-bit processor emulated there that 
runs microMIPS code, so despite the lack of actual 64-bit microMIPS 
hardware there is a way to run 64-bit microMIPS Linux, but it can all be 
considered early development and we are not there yet.  Userland tools 
are lacking too, e.g. GCC produces bad code:

{standard input}: Assembler messages:
{standard input}:380: Warning: wrong size instruction in a 16-bit branch delay slot

And our build fails early on, so disable the configuration, for the sake 
of automatic random config checkers if nothing else.  Whoever needs to 
experiment with 64-bit microMIPS support can revert this change easily.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
linux-umips-32bit.diff
Index: linux-3.18-rc4-malta/arch/mips/Kconfig
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/Kconfig	2014-11-15 05:55:56.441902868 +0000
+++ linux-3.18-rc4-malta/arch/mips/Kconfig	2014-11-15 05:56:01.941907996 +0000
@@ -2115,7 +2115,7 @@ config CPU_HAS_SMARTMIPS
 	  here.
 
 config CPU_MICROMIPS
-	depends on SYS_SUPPORTS_MICROMIPS
+	depends on 32BIT && SYS_SUPPORTS_MICROMIPS
 	bool "Build kernel using microMIPS ISA"
 	help
 	  When this option is enabled the kernel will be built using the

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 5/7] MIPS: Fix microMIPS LL/SC immediate offsets
@ 2014-11-15 22:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

In the microMIPS encoding some memory access instructions have their 
immediate offset reduced to 12 bits only.  That does not match the GCC 
`R' constraint we use in some places to satisfy the requirement, 
resulting in build failures like this:

{standard input}: Assembler messages:
{standard input}:720: Error: macro used $at after ".set noat"
{standard input}:720: Warning: macro instruction expanded into multiple instructions

Fix the problem by defining a macro, `GCC_OFF12_ASM', that expands to 
the right constraint depending on whether microMIPS or standard MIPS 
code is produced.  Also apply the fix to where `m' is used as in the 
worst case this change does nothing, e.g. where the pointer was already 
in a register such as a function argument and no further offset was 
requested, and in the best case it avoids an extraneous sequence of up 
to two instructions to load the high 20 bits of the address in the LL/SC 
loop.  This reduces the risk of lock contention that is the higher the 
more instructions there are in the critical section between LL and SC.

Strictly speaking we could just bulk-replace `R' with `ZC' as the latter 
constraint adjusts automatically depending on the ISA selected.  
However it was only introduced with GCC 4.9 and we keep supporing older 
compilers for the standard MIPS configuration, hence the slightly more 
complicated approach I chose.

The choice of a zero-argument function-like rather than an object-like 
macro was made so that it does not look like a function call taking the 
C expression used for the constraint as an argument.  This is so as not 
to confuse the reader or formatting checkers like `checkpatch.pl' and 
follows previous practice.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 This has been discussed before and I already recommended implementing 
it, but nobody bothered -- I guess that means nobody actually maintains 
the microMIPS port.  Anyway I needed to build a working kernel (well it 
still does not boot as at 3.17, I'll have to debug it, it stops with a 
fault at giving away the initial console, at which point no exception 
handler has been installed yet, probably a BUG() somewhere) so I went 
ahead and implemented the missing bits.

 In the process of updating these constraints I noticed there were many 
inconsistencies and bugs, but I decided enough is enough.  Therefore 
this change merely replaces the existing constraints in place without 
any semantic rearrangements.

 Also sometime recently someone has reformatted the file breaking our 
coding convention rule not to extend lines beyond 79 columns and making 
it completely unreadable in the sections affected.  I don't know why 
such a change was accepted, it shouldn't have been.

 Anyway, I decided the bug fix has a priority so this change retains the 
broken formatting and I'll be bringing sanity back here with a follow-up 
change.

 Please apply,

  Maciej

linux-umips-off12-constraint.diff
Index: linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/atomic.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h	2014-11-15 05:55:38.441902949 +0000
@@ -17,6 +17,7 @@
 #include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
+#include <asm/compiler.h>
 #include <asm/cpu-features.h>
 #include <asm/cmpxchg.h>
 #include <asm/war.h>
@@ -53,7 +54,7 @@ static __inline__ void atomic_##op(int i
 		"	sc	%0, %1					\n"	\
 		"	beqzl	%0, 1b					\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+m" (v->counter)				\
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		int temp;							\
@@ -65,7 +66,7 @@ static __inline__ void atomic_##op(int i
 			"	" #asm_op " %0, %2			\n"	\
 			"	sc	%0, %1				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+m" (v->counter)			\
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
 			: "Ir" (i));						\
 		} while (unlikely(!temp));					\
 	} else {								\
@@ -95,7 +96,8 @@ static __inline__ int atomic_##op##_retu
 		"	beqzl	%0, 1b					\n"	\
 		"	" #asm_op " %0, %1, %3				\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)		\
+		: "=&r" (result), "=&r" (temp),					\
+		  "+" GCC_OFF12_ASM() (v->counter)				\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		int temp;							\
@@ -107,7 +109,8 @@ static __inline__ int atomic_##op##_retu
 			"	" #asm_op " %0, %1, %3			\n"	\
 			"	sc	%0, %2				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp), "+m" (v->counter)	\
+			: "=&r" (result), "=&r" (temp),				\
+			  "+" GCC_OFF12_ASM() (v->counter)			\
 			: "Ir" (i));						\
 		} while (unlikely(!result));					\
 										\
@@ -167,8 +170,9 @@ static __inline__ int atomic_sub_if_posi
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
-		: "Ir" (i), "m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "+" GCC_OFF12_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		int temp;
@@ -185,7 +189,8 @@ static __inline__ int atomic_sub_if_posi
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "+" GCC_OFF12_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
@@ -328,7 +333,7 @@ static __inline__ void atomic64_##op(lon
 		"	scd	%0, %1					\n"	\
 		"	beqzl	%0, 1b					\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+m" (v->counter)				\
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		long temp;							\
@@ -340,7 +345,7 @@ static __inline__ void atomic64_##op(lon
 			"	" #asm_op " %0, %2			\n"	\
 			"	scd	%0, %1				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+m" (v->counter)			\
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
 			: "Ir" (i));						\
 		} while (unlikely(!temp));					\
 	} else {								\
@@ -370,7 +375,8 @@ static __inline__ long atomic64_##op##_r
 		"	beqzl	%0, 1b					\n"	\
 		"	" #asm_op " %0, %1, %3				\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)		\
+		: "=&r" (result), "=&r" (temp),					\
+		  "+" GCC_OFF12_ASM() (v->counter)				\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		long temp;							\
@@ -382,8 +388,9 @@ static __inline__ long atomic64_##op##_r
 			"	" #asm_op " %0, %1, %3			\n"	\
 			"	scd	%0, %2				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp), "=m" (v->counter)	\
-			: "Ir" (i), "m" (v->counter)				\
+			: "=&r" (result), "=&r" (temp),				\
+			  "=" GCC_OFF12_ASM() (v->counter)			\
+			: "Ir" (i), GCC_OFF12_ASM() (v->counter)		\
 			: "memory");						\
 		} while (unlikely(!result));					\
 										\
@@ -443,8 +450,9 @@ static __inline__ long atomic64_sub_if_p
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
-		: "Ir" (i), "m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "=" GCC_OFF12_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		long temp;
@@ -461,7 +469,8 @@ static __inline__ long atomic64_sub_if_p
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "+" GCC_OFF12_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
Index: linux-3.18-rc4-malta/arch/mips/include/asm/bitops.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/bitops.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/bitops.h	2014-11-15 05:48:25.871909457 +0000
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>		/* sigh ... */
+#include <asm/compiler.h>
 #include <asm/cpu-features.h>
 #include <asm/sgidefs.h>
 #include <asm/war.h>
@@ -78,8 +79,8 @@ static inline void set_bit(unsigned long
 		"	" __SC	"%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=m" (*m)
-		: "ir" (1UL << bit), "m" (*m));
+		: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
+		: "ir" (1UL << bit), GCC_OFF12_ASM() (*m));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
@@ -87,7 +88,7 @@ static inline void set_bit(unsigned long
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -99,7 +100,7 @@ static inline void set_bit(unsigned long
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -130,7 +131,7 @@ static inline void clear_bit(unsigned lo
 		"	" __SC "%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 		: "ir" (~(1UL << bit)));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
@@ -139,7 +140,7 @@ static inline void clear_bit(unsigned lo
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -151,7 +152,7 @@ static inline void clear_bit(unsigned lo
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (~(1UL << bit)));
 		} while (unlikely(!temp));
 	} else
@@ -196,7 +197,7 @@ static inline void change_bit(unsigned l
 		"	" __SC	"%0, %1				\n"
 		"	beqzl	%0, 1b				\n"
 		"	.set	mips0				\n"
-		: "=&r" (temp), "+m" (*m)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 		: "ir" (1UL << bit));
 	} else if (kernel_uses_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -209,7 +210,7 @@ static inline void change_bit(unsigned l
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -244,7 +245,7 @@ static inline int test_and_set_bit(unsig
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -258,7 +259,7 @@ static inline int test_and_set_bit(unsig
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -312,7 +313,7 @@ static inline int test_and_set_bit_lock(
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -354,7 +355,7 @@ static inline int test_and_clear_bit(uns
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 #ifdef CONFIG_CPU_MIPSR2
@@ -368,7 +369,7 @@ static inline int test_and_clear_bit(uns
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
 			"	" __SC	"%0, %1				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "ir" (bit)
 			: "memory");
 		} while (unlikely(!temp));
@@ -385,7 +386,7 @@ static inline int test_and_clear_bit(uns
 			"	xor	%2, %3				\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -427,7 +428,7 @@ static inline int test_and_change_bit(un
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -441,7 +442,7 @@ static inline int test_and_change_bit(un
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
Index: linux-3.18-rc4-malta/arch/mips/include/asm/cmpxchg.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/cmpxchg.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/cmpxchg.h	2014-11-15 05:48:25.871909457 +0000
@@ -10,6 +10,7 @@
 
 #include <linux/bug.h>
 #include <linux/irqflags.h>
+#include <asm/compiler.h>
 #include <asm/war.h>
 
 static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
@@ -30,8 +31,8 @@ static inline unsigned long __xchg_u32(v
 		"	sc	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-		: "R" (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF12_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -45,8 +46,9 @@ static inline unsigned long __xchg_u32(v
 			"	.set	arch=r4000			\n"
 			"	sc	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			  "=&r" (dummy)
+			: GCC_OFF12_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -80,8 +82,8 @@ static inline __u64 __xchg_u64(volatile 
 		"	scd	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-		: "R" (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF12_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -93,8 +95,9 @@ static inline __u64 __xchg_u64(volatile 
 			"	move	%2, %z4				\n"
 			"	scd	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			  "=&r" (dummy)
+			: GCC_OFF12_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -155,8 +158,8 @@ static inline unsigned long __xchg(unsig
 		"	beqzl	$1, 1b				\n"	\
 		"2:						\n"	\
 		"	.set	pop				\n"	\
-		: "=&r" (__ret), "=R" (*m)				\
-		: "R" (*m), "Jr" (old), "Jr" (new)			\
+		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
+		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else if (kernel_uses_llsc) {					\
 		__asm__ __volatile__(					\
@@ -172,8 +175,8 @@ static inline unsigned long __xchg(unsig
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
-		: "=&r" (__ret), "=R" (*m)				\
-		: "R" (*m), "Jr" (old), "Jr" (new)			\
+		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
+		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else {							\
 		unsigned long __flags;					\
Index: linux-3.18-rc4-malta/arch/mips/include/asm/compiler.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/compiler.h	2012-09-12 21:33:05.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/compiler.h	2014-11-15 05:48:25.871909457 +0000
@@ -16,4 +16,12 @@
 #define GCC_REG_ACCUM "accum"
 #endif
 
+#ifndef CONFIG_CPU_MICROMIPS
+#define GCC_OFF12_ASM() "R"
+#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
+#define GCC_OFF12_ASM() "ZC"
+#else
+#error "microMIPS compilation unsupported with GCC older than 4.9"
+#endif
+
 #endif /* _ASM_COMPILER_H */
Index: linux-3.18-rc4-malta/arch/mips/include/asm/edac.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/edac.h	2012-09-12 21:33:05.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/edac.h	2014-11-15 05:48:25.871909457 +0000
@@ -1,6 +1,8 @@
 #ifndef ASM_EDAC_H
 #define ASM_EDAC_H
 
+#include <asm/compiler.h>
+
 /* ECC atomic, DMA, SMP and interrupt safe scrub function */
 
 static inline void atomic_scrub(void *va, u32 size)
@@ -24,8 +26,8 @@ static inline void atomic_scrub(void *va
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=m" (*virt_addr)
-		: "m" (*virt_addr));
+		: "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr)
+		: GCC_OFF12_ASM() (*virt_addr));
 
 		virt_addr++;
 	}
Index: linux-3.18-rc4-malta/arch/mips/include/asm/futex.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/futex.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/futex.h	2014-11-15 05:48:25.871909457 +0000
@@ -14,6 +14,7 @@
 #include <linux/uaccess.h>
 #include <asm/asm-eva.h>
 #include <asm/barrier.h>
+#include <asm/compiler.h>
 #include <asm/errno.h>
 #include <asm/war.h>
 
@@ -42,8 +43,10 @@
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
-		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "=r" (ret), "=&r" (oldval),				\
+		  "=" GCC_OFF12_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else if (cpu_has_llsc) {					\
 		__asm__ __volatile__(					\
@@ -68,8 +71,10 @@
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
-		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "=r" (ret), "=&r" (oldval),				\
+		  "=" GCC_OFF12_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else								\
 		ret = -ENOSYS;						\
@@ -166,8 +171,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
-		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
+		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		  "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
@@ -193,8 +199,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
-		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
+		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		  "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
Index: linux-3.18-rc4-malta/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h	2014-11-15 05:48:25.871909457 +0000
@@ -49,6 +49,7 @@
 
 #include <linux/types.h>
 
+#include <asm/compiler.h>
 #include <asm/war.h>
 
 #ifndef R10000_LLSC_WAR
@@ -84,8 +85,8 @@ static inline void set_value_reg32(volat
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (~mask), "ir" (value), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -105,8 +106,8 @@ static inline void set_reg32(volatile u3
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (mask), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (mask), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -126,8 +127,8 @@ static inline void clear_reg32(volatile 
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (~mask), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (~mask), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -147,8 +148,8 @@ static inline void toggle_reg32(volatile
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (mask), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (mask), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -219,8 +220,8 @@ static inline u32 blocking_read_reg32(vo
 	"	.set	arch=r4000			\n"	\
 	"1:	ll	%0, %1	#custom_read_reg32	\n"	\
 	"	.set	pop				\n"	\
-	: "=r" (tmp), "=m" (*address)				\
-	: "m" (*address))
+	: "=r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
+	: GCC_OFF12_ASM() (*address))
 
 #define custom_write_reg32(address, tmp)			\
 	__asm__ __volatile__(					\
@@ -230,7 +231,7 @@ static inline u32 blocking_read_reg32(vo
 	"	"__beqz"%0, 1b				\n"	\
 	"	nop					\n"	\
 	"	.set	pop				\n"	\
-	: "=&r" (tmp), "=m" (*address)				\
-	: "0" (tmp), "m" (*address))
+	: "=&r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
+	: "0" (tmp), GCC_OFF12_ASM() (*address))
 
 #endif	/* __ASM_REGOPS_H__ */
Index: linux-3.18-rc4-malta/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/octeon/cvmx-cmd-queue.h	2013-05-23 16:08:04.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/octeon/cvmx-cmd-queue.h	2014-11-15 05:48:25.871909457 +0000
@@ -76,6 +76,8 @@
 
 #include <linux/prefetch.h>
 
+#include <asm/compiler.h>
+
 #include <asm/octeon/cvmx-fpa.h>
 /**
  * By default we disable the max depth support. Most programs
@@ -273,7 +275,7 @@ static inline void __cvmx_cmd_queue_lock
 		" lbu	%[ticket], %[now_serving]\n"
 		"4:\n"
 		".set pop\n" :
-		[ticket_ptr] "=m"(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
+		[ticket_ptr] "=" GCC_OFF12_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
 		[now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
 		[my_ticket] "=r"(my_ticket)
 	    );
Index: linux-3.18-rc4-malta/arch/mips/include/asm/spinlock.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/spinlock.h	2013-05-23 16:08:04.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/spinlock.h	2014-11-15 05:48:25.871909457 +0000
@@ -12,6 +12,7 @@
 #include <linux/compiler.h>
 
 #include <asm/barrier.h>
+#include <asm/compiler.h>
 #include <asm/war.h>
 
 /*
@@ -88,7 +89,7 @@ static inline void arch_spin_lock(arch_s
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -121,7 +122,7 @@ static inline void arch_spin_lock(arch_s
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -163,7 +164,7 @@ static inline unsigned int arch_spin_try
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -187,7 +188,7 @@ static inline unsigned int arch_spin_try
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -234,8 +235,8 @@ static inline void arch_read_lock(arch_r
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=m" (rw->lock), "=&r" (tmp)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -244,8 +245,8 @@ static inline void arch_read_lock(arch_r
 			"	bltz	%1, 1b				\n"
 			"	 addu	%1, 1				\n"
 			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -268,8 +269,8 @@ static inline void arch_read_unlock(arch
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
-		: "=m" (rw->lock), "=&r" (tmp)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -277,8 +278,8 @@ static inline void arch_read_unlock(arch
 			"1:	ll	%1, %2	# arch_read_unlock	\n"
 			"	sub	%1, 1				\n"
 			"	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -298,8 +299,8 @@ static inline void arch_write_lock(arch_
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=m" (rw->lock), "=&r" (tmp)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -308,8 +309,8 @@ static inline void arch_write_lock(arch_
 			"	bnez	%1, 1b				\n"
 			"	 lui	%1, 0x8000			\n"
 			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -348,8 +349,8 @@ static inline int arch_read_trylock(arch
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		__asm__ __volatile__(
@@ -365,8 +366,8 @@ static inline int arch_read_trylock(arch
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	}
 
@@ -392,8 +393,8 @@ static inline int arch_write_trylock(arc
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -405,8 +406,9 @@ static inline int arch_write_trylock(arc
 			"	sc	%1, %0				\n"
 			"	li	%2, 1				\n"
 			"2:						\n"
-			: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp),
+			  "=&r" (ret)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 5/7] MIPS: Fix microMIPS LL/SC immediate offsets
@ 2014-11-15 22:08   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:08 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

In the microMIPS encoding some memory access instructions have their 
immediate offset reduced to 12 bits only.  That does not match the GCC 
`R' constraint we use in some places to satisfy the requirement, 
resulting in build failures like this:

{standard input}: Assembler messages:
{standard input}:720: Error: macro used $at after ".set noat"
{standard input}:720: Warning: macro instruction expanded into multiple instructions

Fix the problem by defining a macro, `GCC_OFF12_ASM', that expands to 
the right constraint depending on whether microMIPS or standard MIPS 
code is produced.  Also apply the fix to where `m' is used as in the 
worst case this change does nothing, e.g. where the pointer was already 
in a register such as a function argument and no further offset was 
requested, and in the best case it avoids an extraneous sequence of up 
to two instructions to load the high 20 bits of the address in the LL/SC 
loop.  This reduces the risk of lock contention that is the higher the 
more instructions there are in the critical section between LL and SC.

Strictly speaking we could just bulk-replace `R' with `ZC' as the latter 
constraint adjusts automatically depending on the ISA selected.  
However it was only introduced with GCC 4.9 and we keep supporing older 
compilers for the standard MIPS configuration, hence the slightly more 
complicated approach I chose.

The choice of a zero-argument function-like rather than an object-like 
macro was made so that it does not look like a function call taking the 
C expression used for the constraint as an argument.  This is so as not 
to confuse the reader or formatting checkers like `checkpatch.pl' and 
follows previous practice.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 This has been discussed before and I already recommended implementing 
it, but nobody bothered -- I guess that means nobody actually maintains 
the microMIPS port.  Anyway I needed to build a working kernel (well it 
still does not boot as at 3.17, I'll have to debug it, it stops with a 
fault at giving away the initial console, at which point no exception 
handler has been installed yet, probably a BUG() somewhere) so I went 
ahead and implemented the missing bits.

 In the process of updating these constraints I noticed there were many 
inconsistencies and bugs, but I decided enough is enough.  Therefore 
this change merely replaces the existing constraints in place without 
any semantic rearrangements.

 Also sometime recently someone has reformatted the file breaking our 
coding convention rule not to extend lines beyond 79 columns and making 
it completely unreadable in the sections affected.  I don't know why 
such a change was accepted, it shouldn't have been.

 Anyway, I decided the bug fix has a priority so this change retains the 
broken formatting and I'll be bringing sanity back here with a follow-up 
change.

 Please apply,

  Maciej

linux-umips-off12-constraint.diff
Index: linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/atomic.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h	2014-11-15 05:55:38.441902949 +0000
@@ -17,6 +17,7 @@
 #include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
+#include <asm/compiler.h>
 #include <asm/cpu-features.h>
 #include <asm/cmpxchg.h>
 #include <asm/war.h>
@@ -53,7 +54,7 @@ static __inline__ void atomic_##op(int i
 		"	sc	%0, %1					\n"	\
 		"	beqzl	%0, 1b					\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+m" (v->counter)				\
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		int temp;							\
@@ -65,7 +66,7 @@ static __inline__ void atomic_##op(int i
 			"	" #asm_op " %0, %2			\n"	\
 			"	sc	%0, %1				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+m" (v->counter)			\
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
 			: "Ir" (i));						\
 		} while (unlikely(!temp));					\
 	} else {								\
@@ -95,7 +96,8 @@ static __inline__ int atomic_##op##_retu
 		"	beqzl	%0, 1b					\n"	\
 		"	" #asm_op " %0, %1, %3				\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)		\
+		: "=&r" (result), "=&r" (temp),					\
+		  "+" GCC_OFF12_ASM() (v->counter)				\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		int temp;							\
@@ -107,7 +109,8 @@ static __inline__ int atomic_##op##_retu
 			"	" #asm_op " %0, %1, %3			\n"	\
 			"	sc	%0, %2				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp), "+m" (v->counter)	\
+			: "=&r" (result), "=&r" (temp),				\
+			  "+" GCC_OFF12_ASM() (v->counter)			\
 			: "Ir" (i));						\
 		} while (unlikely(!result));					\
 										\
@@ -167,8 +170,9 @@ static __inline__ int atomic_sub_if_posi
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
-		: "Ir" (i), "m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "+" GCC_OFF12_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		int temp;
@@ -185,7 +189,8 @@ static __inline__ int atomic_sub_if_posi
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "+" GCC_OFF12_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
@@ -328,7 +333,7 @@ static __inline__ void atomic64_##op(lon
 		"	scd	%0, %1					\n"	\
 		"	beqzl	%0, 1b					\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+m" (v->counter)				\
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		long temp;							\
@@ -340,7 +345,7 @@ static __inline__ void atomic64_##op(lon
 			"	" #asm_op " %0, %2			\n"	\
 			"	scd	%0, %1				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+m" (v->counter)			\
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
 			: "Ir" (i));						\
 		} while (unlikely(!temp));					\
 	} else {								\
@@ -370,7 +375,8 @@ static __inline__ long atomic64_##op##_r
 		"	beqzl	%0, 1b					\n"	\
 		"	" #asm_op " %0, %1, %3				\n"	\
 		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)		\
+		: "=&r" (result), "=&r" (temp),					\
+		  "+" GCC_OFF12_ASM() (v->counter)				\
 		: "Ir" (i));							\
 	} else if (kernel_uses_llsc) {						\
 		long temp;							\
@@ -382,8 +388,9 @@ static __inline__ long atomic64_##op##_r
 			"	" #asm_op " %0, %1, %3			\n"	\
 			"	scd	%0, %2				\n"	\
 			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp), "=m" (v->counter)	\
-			: "Ir" (i), "m" (v->counter)				\
+			: "=&r" (result), "=&r" (temp),				\
+			  "=" GCC_OFF12_ASM() (v->counter)			\
+			: "Ir" (i), GCC_OFF12_ASM() (v->counter)		\
 			: "memory");						\
 		} while (unlikely(!result));					\
 										\
@@ -443,8 +450,9 @@ static __inline__ long atomic64_sub_if_p
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
-		: "Ir" (i), "m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "=" GCC_OFF12_ASM() (v->counter)
+		: "Ir" (i), GCC_OFF12_ASM() (v->counter)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		long temp;
@@ -461,7 +469,8 @@ static __inline__ long atomic64_sub_if_p
 		"	.set	reorder					\n"
 		"1:							\n"
 		"	.set	mips0					\n"
-		: "=&r" (result), "=&r" (temp), "+m" (v->counter)
+		: "=&r" (result), "=&r" (temp),
+		  "+" GCC_OFF12_ASM() (v->counter)
 		: "Ir" (i));
 	} else {
 		unsigned long flags;
Index: linux-3.18-rc4-malta/arch/mips/include/asm/bitops.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/bitops.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/bitops.h	2014-11-15 05:48:25.871909457 +0000
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>		/* sigh ... */
+#include <asm/compiler.h>
 #include <asm/cpu-features.h>
 #include <asm/sgidefs.h>
 #include <asm/war.h>
@@ -78,8 +79,8 @@ static inline void set_bit(unsigned long
 		"	" __SC	"%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=m" (*m)
-		: "ir" (1UL << bit), "m" (*m));
+		: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
+		: "ir" (1UL << bit), GCC_OFF12_ASM() (*m));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
 		do {
@@ -87,7 +88,7 @@ static inline void set_bit(unsigned long
 			"	" __LL "%0, %1		# set_bit	\n"
 			"	" __INS "%0, %3, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit), "r" (~0));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -99,7 +100,7 @@ static inline void set_bit(unsigned long
 			"	or	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -130,7 +131,7 @@ static inline void clear_bit(unsigned lo
 		"	" __SC "%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 		: "ir" (~(1UL << bit)));
 #ifdef CONFIG_CPU_MIPSR2
 	} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
@@ -139,7 +140,7 @@ static inline void clear_bit(unsigned lo
 			"	" __LL "%0, %1		# clear_bit	\n"
 			"	" __INS "%0, $0, %2, 1			\n"
 			"	" __SC "%0, %1				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (bit));
 		} while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 */
@@ -151,7 +152,7 @@ static inline void clear_bit(unsigned lo
 			"	and	%0, %2				\n"
 			"	" __SC "%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (~(1UL << bit)));
 		} while (unlikely(!temp));
 	} else
@@ -196,7 +197,7 @@ static inline void change_bit(unsigned l
 		"	" __SC	"%0, %1				\n"
 		"	beqzl	%0, 1b				\n"
 		"	.set	mips0				\n"
-		: "=&r" (temp), "+m" (*m)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 		: "ir" (1UL << bit));
 	} else if (kernel_uses_llsc) {
 		unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -209,7 +210,7 @@ static inline void change_bit(unsigned l
 			"	xor	%0, %2				\n"
 			"	" __SC	"%0, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
 			: "ir" (1UL << bit));
 		} while (unlikely(!temp));
 	} else
@@ -244,7 +245,7 @@ static inline int test_and_set_bit(unsig
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -258,7 +259,7 @@ static inline int test_and_set_bit(unsig
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -312,7 +313,7 @@ static inline int test_and_set_bit_lock(
 			"	or	%2, %0, %3			\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -354,7 +355,7 @@ static inline int test_and_clear_bit(uns
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 #ifdef CONFIG_CPU_MIPSR2
@@ -368,7 +369,7 @@ static inline int test_and_clear_bit(uns
 			"	" __EXT "%2, %0, %3, 1			\n"
 			"	" __INS "%0, $0, %3, 1			\n"
 			"	" __SC	"%0, %1				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "ir" (bit)
 			: "memory");
 		} while (unlikely(!temp));
@@ -385,7 +386,7 @@ static inline int test_and_clear_bit(uns
 			"	xor	%2, %3				\n"
 			"	" __SC	"%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
@@ -427,7 +428,7 @@ static inline int test_and_change_bit(un
 		"	beqzl	%2, 1b					\n"
 		"	and	%2, %0, %3				\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "+m" (*m), "=&r" (res)
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 		: "r" (1UL << bit)
 		: "memory");
 	} else if (kernel_uses_llsc) {
@@ -441,7 +442,7 @@ static inline int test_and_change_bit(un
 			"	xor	%2, %0, %3			\n"
 			"	" __SC	"\t%2, %1			\n"
 			"	.set	mips0				\n"
-			: "=&r" (temp), "+m" (*m), "=&r" (res)
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
 			: "r" (1UL << bit)
 			: "memory");
 		} while (unlikely(!res));
Index: linux-3.18-rc4-malta/arch/mips/include/asm/cmpxchg.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/cmpxchg.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/cmpxchg.h	2014-11-15 05:48:25.871909457 +0000
@@ -10,6 +10,7 @@
 
 #include <linux/bug.h>
 #include <linux/irqflags.h>
+#include <asm/compiler.h>
 #include <asm/war.h>
 
 static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
@@ -30,8 +31,8 @@ static inline unsigned long __xchg_u32(v
 		"	sc	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-		: "R" (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF12_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -45,8 +46,9 @@ static inline unsigned long __xchg_u32(v
 			"	.set	arch=r4000			\n"
 			"	sc	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			  "=&r" (dummy)
+			: GCC_OFF12_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -80,8 +82,8 @@ static inline __u64 __xchg_u64(volatile 
 		"	scd	%2, %1					\n"
 		"	beqzl	%2, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-		: "R" (*m), "Jr" (val)
+		: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
+		: GCC_OFF12_ASM() (*m), "Jr" (val)
 		: "memory");
 	} else if (kernel_uses_llsc) {
 		unsigned long dummy;
@@ -93,8 +95,9 @@ static inline __u64 __xchg_u64(volatile 
 			"	move	%2, %z4				\n"
 			"	scd	%2, %1				\n"
 			"	.set	mips0				\n"
-			: "=&r" (retval), "=m" (*m), "=&r" (dummy)
-			: "R" (*m), "Jr" (val)
+			: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
+			  "=&r" (dummy)
+			: GCC_OFF12_ASM() (*m), "Jr" (val)
 			: "memory");
 		} while (unlikely(!dummy));
 	} else {
@@ -155,8 +158,8 @@ static inline unsigned long __xchg(unsig
 		"	beqzl	$1, 1b				\n"	\
 		"2:						\n"	\
 		"	.set	pop				\n"	\
-		: "=&r" (__ret), "=R" (*m)				\
-		: "R" (*m), "Jr" (old), "Jr" (new)			\
+		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
+		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else if (kernel_uses_llsc) {					\
 		__asm__ __volatile__(					\
@@ -172,8 +175,8 @@ static inline unsigned long __xchg(unsig
 		"	beqz	$1, 1b				\n"	\
 		"	.set	pop				\n"	\
 		"2:						\n"	\
-		: "=&r" (__ret), "=R" (*m)				\
-		: "R" (*m), "Jr" (old), "Jr" (new)			\
+		: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m)		\
+		: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new)		\
 		: "memory");						\
 	} else {							\
 		unsigned long __flags;					\
Index: linux-3.18-rc4-malta/arch/mips/include/asm/compiler.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/compiler.h	2012-09-12 21:33:05.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/compiler.h	2014-11-15 05:48:25.871909457 +0000
@@ -16,4 +16,12 @@
 #define GCC_REG_ACCUM "accum"
 #endif
 
+#ifndef CONFIG_CPU_MICROMIPS
+#define GCC_OFF12_ASM() "R"
+#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
+#define GCC_OFF12_ASM() "ZC"
+#else
+#error "microMIPS compilation unsupported with GCC older than 4.9"
+#endif
+
 #endif /* _ASM_COMPILER_H */
Index: linux-3.18-rc4-malta/arch/mips/include/asm/edac.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/edac.h	2012-09-12 21:33:05.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/edac.h	2014-11-15 05:48:25.871909457 +0000
@@ -1,6 +1,8 @@
 #ifndef ASM_EDAC_H
 #define ASM_EDAC_H
 
+#include <asm/compiler.h>
+
 /* ECC atomic, DMA, SMP and interrupt safe scrub function */
 
 static inline void atomic_scrub(void *va, u32 size)
@@ -24,8 +26,8 @@ static inline void atomic_scrub(void *va
 		"	sc	%0, %1					\n"
 		"	beqz	%0, 1b					\n"
 		"	.set	mips0					\n"
-		: "=&r" (temp), "=m" (*virt_addr)
-		: "m" (*virt_addr));
+		: "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr)
+		: GCC_OFF12_ASM() (*virt_addr));
 
 		virt_addr++;
 	}
Index: linux-3.18-rc4-malta/arch/mips/include/asm/futex.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/futex.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/futex.h	2014-11-15 05:48:25.871909457 +0000
@@ -14,6 +14,7 @@
 #include <linux/uaccess.h>
 #include <asm/asm-eva.h>
 #include <asm/barrier.h>
+#include <asm/compiler.h>
 #include <asm/errno.h>
 #include <asm/war.h>
 
@@ -42,8 +43,10 @@
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
-		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "=r" (ret), "=&r" (oldval),				\
+		  "=" GCC_OFF12_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else if (cpu_has_llsc) {					\
 		__asm__ __volatile__(					\
@@ -68,8 +71,10 @@
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
-		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "=r" (ret), "=&r" (oldval),				\
+		  "=" GCC_OFF12_ASM() (*uaddr)				\
+		: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg),	\
+		  "i" (-EFAULT)						\
 		: "memory");						\
 	} else								\
 		ret = -ENOSYS;						\
@@ -166,8 +171,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
-		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
+		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		  "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
 		__asm__ __volatile__(
@@ -193,8 +199,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
-		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+		: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
+		: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
+		  "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
Index: linux-3.18-rc4-malta/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/mach-pmcs-msp71xx/msp_regops.h	2014-11-15 05:48:25.871909457 +0000
@@ -49,6 +49,7 @@
 
 #include <linux/types.h>
 
+#include <asm/compiler.h>
 #include <asm/war.h>
 
 #ifndef R10000_LLSC_WAR
@@ -84,8 +85,8 @@ static inline void set_value_reg32(volat
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (~mask), "ir" (value), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -105,8 +106,8 @@ static inline void set_reg32(volatile u3
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (mask), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (mask), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -126,8 +127,8 @@ static inline void clear_reg32(volatile 
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (~mask), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (~mask), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -147,8 +148,8 @@ static inline void toggle_reg32(volatile
 	"	"__beqz"%0, 1b				\n"
 	"	nop					\n"
 	"	.set	pop				\n"
-	: "=&r" (temp), "=m" (*addr)
-	: "ir" (mask), "m" (*addr));
+	: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
+	: "ir" (mask), GCC_OFF12_ASM() (*addr));
 }
 
 /*
@@ -219,8 +220,8 @@ static inline u32 blocking_read_reg32(vo
 	"	.set	arch=r4000			\n"	\
 	"1:	ll	%0, %1	#custom_read_reg32	\n"	\
 	"	.set	pop				\n"	\
-	: "=r" (tmp), "=m" (*address)				\
-	: "m" (*address))
+	: "=r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
+	: GCC_OFF12_ASM() (*address))
 
 #define custom_write_reg32(address, tmp)			\
 	__asm__ __volatile__(					\
@@ -230,7 +231,7 @@ static inline u32 blocking_read_reg32(vo
 	"	"__beqz"%0, 1b				\n"	\
 	"	nop					\n"	\
 	"	.set	pop				\n"	\
-	: "=&r" (tmp), "=m" (*address)				\
-	: "0" (tmp), "m" (*address))
+	: "=&r" (tmp), "=" GCC_OFF12_ASM() (*address)		\
+	: "0" (tmp), GCC_OFF12_ASM() (*address))
 
 #endif	/* __ASM_REGOPS_H__ */
Index: linux-3.18-rc4-malta/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/octeon/cvmx-cmd-queue.h	2013-05-23 16:08:04.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/octeon/cvmx-cmd-queue.h	2014-11-15 05:48:25.871909457 +0000
@@ -76,6 +76,8 @@
 
 #include <linux/prefetch.h>
 
+#include <asm/compiler.h>
+
 #include <asm/octeon/cvmx-fpa.h>
 /**
  * By default we disable the max depth support. Most programs
@@ -273,7 +275,7 @@ static inline void __cvmx_cmd_queue_lock
 		" lbu	%[ticket], %[now_serving]\n"
 		"4:\n"
 		".set pop\n" :
-		[ticket_ptr] "=m"(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
+		[ticket_ptr] "=" GCC_OFF12_ASM()(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
 		[now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
 		[my_ticket] "=r"(my_ticket)
 	    );
Index: linux-3.18-rc4-malta/arch/mips/include/asm/spinlock.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/spinlock.h	2013-05-23 16:08:04.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/spinlock.h	2014-11-15 05:48:25.871909457 +0000
@@ -12,6 +12,7 @@
 #include <linux/compiler.h>
 
 #include <asm/barrier.h>
+#include <asm/compiler.h>
 #include <asm/war.h>
 
 /*
@@ -88,7 +89,7 @@ static inline void arch_spin_lock(arch_s
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -121,7 +122,7 @@ static inline void arch_spin_lock(arch_s
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [serving_now_ptr] "+m" (lock->h.serving_now),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (my_ticket)
@@ -163,7 +164,7 @@ static inline unsigned int arch_spin_try
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -187,7 +188,7 @@ static inline unsigned int arch_spin_try
 		"	 li	%[ticket], 0				\n"
 		"	.previous					\n"
 		"	.set pop					\n"
-		: [ticket_ptr] "+m" (lock->lock),
+		: [ticket_ptr] "+" GCC_OFF12_ASM() (lock->lock),
 		  [ticket] "=&r" (tmp),
 		  [my_ticket] "=&r" (tmp2),
 		  [now_serving] "=&r" (tmp3)
@@ -234,8 +235,8 @@ static inline void arch_read_lock(arch_r
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=m" (rw->lock), "=&r" (tmp)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -244,8 +245,8 @@ static inline void arch_read_lock(arch_r
 			"	bltz	%1, 1b				\n"
 			"	 addu	%1, 1				\n"
 			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -268,8 +269,8 @@ static inline void arch_read_unlock(arch
 		"	sub	%1, 1					\n"
 		"	sc	%1, %0					\n"
 		"	beqzl	%1, 1b					\n"
-		: "=m" (rw->lock), "=&r" (tmp)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -277,8 +278,8 @@ static inline void arch_read_unlock(arch
 			"1:	ll	%1, %2	# arch_read_unlock	\n"
 			"	sub	%1, 1				\n"
 			"	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -298,8 +299,8 @@ static inline void arch_write_lock(arch_
 		"	beqzl	%1, 1b					\n"
 		"	 nop						\n"
 		"	.set	reorder					\n"
-		: "=m" (rw->lock), "=&r" (tmp)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -308,8 +309,8 @@ static inline void arch_write_lock(arch_
 			"	bnez	%1, 1b				\n"
 			"	 lui	%1, 0x8000			\n"
 			"2:	sc	%1, %0				\n"
-			: "=m" (rw->lock), "=&r" (tmp)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 	}
@@ -348,8 +349,8 @@ static inline int arch_read_trylock(arch
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		__asm__ __volatile__(
@@ -365,8 +366,8 @@ static inline int arch_read_trylock(arch
 		__WEAK_LLSC_MB
 		"	li	%2, 1					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	}
 
@@ -392,8 +393,8 @@ static inline int arch_write_trylock(arc
 		"	li	%2, 1					\n"
 		"	.set	reorder					\n"
 		"2:							\n"
-		: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-		: "m" (rw->lock)
+		: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
+		: GCC_OFF12_ASM() (rw->lock)
 		: "memory");
 	} else {
 		do {
@@ -405,8 +406,9 @@ static inline int arch_write_trylock(arc
 			"	sc	%1, %0				\n"
 			"	li	%2, 1				\n"
 			"2:						\n"
-			: "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
-			: "m" (rw->lock)
+			: "=" GCC_OFF12_ASM() (rw->lock), "=&r" (tmp),
+			  "=&r" (ret)
+			: GCC_OFF12_ASM() (rw->lock)
 			: "memory");
 		} while (unlikely(!tmp));
 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout
@ 2014-11-15 22:09   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:09 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Fix the issue with the ISA bit being lost in fixups that jump to labels 
placed just before a section switch.  Such a switch leads to the ISA bit 
being lost, because GAS concludes there is no code that follows and 
therefore the label refers to data.  Use the `.insn' pseudo-op to 
convince the tool this is not the case.

This lack of label annotation leads to microMIPS compilation errors 
like:

mips-linux-gnu-ld: arch/mips/built-in.o: .fixup+0x3b8: Unsupported jump between ISA modes; consider recompiling with interlinking enabled.
mips-linux-gnu-ld: final link failed: Bad value

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 I see someone has just fixed this issue in one place, so I had to 
regenerate the change I originally made against 3.17, but I really fail 
to see why not to fix it throughout at once.

 Please apply,

  Maciej

linux-umips-fixup-insn.diff
Index: linux-3.18-rc4-malta/arch/mips/include/asm/futex.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/futex.h	2014-11-15 05:56:06.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/futex.h	2014-11-15 00:26:50.261902695 +0000
@@ -33,6 +33,7 @@
 		"	beqzl	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
+		"	.insn					\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.section .fixup,\"ax\"			\n"	\
@@ -61,6 +62,7 @@
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
+		"	.insn					\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.section .fixup,\"ax\"			\n"	\
@@ -162,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
+		"	.insn						\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
 		"4:	li	%0, %6					\n"
@@ -190,6 +193,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
+		"	.insn						\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
 		"4:	li	%0, %6					\n"
Index: linux-3.18-rc4-malta/arch/mips/include/asm/paccess.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/paccess.h	2013-05-23 16:08:04.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/paccess.h	2014-11-15 05:56:52.451903033 +0000
@@ -56,6 +56,7 @@ struct __large_pstruct { unsigned long b
 	"1:\t" insn "\t%1,%2\n\t"					\
 	"move\t%0,$0\n"							\
 	"2:\n\t"							\
+	".insn\n\t"							\
 	".section\t.fixup,\"ax\"\n"					\
 	"3:\tli\t%0,%3\n\t"						\
 	"move\t%1,$0\n\t"						\
@@ -94,6 +95,7 @@ extern void __get_dbe_unknown(void);
 	"1:\t" insn "\t%1,%2\n\t"					\
 	"move\t%0,$0\n"							\
 	"2:\n\t"							\
+	".insn\n\t"							\
 	".section\t.fixup,\"ax\"\n"					\
 	"3:\tli\t%0,%3\n\t"						\
 	"j\t2b\n\t"							\
Index: linux-3.18-rc4-malta/arch/mips/kernel/syscall.c
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/kernel/syscall.c	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/kernel/syscall.c	2014-11-15 05:56:52.451903033 +0000
@@ -117,6 +117,7 @@ static inline int mips_atomic_set(unsign
 		"2:	sc	%[tmp], (%[addr])			\n"
 		"	beqzl	%[tmp], 1b				\n"
 		"3:							\n"
+		"	.insn						\n"
 		"	.section .fixup,\"ax\"				\n"
 		"4:	li	%[err], %[efault]			\n"
 		"	j	3b					\n"
@@ -142,6 +143,7 @@ static inline int mips_atomic_set(unsign
 		"2:	sc	%[tmp], (%[addr])			\n"
 		"	bnez	%[tmp], 4f				\n"
 		"3:							\n"
+		"	.insn						\n"
 		"	.subsection 2					\n"
 		"4:	b	1b					\n"
 		"	.previous					\n"

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout
@ 2014-11-15 22:09   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:09 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Fix the issue with the ISA bit being lost in fixups that jump to labels 
placed just before a section switch.  Such a switch leads to the ISA bit 
being lost, because GAS concludes there is no code that follows and 
therefore the label refers to data.  Use the `.insn' pseudo-op to 
convince the tool this is not the case.

This lack of label annotation leads to microMIPS compilation errors 
like:

mips-linux-gnu-ld: arch/mips/built-in.o: .fixup+0x3b8: Unsupported jump between ISA modes; consider recompiling with interlinking enabled.
mips-linux-gnu-ld: final link failed: Bad value

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 I see someone has just fixed this issue in one place, so I had to 
regenerate the change I originally made against 3.17, but I really fail 
to see why not to fix it throughout at once.

 Please apply,

  Maciej

linux-umips-fixup-insn.diff
Index: linux-3.18-rc4-malta/arch/mips/include/asm/futex.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/futex.h	2014-11-15 05:56:06.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/futex.h	2014-11-15 00:26:50.261902695 +0000
@@ -33,6 +33,7 @@
 		"	beqzl	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
+		"	.insn					\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.section .fixup,\"ax\"			\n"	\
@@ -61,6 +62,7 @@
 		"	beqz	$1, 1b				\n"	\
 		__WEAK_LLSC_MB						\
 		"3:						\n"	\
+		"	.insn					\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.section .fixup,\"ax\"			\n"	\
@@ -162,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
+		"	.insn						\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
 		"4:	li	%0, %6					\n"
@@ -190,6 +193,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
+		"	.insn						\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
 		"4:	li	%0, %6					\n"
Index: linux-3.18-rc4-malta/arch/mips/include/asm/paccess.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/paccess.h	2013-05-23 16:08:04.000000000 +0100
+++ linux-3.18-rc4-malta/arch/mips/include/asm/paccess.h	2014-11-15 05:56:52.451903033 +0000
@@ -56,6 +56,7 @@ struct __large_pstruct { unsigned long b
 	"1:\t" insn "\t%1,%2\n\t"					\
 	"move\t%0,$0\n"							\
 	"2:\n\t"							\
+	".insn\n\t"							\
 	".section\t.fixup,\"ax\"\n"					\
 	"3:\tli\t%0,%3\n\t"						\
 	"move\t%1,$0\n\t"						\
@@ -94,6 +95,7 @@ extern void __get_dbe_unknown(void);
 	"1:\t" insn "\t%1,%2\n\t"					\
 	"move\t%0,$0\n"							\
 	"2:\n\t"							\
+	".insn\n\t"							\
 	".section\t.fixup,\"ax\"\n"					\
 	"3:\tli\t%0,%3\n\t"						\
 	"j\t2b\n\t"							\
Index: linux-3.18-rc4-malta/arch/mips/kernel/syscall.c
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/kernel/syscall.c	2014-11-14 03:29:49.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/kernel/syscall.c	2014-11-15 05:56:52.451903033 +0000
@@ -117,6 +117,7 @@ static inline int mips_atomic_set(unsign
 		"2:	sc	%[tmp], (%[addr])			\n"
 		"	beqzl	%[tmp], 1b				\n"
 		"3:							\n"
+		"	.insn						\n"
 		"	.section .fixup,\"ax\"				\n"
 		"4:	li	%[err], %[efault]			\n"
 		"	j	3b					\n"
@@ -142,6 +143,7 @@ static inline int mips_atomic_set(unsign
 		"2:	sc	%[tmp], (%[addr])			\n"
 		"	bnez	%[tmp], 4f				\n"
 		"3:							\n"
+		"	.insn						\n"
 		"	.subsection 2					\n"
 		"4:	b	1b					\n"
 		"	.previous					\n"

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 7/7] MIPS: atomic.h: Reformat to fit in 79 columns
@ 2014-11-15 22:09   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:09 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 No comment.  Please apply.

  Maciej

linux-mips-atomic-format.diff
Index: linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/atomic.h	2014-11-15 05:56:06.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h	2014-11-15 06:06:58.551778827 +0000
@@ -41,97 +41,97 @@
  */
 #define atomic_set(v, i)		((v)->counter = (i))
 
-#define ATOMIC_OP(op, c_op, asm_op)						\
-static __inline__ void atomic_##op(int i, atomic_t * v)				\
-{										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		int temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	ll	%0, %1		# atomic_" #op "	\n"	\
-		"	" #asm_op " %0, %2				\n"	\
-		"	sc	%0, %1					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		int temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%0, %1		# atomic_" #op "\n"	\
-			"	" #asm_op " %0, %2			\n"	\
-			"	sc	%0, %1				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
-			: "Ir" (i));						\
-		} while (unlikely(!temp));					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		v->counter c_op i;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-}										\
+#define ATOMIC_OP(op, c_op, asm_op)					      \
+static __inline__ void atomic_##op(int i, atomic_t * v)			      \
+{									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		int temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	ll	%0, %1		# atomic_" #op "	\n"   \
+		"	" #asm_op " %0, %2				\n"   \
+		"	sc	%0, %1					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		int temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	ll	%0, %1		# atomic_" #op "\n"   \
+			"	" #asm_op " %0, %2			\n"   \
+			"	sc	%0, %1				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "Ir" (i));					      \
+		} while (unlikely(!temp));				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		v->counter c_op i;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+}
 
-#define ATOMIC_OP_RETURN(op, c_op, asm_op)					\
-static __inline__ int atomic_##op##_return(int i, atomic_t * v)			\
-{										\
-	int result;								\
-										\
-	smp_mb__before_llsc();							\
-										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		int temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	ll	%1, %2		# atomic_" #op "_return	\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	sc	%0, %2					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp),					\
-		  "+" GCC_OFF12_ASM() (v->counter)				\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		int temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%1, %2	# atomic_" #op "_return	\n"	\
-			"	" #asm_op " %0, %1, %3			\n"	\
-			"	sc	%0, %2				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp),				\
-			  "+" GCC_OFF12_ASM() (v->counter)			\
-			: "Ir" (i));						\
-		} while (unlikely(!result));					\
-										\
-		result = temp; result c_op i;					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		result = v->counter;						\
-		result c_op i;							\
-		v->counter = result;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-										\
-	smp_llsc_mb();								\
-										\
-	return result;								\
+#define ATOMIC_OP_RETURN(op, c_op, asm_op)				      \
+static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
+{									      \
+	int result;							      \
+									      \
+	smp_mb__before_llsc();						      \
+									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		int temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	ll	%1, %2		# atomic_" #op "_return	\n"   \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	sc	%0, %2					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (result), "=&r" (temp),				      \
+		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		int temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	ll	%1, %2	# atomic_" #op "_return	\n"   \
+			"	" #asm_op " %0, %1, %3			\n"   \
+			"	sc	%0, %2				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (result), "=&r" (temp),			      \
+			  "+" GCC_OFF12_ASM() (v->counter)		      \
+			: "Ir" (i));					      \
+		} while (unlikely(!result));				      \
+									      \
+		result = temp; result c_op i;				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		result = v->counter;					      \
+		result c_op i;						      \
+		v->counter = result;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+									      \
+	smp_llsc_mb();							      \
+									      \
+	return result;							      \
 }
 
-#define ATOMIC_OPS(op, c_op, asm_op)						\
-	ATOMIC_OP(op, c_op, asm_op)						\
+#define ATOMIC_OPS(op, c_op, asm_op)					      \
+	ATOMIC_OP(op, c_op, asm_op)					      \
 	ATOMIC_OP_RETURN(op, c_op, asm_op)
 
 ATOMIC_OPS(add, +=, addu)
@@ -320,98 +320,98 @@ static __inline__ int __atomic_add_unles
  */
 #define atomic64_set(v, i)	((v)->counter = (i))
 
-#define ATOMIC64_OP(op, c_op, asm_op)						\
-static __inline__ void atomic64_##op(long i, atomic64_t * v)			\
-{										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		long temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	lld	%0, %1		# atomic64_" #op "	\n"	\
-		"	" #asm_op " %0, %2				\n"	\
-		"	scd	%0, %1					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		long temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%0, %1		# atomic64_" #op "\n"	\
-			"	" #asm_op " %0, %2			\n"	\
-			"	scd	%0, %1				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
-			: "Ir" (i));						\
-		} while (unlikely(!temp));					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		v->counter c_op i;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-}										\
+#define ATOMIC64_OP(op, c_op, asm_op)					      \
+static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
+{									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		long temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	lld	%0, %1		# atomic64_" #op "	\n"   \
+		"	" #asm_op " %0, %2				\n"   \
+		"	scd	%0, %1					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		long temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	lld	%0, %1		# atomic64_" #op "\n" \
+			"	" #asm_op " %0, %2			\n"   \
+			"	scd	%0, %1				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "Ir" (i));					      \
+		} while (unlikely(!temp));				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		v->counter c_op i;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+}
 
-#define ATOMIC64_OP_RETURN(op, c_op, asm_op)					\
-static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)		\
-{										\
-	long result;								\
-										\
-	smp_mb__before_llsc();							\
-										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		long temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	lld	%1, %2		# atomic64_" #op "_return\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	scd	%0, %2					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp),					\
-		  "+" GCC_OFF12_ASM() (v->counter)				\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		long temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%1, %2	# atomic64_" #op "_return\n"	\
-			"	" #asm_op " %0, %1, %3			\n"	\
-			"	scd	%0, %2				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp),				\
-			  "=" GCC_OFF12_ASM() (v->counter)			\
-			: "Ir" (i), GCC_OFF12_ASM() (v->counter)		\
-			: "memory");						\
-		} while (unlikely(!result));					\
-										\
-		result = temp; result c_op i;					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		result = v->counter;						\
-		result c_op i;							\
-		v->counter = result;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-										\
-	smp_llsc_mb();								\
-										\
-	return result;								\
+#define ATOMIC64_OP_RETURN(op, c_op, asm_op)				      \
+static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
+{									      \
+	long result;							      \
+									      \
+	smp_mb__before_llsc();						      \
+									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		long temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	lld	%1, %2		# atomic64_" #op "_return\n"  \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	scd	%0, %2					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (result), "=&r" (temp),				      \
+		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		long temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	lld	%1, %2	# atomic64_" #op "_return\n"  \
+			"	" #asm_op " %0, %1, %3			\n"   \
+			"	scd	%0, %2				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (result), "=&r" (temp),			      \
+			  "=" GCC_OFF12_ASM() (v->counter)		      \
+			: "Ir" (i), GCC_OFF12_ASM() (v->counter)	      \
+			: "memory");					      \
+		} while (unlikely(!result));				      \
+									      \
+		result = temp; result c_op i;				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		result = v->counter;					      \
+		result c_op i;						      \
+		v->counter = result;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+									      \
+	smp_llsc_mb();							      \
+									      \
+	return result;							      \
 }
 
-#define ATOMIC64_OPS(op, c_op, asm_op)						\
-	ATOMIC64_OP(op, c_op, asm_op)						\
+#define ATOMIC64_OPS(op, c_op, asm_op)					      \
+	ATOMIC64_OP(op, c_op, asm_op)					      \
 	ATOMIC64_OP_RETURN(op, c_op, asm_op)
 
 ATOMIC64_OPS(add, +=, daddu)
@@ -422,7 +422,8 @@ ATOMIC64_OPS(sub, -=, dsubu)
 #undef ATOMIC64_OP
 
 /*
- * atomic64_sub_if_positive - conditionally subtract integer from atomic variable
+ * atomic64_sub_if_positive - conditionally subtract integer from atomic
+ *                            variable
  * @i: integer value to subtract
  * @v: pointer of type atomic64_t
  *

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 7/7] MIPS: atomic.h: Reformat to fit in 79 columns
@ 2014-11-15 22:09   ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-15 22:09 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Hi,

 No comment.  Please apply.

  Maciej

linux-mips-atomic-format.diff
Index: linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h
===================================================================
--- linux-3.18-rc4-malta.orig/arch/mips/include/asm/atomic.h	2014-11-15 05:56:06.000000000 +0000
+++ linux-3.18-rc4-malta/arch/mips/include/asm/atomic.h	2014-11-15 06:06:58.551778827 +0000
@@ -41,97 +41,97 @@
  */
 #define atomic_set(v, i)		((v)->counter = (i))
 
-#define ATOMIC_OP(op, c_op, asm_op)						\
-static __inline__ void atomic_##op(int i, atomic_t * v)				\
-{										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		int temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	ll	%0, %1		# atomic_" #op "	\n"	\
-		"	" #asm_op " %0, %2				\n"	\
-		"	sc	%0, %1					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		int temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%0, %1		# atomic_" #op "\n"	\
-			"	" #asm_op " %0, %2			\n"	\
-			"	sc	%0, %1				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
-			: "Ir" (i));						\
-		} while (unlikely(!temp));					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		v->counter c_op i;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-}										\
+#define ATOMIC_OP(op, c_op, asm_op)					      \
+static __inline__ void atomic_##op(int i, atomic_t * v)			      \
+{									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		int temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	ll	%0, %1		# atomic_" #op "	\n"   \
+		"	" #asm_op " %0, %2				\n"   \
+		"	sc	%0, %1					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		int temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	ll	%0, %1		# atomic_" #op "\n"   \
+			"	" #asm_op " %0, %2			\n"   \
+			"	sc	%0, %1				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "Ir" (i));					      \
+		} while (unlikely(!temp));				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		v->counter c_op i;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+}
 
-#define ATOMIC_OP_RETURN(op, c_op, asm_op)					\
-static __inline__ int atomic_##op##_return(int i, atomic_t * v)			\
-{										\
-	int result;								\
-										\
-	smp_mb__before_llsc();							\
-										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		int temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	ll	%1, %2		# atomic_" #op "_return	\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	sc	%0, %2					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp),					\
-		  "+" GCC_OFF12_ASM() (v->counter)				\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		int temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	ll	%1, %2	# atomic_" #op "_return	\n"	\
-			"	" #asm_op " %0, %1, %3			\n"	\
-			"	sc	%0, %2				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp),				\
-			  "+" GCC_OFF12_ASM() (v->counter)			\
-			: "Ir" (i));						\
-		} while (unlikely(!result));					\
-										\
-		result = temp; result c_op i;					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		result = v->counter;						\
-		result c_op i;							\
-		v->counter = result;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-										\
-	smp_llsc_mb();								\
-										\
-	return result;								\
+#define ATOMIC_OP_RETURN(op, c_op, asm_op)				      \
+static __inline__ int atomic_##op##_return(int i, atomic_t * v)		      \
+{									      \
+	int result;							      \
+									      \
+	smp_mb__before_llsc();						      \
+									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		int temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	ll	%1, %2		# atomic_" #op "_return	\n"   \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	sc	%0, %2					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (result), "=&r" (temp),				      \
+		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		int temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	ll	%1, %2	# atomic_" #op "_return	\n"   \
+			"	" #asm_op " %0, %1, %3			\n"   \
+			"	sc	%0, %2				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (result), "=&r" (temp),			      \
+			  "+" GCC_OFF12_ASM() (v->counter)		      \
+			: "Ir" (i));					      \
+		} while (unlikely(!result));				      \
+									      \
+		result = temp; result c_op i;				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		result = v->counter;					      \
+		result c_op i;						      \
+		v->counter = result;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+									      \
+	smp_llsc_mb();							      \
+									      \
+	return result;							      \
 }
 
-#define ATOMIC_OPS(op, c_op, asm_op)						\
-	ATOMIC_OP(op, c_op, asm_op)						\
+#define ATOMIC_OPS(op, c_op, asm_op)					      \
+	ATOMIC_OP(op, c_op, asm_op)					      \
 	ATOMIC_OP_RETURN(op, c_op, asm_op)
 
 ATOMIC_OPS(add, +=, addu)
@@ -320,98 +320,98 @@ static __inline__ int __atomic_add_unles
  */
 #define atomic64_set(v, i)	((v)->counter = (i))
 
-#define ATOMIC64_OP(op, c_op, asm_op)						\
-static __inline__ void atomic64_##op(long i, atomic64_t * v)			\
-{										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		long temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	lld	%0, %1		# atomic64_" #op "	\n"	\
-		"	" #asm_op " %0, %2				\n"	\
-		"	scd	%0, %1					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)		\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		long temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%0, %1		# atomic64_" #op "\n"	\
-			"	" #asm_op " %0, %2			\n"	\
-			"	scd	%0, %1				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	\
-			: "Ir" (i));						\
-		} while (unlikely(!temp));					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		v->counter c_op i;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-}										\
+#define ATOMIC64_OP(op, c_op, asm_op)					      \
+static __inline__ void atomic64_##op(long i, atomic64_t * v)		      \
+{									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		long temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	lld	%0, %1		# atomic64_" #op "	\n"   \
+		"	" #asm_op " %0, %2				\n"   \
+		"	scd	%0, %1					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)	      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		long temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	lld	%0, %1		# atomic64_" #op "\n" \
+			"	" #asm_op " %0, %2			\n"   \
+			"	scd	%0, %1				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter)      \
+			: "Ir" (i));					      \
+		} while (unlikely(!temp));				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		v->counter c_op i;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+}
 
-#define ATOMIC64_OP_RETURN(op, c_op, asm_op)					\
-static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)		\
-{										\
-	long result;								\
-										\
-	smp_mb__before_llsc();							\
-										\
-	if (kernel_uses_llsc && R10000_LLSC_WAR) {				\
-		long temp;							\
-										\
-		__asm__ __volatile__(						\
-		"	.set	arch=r4000				\n"	\
-		"1:	lld	%1, %2		# atomic64_" #op "_return\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	scd	%0, %2					\n"	\
-		"	beqzl	%0, 1b					\n"	\
-		"	" #asm_op " %0, %1, %3				\n"	\
-		"	.set	mips0					\n"	\
-		: "=&r" (result), "=&r" (temp),					\
-		  "+" GCC_OFF12_ASM() (v->counter)				\
-		: "Ir" (i));							\
-	} else if (kernel_uses_llsc) {						\
-		long temp;							\
-										\
-		do {								\
-			__asm__ __volatile__(					\
-			"	.set	arch=r4000			\n"	\
-			"	lld	%1, %2	# atomic64_" #op "_return\n"	\
-			"	" #asm_op " %0, %1, %3			\n"	\
-			"	scd	%0, %2				\n"	\
-			"	.set	mips0				\n"	\
-			: "=&r" (result), "=&r" (temp),				\
-			  "=" GCC_OFF12_ASM() (v->counter)			\
-			: "Ir" (i), GCC_OFF12_ASM() (v->counter)		\
-			: "memory");						\
-		} while (unlikely(!result));					\
-										\
-		result = temp; result c_op i;					\
-	} else {								\
-		unsigned long flags;						\
-										\
-		raw_local_irq_save(flags);					\
-		result = v->counter;						\
-		result c_op i;							\
-		v->counter = result;						\
-		raw_local_irq_restore(flags);					\
-	}									\
-										\
-	smp_llsc_mb();								\
-										\
-	return result;								\
+#define ATOMIC64_OP_RETURN(op, c_op, asm_op)				      \
+static __inline__ long atomic64_##op##_return(long i, atomic64_t * v)	      \
+{									      \
+	long result;							      \
+									      \
+	smp_mb__before_llsc();						      \
+									      \
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {			      \
+		long temp;						      \
+									      \
+		__asm__ __volatile__(					      \
+		"	.set	arch=r4000				\n"   \
+		"1:	lld	%1, %2		# atomic64_" #op "_return\n"  \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	scd	%0, %2					\n"   \
+		"	beqzl	%0, 1b					\n"   \
+		"	" #asm_op " %0, %1, %3				\n"   \
+		"	.set	mips0					\n"   \
+		: "=&r" (result), "=&r" (temp),				      \
+		  "+" GCC_OFF12_ASM() (v->counter)			      \
+		: "Ir" (i));						      \
+	} else if (kernel_uses_llsc) {					      \
+		long temp;						      \
+									      \
+		do {							      \
+			__asm__ __volatile__(				      \
+			"	.set	arch=r4000			\n"   \
+			"	lld	%1, %2	# atomic64_" #op "_return\n"  \
+			"	" #asm_op " %0, %1, %3			\n"   \
+			"	scd	%0, %2				\n"   \
+			"	.set	mips0				\n"   \
+			: "=&r" (result), "=&r" (temp),			      \
+			  "=" GCC_OFF12_ASM() (v->counter)		      \
+			: "Ir" (i), GCC_OFF12_ASM() (v->counter)	      \
+			: "memory");					      \
+		} while (unlikely(!result));				      \
+									      \
+		result = temp; result c_op i;				      \
+	} else {							      \
+		unsigned long flags;					      \
+									      \
+		raw_local_irq_save(flags);				      \
+		result = v->counter;					      \
+		result c_op i;						      \
+		v->counter = result;					      \
+		raw_local_irq_restore(flags);				      \
+	}								      \
+									      \
+	smp_llsc_mb();							      \
+									      \
+	return result;							      \
 }
 
-#define ATOMIC64_OPS(op, c_op, asm_op)						\
-	ATOMIC64_OP(op, c_op, asm_op)						\
+#define ATOMIC64_OPS(op, c_op, asm_op)					      \
+	ATOMIC64_OP(op, c_op, asm_op)					      \
 	ATOMIC64_OP_RETURN(op, c_op, asm_op)
 
 ATOMIC64_OPS(add, +=, daddu)
@@ -422,7 +422,8 @@ ATOMIC64_OPS(sub, -=, dsubu)
 #undef ATOMIC64_OP
 
 /*
- * atomic64_sub_if_positive - conditionally subtract integer from atomic variable
+ * atomic64_sub_if_positive - conditionally subtract integer from atomic
+ *                            variable
  * @i: integer value to subtract
  * @v: pointer of type atomic64_t
  *

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/7] MIPS: Assorted microMIPS fixes
@ 2014-11-17 16:37   ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:37 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:06 PM, Maciej W. Rozycki wrote:
> Hi,
> 
>  In an attempt to build a kernel that supports microMIPS userland and 
> runs on QEMU I came across the problem that, due to apparently arbitrary 
> decisions made sometime in the past, there is no such combination 
> possible.
> 
>  I went ahead and fixed our configuration to support that, but in the 
> course of doing that I came across numerous problems that I decided to 
> address at the same time.  This mini patch series the result.  Most of 
> the changes are actually independent of one another, although there is a 
> syntactical overlap between 5/7 and 7/7, so these have to be applied in 
> order.
> 
>  Of course I had to draw a line somewhere so as not to get distracted 
> too much from the actual purpose I have the need to run such a 
> configuration, so I left some further bugs I spotted for the next 
> occasion.
> 
>  Ralf, please backport these fixes to stable branches as applicable; I 
> can supply you with a 3.17 equivalent of 5/7 as this piece has changed 
> significantly recently and I actually had to forward-port the original 
> change that I made to address the issue.
> 
>   Maciej
> 
Maciej,

This whole patchset looks really good. I went through all of them and
just made a few comments during review.

Steve


Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/7] MIPS: Assorted microMIPS fixes
@ 2014-11-17 16:37   ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:37 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:06 PM, Maciej W. Rozycki wrote:
> Hi,
> 
>  In an attempt to build a kernel that supports microMIPS userland and 
> runs on QEMU I came across the problem that, due to apparently arbitrary 
> decisions made sometime in the past, there is no such combination 
> possible.
> 
>  I went ahead and fixed our configuration to support that, but in the 
> course of doing that I came across numerous problems that I decided to 
> address at the same time.  This mini patch series the result.  Most of 
> the changes are actually independent of one another, although there is a 
> syntactical overlap between 5/7 and 7/7, so these have to be applied in 
> order.
> 
>  Of course I had to draw a line somewhere so as not to get distracted 
> too much from the actual purpose I have the need to run such a 
> configuration, so I left some further bugs I spotted for the next 
> occasion.
> 
>  Ralf, please backport these fixes to stable branches as applicable; I 
> can supply you with a 3.17 equivalent of 5/7 as this piece has changed 
> significantly recently and I actually had to forward-port the original 
> change that I made to address the issue.
> 
>   Maciej
> 
Maciej,

This whole patchset looks really good. I went through all of them and
just made a few comments during review.

Steve


Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] MIPS: Kconfig: Enable microMIPS support for Malta
@ 2014-11-17 16:38     ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:07 PM, Maciej W. Rozycki wrote:
> Add missing microMIPS support to Malta.  Currently the kernel only 
> enables support for the instruction set for the SEAD-3 board despite the 
> fact processor features have nothing to do with the board a processor is 
> installed in.
> 
For years there have been no microMIPS cores designed for the Malta
platform. Only now since you are trying to use microMIPS on QEMU is this
an issue. It was also the quick and dirty way to make sure microMIPS
kernels could not be used without changing the platform. Still, this is
certainly correct and I like it. Thanks.

Steve

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] MIPS: Kconfig: Enable microMIPS support for Malta
@ 2014-11-17 16:38     ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:07 PM, Maciej W. Rozycki wrote:
> Add missing microMIPS support to Malta.  Currently the kernel only 
> enables support for the instruction set for the SEAD-3 board despite the 
> fact processor features have nothing to do with the board a processor is 
> installed in.
> 
For years there have been no microMIPS cores designed for the Malta
platform. Only now since you are trying to use microMIPS on QEMU is this
an issue. It was also the quick and dirty way to make sure microMIPS
kernels could not be used without changing the platform. Still, this is
certainly correct and I like it. Thanks.

Steve

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 5/7] MIPS: Fix microMIPS LL/SC immediate offsets
@ 2014-11-17 16:38     ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:08 PM, Maciej W. Rozycki wrote:
> In the microMIPS encoding some memory access instructions have their 
> immediate offset reduced to 12 bits only.  That does not match the GCC 
> `R' constraint we use in some places to satisfy the requirement, 
> resulting in build failures like this:
> 
> {standard input}: Assembler messages:
> {standard input}:720: Error: macro used $at after ".set noat"
> {standard input}:720: Warning: macro instruction expanded into multiple instructions
> 
> Fix the problem by defining a macro, `GCC_OFF12_ASM', that expands to 
> the right constraint depending on whether microMIPS or standard MIPS 
> code is produced.  Also apply the fix to where `m' is used as in the 
> worst case this change does nothing, e.g. where the pointer was already 
> in a register such as a function argument and no further offset was 
> requested, and in the best case it avoids an extraneous sequence of up 
> to two instructions to load the high 20 bits of the address in the LL/SC 
> loop.  This reduces the risk of lock contention that is the higher the 
> more instructions there are in the critical section between LL and SC.
> 
> Strictly speaking we could just bulk-replace `R' with `ZC' as the latter 
> constraint adjusts automatically depending on the ISA selected.  
> However it was only introduced with GCC 4.9 and we keep supporing older 
> compilers for the standard MIPS configuration, hence the slightly more 
> complicated approach I chose.
> 
> The choice of a zero-argument function-like rather than an object-like 
> macro was made so that it does not look like a function call taking the 
> C expression used for the constraint as an argument.  This is so as not 
> to confuse the reader or formatting checkers like `checkpatch.pl' and 
> follows previous practice.
> 
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
> ---
> 
I am extremely pleased with this patch. We had discussed this problem
and various potential solutions a year or two ago, but I was never able
to find time to look at it again. Thanks for figuring this out.


Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 5/7] MIPS: Fix microMIPS LL/SC immediate offsets
@ 2014-11-17 16:38     ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:08 PM, Maciej W. Rozycki wrote:
> In the microMIPS encoding some memory access instructions have their 
> immediate offset reduced to 12 bits only.  That does not match the GCC 
> `R' constraint we use in some places to satisfy the requirement, 
> resulting in build failures like this:
> 
> {standard input}: Assembler messages:
> {standard input}:720: Error: macro used $at after ".set noat"
> {standard input}:720: Warning: macro instruction expanded into multiple instructions
> 
> Fix the problem by defining a macro, `GCC_OFF12_ASM', that expands to 
> the right constraint depending on whether microMIPS or standard MIPS 
> code is produced.  Also apply the fix to where `m' is used as in the 
> worst case this change does nothing, e.g. where the pointer was already 
> in a register such as a function argument and no further offset was 
> requested, and in the best case it avoids an extraneous sequence of up 
> to two instructions to load the high 20 bits of the address in the LL/SC 
> loop.  This reduces the risk of lock contention that is the higher the 
> more instructions there are in the critical section between LL and SC.
> 
> Strictly speaking we could just bulk-replace `R' with `ZC' as the latter 
> constraint adjusts automatically depending on the ISA selected.  
> However it was only introduced with GCC 4.9 and we keep supporing older 
> compilers for the standard MIPS configuration, hence the slightly more 
> complicated approach I chose.
> 
> The choice of a zero-argument function-like rather than an object-like 
> macro was made so that it does not look like a function call taking the 
> C expression used for the constraint as an argument.  This is so as not 
> to confuse the reader or formatting checkers like `checkpatch.pl' and 
> follows previous practice.
> 
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
> ---
> 
I am extremely pleased with this patch. We had discussed this problem
and various potential solutions a year or two ago, but I was never able
to find time to look at it again. Thanks for figuring this out.


Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout
@ 2014-11-17 16:38     ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:09 PM, Maciej W. Rozycki wrote:
> Fix the issue with the ISA bit being lost in fixups that jump to
> labels placed just before a section switch.  Such a switch leads to
> the ISA bit being lost, because GAS concludes there is no code that
> follows and therefore the label refers to data.  Use the `.insn'
> pseudo-op to convince the tool this is not the case.
> 
> This lack of label annotation leads to microMIPS compilation errors 
> like:
> 
> mips-linux-gnu-ld: arch/mips/built-in.o: .fixup+0x3b8: Unsupported
> jump between ISA modes; consider recompiling with interlinking
> enabled. mips-linux-gnu-ld: final link failed: Bad value
> 
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com> --- Hi,
> 
> I see someone has just fixed this issue in one place, so I had to 
> regenerate the change I originally made against 3.17, but I really
> fail to see why not to fix it throughout at once.
> 
In our earlier branches I believe all of the '.insn' pseudo-ops were in
place. I remember removing a number of them during release testing since
they appeared to not make any difference. It appears that use of
different toolchains has shown that to be in error.

Steve


Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout
@ 2014-11-17 16:38     ` Steven J. Hill
  0 siblings, 0 replies; 26+ messages in thread
From: Steven J. Hill @ 2014-11-17 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On 11/15/2014 04:09 PM, Maciej W. Rozycki wrote:
> Fix the issue with the ISA bit being lost in fixups that jump to
> labels placed just before a section switch.  Such a switch leads to
> the ISA bit being lost, because GAS concludes there is no code that
> follows and therefore the label refers to data.  Use the `.insn'
> pseudo-op to convince the tool this is not the case.
> 
> This lack of label annotation leads to microMIPS compilation errors 
> like:
> 
> mips-linux-gnu-ld: arch/mips/built-in.o: .fixup+0x3b8: Unsupported
> jump between ISA modes; consider recompiling with interlinking
> enabled. mips-linux-gnu-ld: final link failed: Bad value
> 
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com> --- Hi,
> 
> I see someone has just fixed this issue in one place, so I had to 
> regenerate the change I originally made against 3.17, but I really
> fail to see why not to fix it throughout at once.
> 
In our earlier branches I believe all of the '.insn' pseudo-ops were in
place. I remember removing a number of them during release testing since
they appeared to not make any difference. It appears that use of
different toolchains has shown that to be in error.

Steve


Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout
@ 2014-11-17 16:57       ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-17 16:57 UTC (permalink / raw)
  To: Steven J. Hill; +Cc: linux-mips

On Mon, 17 Nov 2014, Steven J. Hill wrote:

> > I see someone has just fixed this issue in one place, so I had to 
> > regenerate the change I originally made against 3.17, but I really
> > fail to see why not to fix it throughout at once.
> > 
> In our earlier branches I believe all of the '.insn' pseudo-ops were in
> place. I remember removing a number of them during release testing since
> they appeared to not make any difference. It appears that use of
> different toolchains has shown that to be in error.

 Well, people keep adding code so these fixups may well have not been 
there previously.  And not all source code is compiled in all 
configurations so if you rely on build-time checking then you may well 
miss a bit here or there.  The best way at the moment is to scan through 
all code or watch as people push changes and react.

 It would be better if we had a way to handle it automatically, or maybe 
even better yet if GAS did not lose the ISA bit on a label when there is 
a temporary section switch between the label and the following 
instruction.  As much as I'd like doing this changing GAS to be able to 
carry the ISA bit across a section switch is non-trivial though, it 
would be a major effort to implement it, so at least for the time being 
we have to live with what we have now.

 Thanks for your review.

  Maciej

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout
@ 2014-11-17 16:57       ` Maciej W. Rozycki
  0 siblings, 0 replies; 26+ messages in thread
From: Maciej W. Rozycki @ 2014-11-17 16:57 UTC (permalink / raw)
  To: Steven J. Hill; +Cc: linux-mips

On Mon, 17 Nov 2014, Steven J. Hill wrote:

> > I see someone has just fixed this issue in one place, so I had to 
> > regenerate the change I originally made against 3.17, but I really
> > fail to see why not to fix it throughout at once.
> > 
> In our earlier branches I believe all of the '.insn' pseudo-ops were in
> place. I remember removing a number of them during release testing since
> they appeared to not make any difference. It appears that use of
> different toolchains has shown that to be in error.

 Well, people keep adding code so these fixups may well have not been 
there previously.  And not all source code is compiled in all 
configurations so if you rely on build-time checking then you may well 
miss a bit here or there.  The best way at the moment is to scan through 
all code or watch as people push changes and react.

 It would be better if we had a way to handle it automatically, or maybe 
even better yet if GAS did not lose the ISA bit on a label when there is 
a temporary section switch between the label and the following 
instruction.  As much as I'd like doing this changing GAS to be able to 
carry the ISA bit across a section switch is non-trivial though, it 
would be a major effort to implement it, so at least for the time being 
we have to live with what we have now.

 Thanks for your review.

  Maciej

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2014-11-17 16:58 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-15 22:06 [PATCH 0/7] MIPS: Assorted microMIPS fixes Maciej W. Rozycki
2014-11-15 22:06 ` Maciej W. Rozycki
2014-11-15 22:07 ` [PATCH 1/7] MIPS: Kconfig: Enable microMIPS support for Malta Maciej W. Rozycki
2014-11-15 22:07   ` Maciej W. Rozycki
2014-11-17 16:38   ` Steven J. Hill
2014-11-17 16:38     ` Steven J. Hill
2014-11-15 22:07 ` [PATCH 2/7] MIPS: mm: Only build one microassembler that is suitable Maciej W. Rozycki
2014-11-15 22:07   ` Maciej W. Rozycki
2014-11-15 22:08 ` [PATCH 3/7] MIPS: signal.c: Fix an invalid cast in ISA mode bit handling Maciej W. Rozycki
2014-11-15 22:08   ` Maciej W. Rozycki
2014-11-15 22:08 ` [PATCH 4/7] MIPS: Kconfig: Only allow 32-bit microMIPS builds Maciej W. Rozycki
2014-11-15 22:08   ` Maciej W. Rozycki
2014-11-15 22:08 ` [PATCH 5/7] MIPS: Fix microMIPS LL/SC immediate offsets Maciej W. Rozycki
2014-11-15 22:08   ` Maciej W. Rozycki
2014-11-17 16:38   ` Steven J. Hill
2014-11-17 16:38     ` Steven J. Hill
2014-11-15 22:09 ` [PATCH 6/7] MIPS: Apply `.insn' to fixup labels throughout Maciej W. Rozycki
2014-11-15 22:09   ` Maciej W. Rozycki
2014-11-17 16:38   ` Steven J. Hill
2014-11-17 16:38     ` Steven J. Hill
2014-11-17 16:57     ` Maciej W. Rozycki
2014-11-17 16:57       ` Maciej W. Rozycki
2014-11-15 22:09 ` [PATCH 7/7] MIPS: atomic.h: Reformat to fit in 79 columns Maciej W. Rozycki
2014-11-15 22:09   ` Maciej W. Rozycki
2014-11-17 16:37 ` [PATCH 0/7] MIPS: Assorted microMIPS fixes Steven J. Hill
2014-11-17 16:37   ` Steven J. Hill

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.