[PATCH 2/3] MIPS: Fix __write_64bit_c0_split() constraints for clang

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When building using clang, the constraints for unreachable inline
assembly seem to be checked. A result of this is that a CONFIG_32BIT=y
build using clang will result in the constraints for inline assembly in
__write_64bit_c0_split() being checked even when the caller ultimately
used __write_ulong_c0_register() & the 64-bit path will never be taken.

This results in build failures like the following:

  In file included from kernel/fork.c:98:
  ./arch/mips/include/asm/mmu_context.h:149:19: error: unsupported
    inline asm: input with type 'unsigned long' matching output with
    type 'unsigned long long'
          write_c0_entryhi(cpu_asid(cpu, next));
          ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
  ./arch/mips/include/asm/mmu_context.h:93:2: note: expanded from macro
    'cpu_asid'
          (cpu_context((cpu), (mm)) & cpu_asid_mask(&cpu_data[cpu]))
          ^
  ./arch/mips/include/asm/mipsregs.h:1617:65: note: expanded from macro
    'write_c0_entryhi'
  #define write_c0_entryhi(val)   __write_ulong_c0_register($10, 0, val)
                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
  ./arch/mips/include/asm/mipsregs.h:1430:39: note: expanded from macro
    '__write_ulong_c0_register'
                  __write_64bit_c0_register(reg, sel, val);               \
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
  ./arch/mips/include/asm/mipsregs.h:1400:41: note: expanded from macro
    '__write_64bit_c0_register'
                  __write_64bit_c0_split(register, sel, value);           \
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
  ./arch/mips/include/asm/mipsregs.h:1498:13: note: expanded from macro
    '__write_64bit_c0_split'
                          : "r,0" (val));                                 \
                                   ^~~

This occurs because __write_64bit_c0_split() declares an unsigned long
long (ie. 64-bit) __tmp variable for use as an output from the inline
assembly, and then attempts to constrain its input to make use of the
same registers without caring whether the input is actually of the same
width.

Avoid the build failure by simply casting the input value to the same
unsigned long long type as the output which we want to use the same
registers as.

On a CONFIG_32BIT=y build this means that for users of
__write_ulong_c0_register() we would zero-extend the input value from
32-bit to 64-bit if the path were ever taken, but we know it never will
be. For a CONFIG_64BIT=y build the caller should be providing a 64-bit
value already causing our cast to be a no-op.

Signed-off-by: Paul Burton <paul.burton@xxxxxxxx>
Cc: James Hogan <jhogan@xxxxxxxxxx>
Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx>
Cc: linux-mips@xxxxxxxxxxxxxx
---

 arch/mips/include/asm/mipsregs.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index ae461d91cd1f..d8213dca2ab4 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1495,7 +1495,7 @@ do {									\
 			"dmtc0\t%L0, " #source "\n\t"			\
 			".set\tmips0"					\
 			: "=&r,r" (__tmp)				\
-			: "r,0" (val));					\
+			: "r,0" ((unsigned long long)val));		\
 	else								\
 		__asm__ __volatile__(					\
 			".set\tmips64\n\t"				\
@@ -1506,7 +1506,7 @@ do {									\
 			"dmtc0\t%L0, " #source ", " #sel "\n\t"		\
 			".set\tmips0"					\
 			: "=&r,r" (__tmp)				\
-			: "r,0" (val));					\
+			: "r,0" ((unsigned long long)val));		\
 	local_irq_restore(__flags);					\
 } while (0)
 
-- 
2.18.0





[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux