From 08eeb44b2466feb1cf98fb0e8e6a1cf932ece6df Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 6 Aug 2018 18:29:51 -0700 Subject: [PATCH] MIPS: Use read-write output operand in __write_64bit_c0_split() Commit c22c80431055 ("MIPS: Fix input modify in __write_64bit_c0_split()") modified __write_64bit_c0_split() constraints such that we have both an input & an output which we hope to assign to the same registers, and modify the output rather than incorrectly clobbering an input. The way in which we use both an output & an input parameter with the input constrained to share the output registers is a little convoluted & also problematic for clang, which complains if the input & output values have different widths. For example: 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)); \ ^~~ We can both fix this build failure & simplify the code somewhat by assigning the __tmp variable with the input value in C prior to our inline assembly, and then using a single read-write output operand (ie. a constraint beginning with +) to provide this value to our assembly. Signed-off-by: Paul Burton --- arch/mips/include/asm/mipsregs.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index b6237ffbacf5..dd46ab2a4ffd 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1485,32 +1485,30 @@ do { \ #define __write_64bit_c0_split(source, sel, val) \ do { \ - unsigned long long __tmp; \ + unsigned long long __tmp = (val); \ unsigned long __flags; \ \ local_irq_save(__flags); \ if (sel == 0) \ __asm__ __volatile__( \ ".set\tmips64\n\t" \ - "dsll\t%L0, %L1, 32\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ "dsrl\t%L0, %L0, 32\n\t" \ - "dsll\t%M0, %M1, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ "or\t%L0, %L0, %M0\n\t" \ "dmtc0\t%L0, " #source "\n\t" \ ".set\tmips0" \ - : "=&r,r" (__tmp) \ - : "r,0" (val)); \ + : "+r" (__tmp)); \ else \ __asm__ __volatile__( \ ".set\tmips64\n\t" \ - "dsll\t%L0, %L1, 32\n\t" \ + "dsll\t%L0, %L0, 32\n\t" \ "dsrl\t%L0, %L0, 32\n\t" \ - "dsll\t%M0, %M1, 32\n\t" \ + "dsll\t%M0, %M0, 32\n\t" \ "or\t%L0, %L0, %M0\n\t" \ "dmtc0\t%L0, " #source ", " #sel "\n\t" \ ".set\tmips0" \ - : "=&r,r" (__tmp) \ - : "r,0" (val)); \ + : "+r" (__tmp)); \ local_irq_restore(__flags); \ } while (0)