diff options
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 74 |
1 files changed, 8 insertions, 66 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 299f956e4db3..bae2e6ee2109 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/sim.h> | 30 | #include <asm/sim.h> |
31 | #include <asm/ucontext.h> | 31 | #include <asm/ucontext.h> |
32 | #include <asm/fpu.h> | 32 | #include <asm/fpu.h> |
33 | #include <asm/msa.h> | ||
34 | #include <asm/war.h> | 33 | #include <asm/war.h> |
35 | #include <asm/vdso.h> | 34 | #include <asm/vdso.h> |
36 | #include <asm/dsp.h> | 35 | #include <asm/dsp.h> |
@@ -43,9 +42,6 @@ static int (*restore_fp_context32)(struct sigcontext32 __user *sc); | |||
43 | extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); | 42 | extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); |
44 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); | 43 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); |
45 | 44 | ||
46 | extern asmlinkage int _save_msa_context32(struct sigcontext32 __user *sc); | ||
47 | extern asmlinkage int _restore_msa_context32(struct sigcontext32 __user *sc); | ||
48 | |||
49 | /* | 45 | /* |
50 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... | 46 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... |
51 | */ | 47 | */ |
@@ -115,59 +111,19 @@ static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc) | |||
115 | } | 111 | } |
116 | 112 | ||
117 | /* | 113 | /* |
118 | * These functions will save only the upper 64 bits of the vector registers, | ||
119 | * since the lower 64 bits have already been saved as the scalar FP context. | ||
120 | */ | ||
121 | static int copy_msa_to_sigcontext32(struct sigcontext32 __user *sc) | ||
122 | { | ||
123 | int i; | ||
124 | int err = 0; | ||
125 | |||
126 | for (i = 0; i < NUM_FPU_REGS; i++) { | ||
127 | err |= | ||
128 | __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 1), | ||
129 | &sc->sc_msaregs[i]); | ||
130 | } | ||
131 | err |= __put_user(current->thread.fpu.msacsr, &sc->sc_msa_csr); | ||
132 | |||
133 | return err; | ||
134 | } | ||
135 | |||
136 | static int copy_msa_from_sigcontext32(struct sigcontext32 __user *sc) | ||
137 | { | ||
138 | int i; | ||
139 | int err = 0; | ||
140 | u64 val; | ||
141 | |||
142 | for (i = 0; i < NUM_FPU_REGS; i++) { | ||
143 | err |= __get_user(val, &sc->sc_msaregs[i]); | ||
144 | set_fpr64(¤t->thread.fpu.fpr[i], 1, val); | ||
145 | } | ||
146 | err |= __get_user(current->thread.fpu.msacsr, &sc->sc_msa_csr); | ||
147 | |||
148 | return err; | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * sigcontext handlers | 114 | * sigcontext handlers |
153 | */ | 115 | */ |
154 | static int protected_save_fp_context32(struct sigcontext32 __user *sc, | 116 | static int protected_save_fp_context32(struct sigcontext32 __user *sc) |
155 | unsigned used_math) | ||
156 | { | 117 | { |
157 | int err; | 118 | int err; |
158 | bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA); | ||
159 | while (1) { | 119 | while (1) { |
160 | lock_fpu_owner(); | 120 | lock_fpu_owner(); |
161 | if (is_fpu_owner()) { | 121 | if (is_fpu_owner()) { |
162 | err = save_fp_context32(sc); | 122 | err = save_fp_context32(sc); |
163 | if (save_msa && !err) | ||
164 | err = _save_msa_context32(sc); | ||
165 | unlock_fpu_owner(); | 123 | unlock_fpu_owner(); |
166 | } else { | 124 | } else { |
167 | unlock_fpu_owner(); | 125 | unlock_fpu_owner(); |
168 | err = copy_fp_to_sigcontext32(sc); | 126 | err = copy_fp_to_sigcontext32(sc); |
169 | if (save_msa && !err) | ||
170 | err = copy_msa_to_sigcontext32(sc); | ||
171 | } | 127 | } |
172 | if (likely(!err)) | 128 | if (likely(!err)) |
173 | break; | 129 | break; |
@@ -181,28 +137,17 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc, | |||
181 | return err; | 137 | return err; |
182 | } | 138 | } |
183 | 139 | ||
184 | static int protected_restore_fp_context32(struct sigcontext32 __user *sc, | 140 | static int protected_restore_fp_context32(struct sigcontext32 __user *sc) |
185 | unsigned used_math) | ||
186 | { | 141 | { |
187 | int err, tmp __maybe_unused; | 142 | int err, tmp __maybe_unused; |
188 | bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA); | ||
189 | while (1) { | 143 | while (1) { |
190 | lock_fpu_owner(); | 144 | lock_fpu_owner(); |
191 | if (is_fpu_owner()) { | 145 | if (is_fpu_owner()) { |
192 | err = restore_fp_context32(sc); | 146 | err = restore_fp_context32(sc); |
193 | if (restore_msa && !err) { | ||
194 | enable_msa(); | ||
195 | err = _restore_msa_context32(sc); | ||
196 | } else { | ||
197 | /* signal handler may have used MSA */ | ||
198 | disable_msa(); | ||
199 | } | ||
200 | unlock_fpu_owner(); | 147 | unlock_fpu_owner(); |
201 | } else { | 148 | } else { |
202 | unlock_fpu_owner(); | 149 | unlock_fpu_owner(); |
203 | err = copy_fp_from_sigcontext32(sc); | 150 | err = copy_fp_from_sigcontext32(sc); |
204 | if (restore_msa && !err) | ||
205 | err = copy_msa_from_sigcontext32(sc); | ||
206 | } | 151 | } |
207 | if (likely(!err)) | 152 | if (likely(!err)) |
208 | break; | 153 | break; |
@@ -241,8 +186,7 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
241 | err |= __put_user(mflo3(), &sc->sc_lo3); | 186 | err |= __put_user(mflo3(), &sc->sc_lo3); |
242 | } | 187 | } |
243 | 188 | ||
244 | used_math = used_math() ? USEDMATH_FP : 0; | 189 | used_math = !!used_math(); |
245 | used_math |= thread_msa_context_live() ? USEDMATH_MSA : 0; | ||
246 | err |= __put_user(used_math, &sc->sc_used_math); | 190 | err |= __put_user(used_math, &sc->sc_used_math); |
247 | 191 | ||
248 | if (used_math) { | 192 | if (used_math) { |
@@ -250,21 +194,20 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
250 | * Save FPU state to signal context. Signal handler | 194 | * Save FPU state to signal context. Signal handler |
251 | * will "inherit" current FPU state. | 195 | * will "inherit" current FPU state. |
252 | */ | 196 | */ |
253 | err |= protected_save_fp_context32(sc, used_math); | 197 | err |= protected_save_fp_context32(sc); |
254 | } | 198 | } |
255 | return err; | 199 | return err; |
256 | } | 200 | } |
257 | 201 | ||
258 | static int | 202 | static int |
259 | check_and_restore_fp_context32(struct sigcontext32 __user *sc, | 203 | check_and_restore_fp_context32(struct sigcontext32 __user *sc) |
260 | unsigned used_math) | ||
261 | { | 204 | { |
262 | int err, sig; | 205 | int err, sig; |
263 | 206 | ||
264 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | 207 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); |
265 | if (err > 0) | 208 | if (err > 0) |
266 | err = 0; | 209 | err = 0; |
267 | err |= protected_restore_fp_context32(sc, used_math); | 210 | err |= protected_restore_fp_context32(sc); |
268 | return err ?: sig; | 211 | return err ?: sig; |
269 | } | 212 | } |
270 | 213 | ||
@@ -301,10 +244,9 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
301 | if (used_math) { | 244 | if (used_math) { |
302 | /* restore fpu context if we have used it before */ | 245 | /* restore fpu context if we have used it before */ |
303 | if (!err) | 246 | if (!err) |
304 | err = check_and_restore_fp_context32(sc, used_math); | 247 | err = check_and_restore_fp_context32(sc); |
305 | } else { | 248 | } else { |
306 | /* signal handler may have used FPU or MSA. Disable them. */ | 249 | /* signal handler may have used FPU. Give it up. */ |
307 | disable_msa(); | ||
308 | lose_fpu(0); | 250 | lose_fpu(0); |
309 | } | 251 | } |
310 | 252 | ||