* [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
* 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
* [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
* 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
* [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
* 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
* [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
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.