[PATCH] MIPS: strnlen_user.S: Fix a CPU_DADDI_WORKAROUNDS regression

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

 



Correct a regression introduced with 8453eebd [MIPS: Fix strnlen_user() 
return value in case of overlong strings.] causing assembler warnings 
and broken code generated in __strnlen_kernel_nocheck_asm:

arch/mips/lib/strnlen_user.S: Assembler messages:
arch/mips/lib/strnlen_user.S:64: Warning: Macro instruction expanded into multiple instructions in a branch delay slot

with the CPU_DADDI_WORKAROUNDS option set, resulting in the function 
looping indefinitely upon mounting NFS root.

Use conditional assembly to avoid a microMIPS code size regression.  
Using $at unconditionally would cause such a regression as there are no 
16-bit instruction encodings available for ALU operations using this 
register.  Using $v1 unconditionally would produce short microMIPS 
encodings, but would prevent this register from being used across calls 
to this function.

The extra LI operation introduced is free, replacing a NOP originally 
scheduled into the delay slot of the branch that follows.

Signed-off-by: Maciej W. Rozycki <macro@xxxxxxxxxxxxxx>
---
Ralf,

 The jump to the delay slot combined with the unusual register usage 
convention taken here made it trickier than it would normally be to make a 
fix that does not regress -- in terms of code size -- unaffected microMIPS 
systems.  I tried several versions and eventually I came up with this one 
that I believe produces the best code in all cases, at the cost of these 
#ifdefs.  I hope they are acceptable.

 Please apply,

  Maciej

linux-mips-strnlen-user-nodaddi-fix.patch
Index: linux-20150524-4maxp64/arch/mips/lib/strnlen_user.S
===================================================================
--- linux-20150524-4maxp64.orig/arch/mips/lib/strnlen_user.S
+++ linux-20150524-4maxp64/arch/mips/lib/strnlen_user.S
@@ -34,7 +34,12 @@ LEAF(__strnlen_\func\()_asm)
 FEXPORT(__strnlen_\func\()_nocheck_asm)
 	move		v0, a0
 	PTR_ADDU	a1, a0			# stop pointer
-1:	beq		v0, a1, 1f		# limit reached?
+1:
+#ifdef CONFIG_CPU_DADDI_WORKAROUNDS
+	.set		noat
+	li		AT, 1
+#endif
+	beq		v0, a1, 1f		# limit reached?
 .ifeqs "\func", "kernel"
 	EX(lb, t0, (v0), .Lfault\@)
 .else
@@ -42,7 +47,13 @@ FEXPORT(__strnlen_\func\()_nocheck_asm)
 .endif
 	.set		noreorder
 	bnez		t0, 1b
-1:	 PTR_ADDIU	v0, 1
+1:
+#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
+	 PTR_ADDIU	v0, 1
+#else
+	 PTR_ADDU	v0, AT
+	.set		at
+#endif
 	.set		reorder
 	PTR_SUBU	v0, a0
 	jr		ra





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

  Powered by Linux