diff options
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r-- | arch/mips/kernel/signal.c | 79 |
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); | |||
48 | extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); | 47 | extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); |
49 | extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); | 48 | extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); |
50 | 49 | ||
51 | extern asmlinkage int _save_msa_context(struct sigcontext __user *sc); | ||
52 | extern asmlinkage int _restore_msa_context(struct sigcontext __user *sc); | ||
53 | |||
54 | struct sigframe { | 50 | struct 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 | */ | ||
106 | static 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(¤t->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 | |||
121 | static 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(¤t->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 | */ |
139 | static int protected_save_fp_context(struct sigcontext __user *sc, | 101 | static 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 | ||
181 | static int protected_restore_fp_context(struct sigcontext __user *sc, | 134 | static 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 | ||
288 | static int | 226 | static int |
289 | check_and_restore_fp_context(struct sigcontext __user *sc, unsigned used_math) | 227 | check_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 | ||