aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r--arch/mips/kernel/signal.c79
1 files changed, 8 insertions, 71 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 33133d3df3e5..9e60d117e41e 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -31,7 +31,6 @@
31#include <linux/bitops.h> 31#include <linux/bitops.h>
32#include <asm/cacheflush.h> 32#include <asm/cacheflush.h>
33#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/msa.h>
35#include <asm/sim.h> 34#include <asm/sim.h>
36#include <asm/ucontext.h> 35#include <asm/ucontext.h>
37#include <asm/cpu-features.h> 36#include <asm/cpu-features.h>
@@ -48,9 +47,6 @@ static int (*restore_fp_context)(struct sigcontext __user *sc);
48extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); 47extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
49extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); 48extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
50 49
51extern asmlinkage int _save_msa_context(struct sigcontext __user *sc);
52extern asmlinkage int _restore_msa_context(struct sigcontext __user *sc);
53
54struct sigframe { 50struct sigframe {
55 u32 sf_ass[4]; /* argument save space for o32 */ 51 u32 sf_ass[4]; /* argument save space for o32 */
56 u32 sf_pad[2]; /* Was: signal trampoline */ 52 u32 sf_pad[2]; /* Was: signal trampoline */
@@ -100,60 +96,20 @@ static int copy_fp_from_sigcontext(struct sigcontext __user *sc)
100} 96}
101 97
102/* 98/*
103 * These functions will save only the upper 64 bits of the vector registers,
104 * since the lower 64 bits have already been saved as the scalar FP context.
105 */
106static int copy_msa_to_sigcontext(struct sigcontext __user *sc)
107{
108 int i;
109 int err = 0;
110
111 for (i = 0; i < NUM_FPU_REGS; i++) {
112 err |=
113 __put_user(get_fpr64(&current->thread.fpu.fpr[i], 1),
114 &sc->sc_msaregs[i]);
115 }
116 err |= __put_user(current->thread.fpu.msacsr, &sc->sc_msa_csr);
117
118 return err;
119}
120
121static int copy_msa_from_sigcontext(struct sigcontext __user *sc)
122{
123 int i;
124 int err = 0;
125 u64 val;
126
127 for (i = 0; i < NUM_FPU_REGS; i++) {
128 err |= __get_user(val, &sc->sc_msaregs[i]);
129 set_fpr64(&current->thread.fpu.fpr[i], 1, val);
130 }
131 err |= __get_user(current->thread.fpu.msacsr, &sc->sc_msa_csr);
132
133 return err;
134}
135
136/*
137 * Helper routines 99 * Helper routines
138 */ 100 */
139static int protected_save_fp_context(struct sigcontext __user *sc, 101static int protected_save_fp_context(struct sigcontext __user *sc)
140 unsigned used_math)
141{ 102{
142 int err; 103 int err;
143 bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
144#ifndef CONFIG_EVA 104#ifndef CONFIG_EVA
145 while (1) { 105 while (1) {
146 lock_fpu_owner(); 106 lock_fpu_owner();
147 if (is_fpu_owner()) { 107 if (is_fpu_owner()) {
148 err = save_fp_context(sc); 108 err = save_fp_context(sc);
149 if (save_msa && !err)
150 err = _save_msa_context(sc);
151 unlock_fpu_owner(); 109 unlock_fpu_owner();
152 } else { 110 } else {
153 unlock_fpu_owner(); 111 unlock_fpu_owner();
154 err = copy_fp_to_sigcontext(sc); 112 err = copy_fp_to_sigcontext(sc);
155 if (save_msa && !err)
156 err = copy_msa_to_sigcontext(sc);
157 } 113 }
158 if (likely(!err)) 114 if (likely(!err))
159 break; 115 break;
@@ -169,38 +125,24 @@ static int protected_save_fp_context(struct sigcontext __user *sc,
169 * EVA does not have FPU EVA instructions so saving fpu context directly 125 * EVA does not have FPU EVA instructions so saving fpu context directly
170 * does not work. 126 * does not work.
171 */ 127 */
172 disable_msa();
173 lose_fpu(1); 128 lose_fpu(1);
174 err = save_fp_context(sc); /* this might fail */ 129 err = save_fp_context(sc); /* this might fail */
175 if (save_msa && !err)
176 err = copy_msa_to_sigcontext(sc);
177#endif 130#endif
178 return err; 131 return err;
179} 132}
180 133
181static int protected_restore_fp_context(struct sigcontext __user *sc, 134static int protected_restore_fp_context(struct sigcontext __user *sc)
182 unsigned used_math)
183{ 135{
184 int err, tmp __maybe_unused; 136 int err, tmp __maybe_unused;
185 bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
186#ifndef CONFIG_EVA 137#ifndef CONFIG_EVA
187 while (1) { 138 while (1) {
188 lock_fpu_owner(); 139 lock_fpu_owner();
189 if (is_fpu_owner()) { 140 if (is_fpu_owner()) {
190 err = restore_fp_context(sc); 141 err = restore_fp_context(sc);
191 if (restore_msa && !err) {
192 enable_msa();
193 err = _restore_msa_context(sc);
194 } else {
195 /* signal handler may have used MSA */
196 disable_msa();
197 }
198 unlock_fpu_owner(); 142 unlock_fpu_owner();
199 } else { 143 } else {
200 unlock_fpu_owner(); 144 unlock_fpu_owner();
201 err = copy_fp_from_sigcontext(sc); 145 err = copy_fp_from_sigcontext(sc);
202 if (!err && (used_math & USEDMATH_MSA))
203 err = copy_msa_from_sigcontext(sc);
204 } 146 }
205 if (likely(!err)) 147 if (likely(!err))
206 break; 148 break;
@@ -216,11 +158,8 @@ static int protected_restore_fp_context(struct sigcontext __user *sc,
216 * EVA does not have FPU EVA instructions so restoring fpu context 158 * EVA does not have FPU EVA instructions so restoring fpu context
217 * directly does not work. 159 * directly does not work.
218 */ 160 */
219 enable_msa();
220 lose_fpu(0); 161 lose_fpu(0);
221 err = restore_fp_context(sc); /* this might fail */ 162 err = restore_fp_context(sc); /* this might fail */
222 if (restore_msa && !err)
223 err = copy_msa_from_sigcontext(sc);
224#endif 163#endif
225 return err; 164 return err;
226} 165}
@@ -252,8 +191,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
252 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); 191 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
253 } 192 }
254 193
255 used_math = used_math() ? USEDMATH_FP : 0; 194 used_math = !!used_math();
256 used_math |= thread_msa_context_live() ? USEDMATH_MSA : 0;
257 err |= __put_user(used_math, &sc->sc_used_math); 195 err |= __put_user(used_math, &sc->sc_used_math);
258 196
259 if (used_math) { 197 if (used_math) {
@@ -261,7 +199,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
261 * Save FPU state to signal context. Signal handler 199 * Save FPU state to signal context. Signal handler
262 * will "inherit" current FPU state. 200 * will "inherit" current FPU state.
263 */ 201 */
264 err |= protected_save_fp_context(sc, used_math); 202 err |= protected_save_fp_context(sc);
265 } 203 }
266 return err; 204 return err;
267} 205}
@@ -286,14 +224,14 @@ int fpcsr_pending(unsigned int __user *fpcsr)
286} 224}
287 225
288static int 226static int
289check_and_restore_fp_context(struct sigcontext __user *sc, unsigned used_math) 227check_and_restore_fp_context(struct sigcontext __user *sc)
290{ 228{
291 int err, sig; 229 int err, sig;
292 230
293 err = sig = fpcsr_pending(&sc->sc_fpc_csr); 231 err = sig = fpcsr_pending(&sc->sc_fpc_csr);
294 if (err > 0) 232 if (err > 0)
295 err = 0; 233 err = 0;
296 err |= protected_restore_fp_context(sc, used_math); 234 err |= protected_restore_fp_context(sc);
297 return err ?: sig; 235 return err ?: sig;
298} 236}
299 237
@@ -333,10 +271,9 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
333 if (used_math) { 271 if (used_math) {
334 /* restore fpu context if we have used it before */ 272 /* restore fpu context if we have used it before */
335 if (!err) 273 if (!err)
336 err = check_and_restore_fp_context(sc, used_math); 274 err = check_and_restore_fp_context(sc);
337 } else { 275 } else {
338 /* signal handler may have used FPU or MSA. Disable them. */ 276 /* signal handler may have used FPU. Give it up. */
339 disable_msa();
340 lose_fpu(0); 277 lose_fpu(0);
341 } 278 }
342 279