diff options
| author | Maciej W. Rozycki <macro@linux-mips.org> | 2015-05-28 12:46:49 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2015-05-29 14:23:58 -0400 |
| commit | c4fca4fdea940bda2cff6b844cda6af8ef1c79cc (patch) | |
| tree | f66a7522cade4d4a883f4597b29f00dd258cdf7a | |
| parent | 57b41758230b567218cb5bc3da9068aabc496fc9 (diff) | |
MIPS: strnlen_user.S: Fix a CPU_DADDI_WORKAROUNDS regression
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@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/10205/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/lib/strnlen_user.S | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S index 7d12c0dded3d..77e64942f004 100644 --- a/arch/mips/lib/strnlen_user.S +++ b/arch/mips/lib/strnlen_user.S | |||
| @@ -34,7 +34,12 @@ LEAF(__strnlen_\func\()_asm) | |||
| 34 | FEXPORT(__strnlen_\func\()_nocheck_asm) | 34 | FEXPORT(__strnlen_\func\()_nocheck_asm) |
| 35 | move v0, a0 | 35 | move v0, a0 |
| 36 | PTR_ADDU a1, a0 # stop pointer | 36 | PTR_ADDU a1, a0 # stop pointer |
| 37 | 1: beq v0, a1, 1f # limit reached? | 37 | 1: |
| 38 | #ifdef CONFIG_CPU_DADDI_WORKAROUNDS | ||
| 39 | .set noat | ||
| 40 | li AT, 1 | ||
| 41 | #endif | ||
| 42 | beq v0, a1, 1f # limit reached? | ||
| 38 | .ifeqs "\func", "kernel" | 43 | .ifeqs "\func", "kernel" |
| 39 | EX(lb, t0, (v0), .Lfault\@) | 44 | EX(lb, t0, (v0), .Lfault\@) |
| 40 | .else | 45 | .else |
| @@ -42,7 +47,13 @@ FEXPORT(__strnlen_\func\()_nocheck_asm) | |||
| 42 | .endif | 47 | .endif |
| 43 | .set noreorder | 48 | .set noreorder |
| 44 | bnez t0, 1b | 49 | bnez t0, 1b |
| 45 | 1: PTR_ADDIU v0, 1 | 50 | 1: |
| 51 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
| 52 | PTR_ADDIU v0, 1 | ||
| 53 | #else | ||
| 54 | PTR_ADDU v0, AT | ||
| 55 | .set at | ||
| 56 | #endif | ||
| 46 | .set reorder | 57 | .set reorder |
| 47 | PTR_SUBU v0, a0 | 58 | PTR_SUBU v0, a0 |
| 48 | jr ra | 59 | jr ra |
