diff options
author | Paul Burton <paul.burton@imgtec.com> | 2016-10-17 17:34:36 +0300 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2017-01-03 18:34:42 +0300 |
commit | 3b4b82399c4557666d348bed1aefc21c999e79a1 (patch) | |
tree | a046c6b1a4f1e7232d3518dcd3d2623ec7d4d1c4 | |
parent | e11124d8ffcdf893d64e0b29624fd88e0ae4ceac (diff) | |
download | linux-3b4b82399c4557666d348bed1aefc21c999e79a1.tar.xz |
MIPS: Cleanup LLBit handling in switch_to
Commit 7c151d3d5d7a ("MIPS: Make use of the ERETNC instruction on MIPS
R6") began clearing LLBit during context switches, but did so on all
systems where it is writable for unclear reasons & did so from a macro
with "software_ll_bit" in its name, which is intended to operate on the
ll_bit variable used by ll/sc emulation for old CPUs.
We do now need to clear LLBit on MIPSr6 systems where we'll use eretnc
to return to userland, but we don't need to do so on MIPSr5 systems with
a writable LLBit.
Move the clear to its own appropriately named macro, do it only for
MIPSr6 systems & comment about why.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/14409/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/switch_to.h | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index c0ae27971e31..e610473d61b8 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -66,13 +66,18 @@ do { \ #define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0) #endif -#define __clear_software_ll_bit() \ -do { if (cpu_has_rw_llb) { \ +/* + * Clear LLBit during context switches on MIPSr6 such that eretnc can be used + * unconditionally when returning to userland in entry.S. + */ +#define __clear_r6_hw_ll_bit() do { \ + if (cpu_has_mips_r6) \ write_c0_lladdr(0); \ - } else { \ - if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc)\ - ll_bit = 0; \ - } \ +} while (0) + +#define __clear_software_ll_bit() do { \ + if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc) \ + ll_bit = 0; \ } while (0) /* @@ -120,6 +125,7 @@ do { \ } \ clear_c0_status(ST0_CU2); \ } \ + __clear_r6_hw_ll_bit(); \ __clear_software_ll_bit(); \ if (cpu_has_userlocal) \ write_c0_userlocal(task_thread_info(next)->tp_value); \ |