summaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2016-10-17 10:34:35 -0400
committerRalf Baechle <ralf@linux-mips.org>2017-01-03 10:34:41 -0500
commite11124d8ffcdf893d64e0b29624fd88e0ae4ceac (patch)
tree7698f9e5e76fd685a8548ba807a6be07592475a7 /arch/mips
parentdaa10170da271ed82b34c39a5f10f993569eec79 (diff)
MIPS: Remove r2_emul_return from struct thread_info
The r2_emul_return field in struct thread_info was used in order to take an alternate codepath when returning to userland, which (besides not implementing certain features) effectively used the eretnc instruction in place of eret. The difference is that eretnc doesn't clear LLBit, and therefore doesn't cause a linked load & store sequence to fail due to emulation like eret would. The reason eret would usually be used to clear LLBit is so that after context switching we ensure that a load performed by one task doesn't influence another task. However commit 7c151d3d5d7a ("MIPS: Make use of the ERETNC instruction on MIPS R6") which introduced the r2_emul_return field and conditional use of eretnc also for some reason began explicitly clearing LLBit during context switches - despite retaining the use of eret for everything but returns from the pre-r6 instruction emulation code. As LLBit is cleared upon context switches anyway, simplify this by using eretnc unconditionally for MIPSr6 kernels. This allows us to remove the 4 byte r2_emul_return boolean from struct thread_info, simplify the return to user code in entry.S and avoid the overhead of tracking & checking state which we don't need. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14408/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/include/asm/stackframe.h4
-rw-r--r--arch/mips/include/asm/thread_info.h1
-rw-r--r--arch/mips/kernel/asm-offsets.c1
-rw-r--r--arch/mips/kernel/entry.S18
-rw-r--r--arch/mips/kernel/traps.c2
5 files changed, 4 insertions, 22 deletions
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 2f182bdf024f..6c74a804fe98 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -364,9 +364,13 @@
364 364
365 .macro RESTORE_SP_AND_RET 365 .macro RESTORE_SP_AND_RET
366 LONG_L sp, PT_R29(sp) 366 LONG_L sp, PT_R29(sp)
367#ifdef CONFIG_CPU_MIPSR6
368 eretnc
369#else
367 .set arch=r4000 370 .set arch=r4000
368 eret 371 eret
369 .set mips0 372 .set mips0
373#endif
370 .endm 374 .endm
371 375
372#endif 376#endif
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index e309d8fcb516..b439e512792b 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -27,7 +27,6 @@ struct thread_info {
27 unsigned long tp_value; /* thread pointer */ 27 unsigned long tp_value; /* thread pointer */
28 __u32 cpu; /* current CPU */ 28 __u32 cpu; /* current CPU */
29 int preempt_count; /* 0 => preemptable, <0 => BUG */ 29 int preempt_count; /* 0 => preemptable, <0 => BUG */
30 int r2_emul_return; /* 1 => Returning from R2 emulator */
31 mm_segment_t addr_limit; /* 30 mm_segment_t addr_limit; /*
32 * thread address space limit: 31 * thread address space limit:
33 * 0x7fffffff for user-thead 32 * 0x7fffffff for user-thead
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index a7277698d328..bb5c5d34ba81 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -97,7 +97,6 @@ void output_thread_info_defines(void)
97 OFFSET(TI_TP_VALUE, thread_info, tp_value); 97 OFFSET(TI_TP_VALUE, thread_info, tp_value);
98 OFFSET(TI_CPU, thread_info, cpu); 98 OFFSET(TI_CPU, thread_info, cpu);
99 OFFSET(TI_PRE_COUNT, thread_info, preempt_count); 99 OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
100 OFFSET(TI_R2_EMUL_RET, thread_info, r2_emul_return);
101 OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit); 100 OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
102 OFFSET(TI_REGS, thread_info, regs); 101 OFFSET(TI_REGS, thread_info, regs);
103 DEFINE(_THREAD_SIZE, THREAD_SIZE); 102 DEFINE(_THREAD_SIZE, THREAD_SIZE);
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 7791840cf22c..8d83fc2a96b7 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -47,11 +47,6 @@ resume_userspace:
47 local_irq_disable # make sure we dont miss an 47 local_irq_disable # make sure we dont miss an
48 # interrupt setting need_resched 48 # interrupt setting need_resched
49 # between sampling and return 49 # between sampling and return
50#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
51 lw k0, TI_R2_EMUL_RET($28)
52 bnez k0, restore_all_from_r2_emul
53#endif
54
55 LONG_L a2, TI_FLAGS($28) # current->work 50 LONG_L a2, TI_FLAGS($28) # current->work
56 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) 51 andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace)
57 bnez t0, work_pending 52 bnez t0, work_pending
@@ -120,19 +115,6 @@ restore_partial: # restore partial frame
120 RESTORE_SP_AND_RET 115 RESTORE_SP_AND_RET
121 .set at 116 .set at
122 117
123#ifdef CONFIG_MIPSR2_TO_R6_EMULATOR
124restore_all_from_r2_emul: # restore full frame
125 .set noat
126 sw zero, TI_R2_EMUL_RET($28) # reset it
127 RESTORE_TEMP
128 RESTORE_AT
129 RESTORE_STATIC
130 RESTORE_SOME
131 LONG_L sp, PT_R29(sp)
132 eretnc
133 .set at
134#endif
135
136work_pending: 118work_pending:
137 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS 119 andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
138 beqz t0, work_notifysig 120 beqz t0, work_notifysig
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 9ea6959cd5bb..cb479be31a50 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1108,7 +1108,6 @@ asmlinkage void do_ri(struct pt_regs *regs)
1108 switch (status) { 1108 switch (status) {
1109 case 0: 1109 case 0:
1110 case SIGEMT: 1110 case SIGEMT:
1111 task_thread_info(current)->r2_emul_return = 1;
1112 return; 1111 return;
1113 case SIGILL: 1112 case SIGILL:
1114 goto no_r2_instr; 1113 goto no_r2_instr;
@@ -1116,7 +1115,6 @@ asmlinkage void do_ri(struct pt_regs *regs)
1116 process_fpemu_return(status, 1115 process_fpemu_return(status,
1117 &current->thread.cp0_baduaddr, 1116 &current->thread.cp0_baduaddr,
1118 fcr31); 1117 fcr31);
1119 task_thread_info(current)->r2_emul_return = 1;
1120 return; 1118 return;
1121 } 1119 }
1122 } 1120 }