diff options
Diffstat (limited to 'arch/m68k/kernel/signal_mm.c')
-rw-r--r-- | arch/m68k/kernel/signal_mm.c | 187 |
1 files changed, 136 insertions, 51 deletions
diff --git a/arch/m68k/kernel/signal_mm.c b/arch/m68k/kernel/signal_mm.c index 5f6b3d0fcd16..cb856f9da655 100644 --- a/arch/m68k/kernel/signal_mm.c +++ b/arch/m68k/kernel/signal_mm.c | |||
@@ -203,7 +203,8 @@ static inline int restore_fpu_state(struct sigcontext *sc) | |||
203 | 203 | ||
204 | if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { | 204 | if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { |
205 | /* Verify the frame format. */ | 205 | /* Verify the frame format. */ |
206 | if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) | 206 | if (!(CPU_IS_060 || CPU_IS_COLDFIRE) && |
207 | (sc->sc_fpstate[0] != fpu_version)) | ||
207 | goto out; | 208 | goto out; |
208 | if (CPU_IS_020_OR_030) { | 209 | if (CPU_IS_020_OR_030) { |
209 | if (m68k_fputype & FPU_68881 && | 210 | if (m68k_fputype & FPU_68881 && |
@@ -222,19 +223,43 @@ static inline int restore_fpu_state(struct sigcontext *sc) | |||
222 | sc->sc_fpstate[3] == 0x60 || | 223 | sc->sc_fpstate[3] == 0x60 || |
223 | sc->sc_fpstate[3] == 0xe0)) | 224 | sc->sc_fpstate[3] == 0xe0)) |
224 | goto out; | 225 | goto out; |
226 | } else if (CPU_IS_COLDFIRE) { | ||
227 | if (!(sc->sc_fpstate[0] == 0x00 || | ||
228 | sc->sc_fpstate[0] == 0x05 || | ||
229 | sc->sc_fpstate[0] == 0xe5)) | ||
230 | goto out; | ||
225 | } else | 231 | } else |
226 | goto out; | 232 | goto out; |
227 | 233 | ||
228 | __asm__ volatile (".chip 68k/68881\n\t" | 234 | if (CPU_IS_COLDFIRE) { |
229 | "fmovemx %0,%%fp0-%%fp1\n\t" | 235 | __asm__ volatile ("fmovemd %0,%%fp0-%%fp1\n\t" |
230 | "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" | 236 | "fmovel %1,%%fpcr\n\t" |
231 | ".chip 68k" | 237 | "fmovel %2,%%fpsr\n\t" |
232 | : /* no outputs */ | 238 | "fmovel %3,%%fpiar" |
233 | : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); | 239 | : /* no outputs */ |
240 | : "m" (sc->sc_fpregs[0]), | ||
241 | "m" (sc->sc_fpcntl[0]), | ||
242 | "m" (sc->sc_fpcntl[1]), | ||
243 | "m" (sc->sc_fpcntl[2])); | ||
244 | } else { | ||
245 | __asm__ volatile (".chip 68k/68881\n\t" | ||
246 | "fmovemx %0,%%fp0-%%fp1\n\t" | ||
247 | "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" | ||
248 | ".chip 68k" | ||
249 | : /* no outputs */ | ||
250 | : "m" (*sc->sc_fpregs), | ||
251 | "m" (*sc->sc_fpcntl)); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | if (CPU_IS_COLDFIRE) { | ||
256 | __asm__ volatile ("frestore %0" : : "m" (*sc->sc_fpstate)); | ||
257 | } else { | ||
258 | __asm__ volatile (".chip 68k/68881\n\t" | ||
259 | "frestore %0\n\t" | ||
260 | ".chip 68k" | ||
261 | : : "m" (*sc->sc_fpstate)); | ||
234 | } | 262 | } |
235 | __asm__ volatile (".chip 68k/68881\n\t" | ||
236 | "frestore %0\n\t" | ||
237 | ".chip 68k" : : "m" (*sc->sc_fpstate)); | ||
238 | err = 0; | 263 | err = 0; |
239 | 264 | ||
240 | out: | 265 | out: |
@@ -249,7 +274,7 @@ out: | |||
249 | static inline int rt_restore_fpu_state(struct ucontext __user *uc) | 274 | static inline int rt_restore_fpu_state(struct ucontext __user *uc) |
250 | { | 275 | { |
251 | unsigned char fpstate[FPCONTEXT_SIZE]; | 276 | unsigned char fpstate[FPCONTEXT_SIZE]; |
252 | int context_size = CPU_IS_060 ? 8 : 0; | 277 | int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0); |
253 | fpregset_t fpregs; | 278 | fpregset_t fpregs; |
254 | int err = 1; | 279 | int err = 1; |
255 | 280 | ||
@@ -268,10 +293,11 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc) | |||
268 | if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) | 293 | if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) |
269 | goto out; | 294 | goto out; |
270 | if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { | 295 | if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { |
271 | if (!CPU_IS_060) | 296 | if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) |
272 | context_size = fpstate[1]; | 297 | context_size = fpstate[1]; |
273 | /* Verify the frame format. */ | 298 | /* Verify the frame format. */ |
274 | if (!CPU_IS_060 && (fpstate[0] != fpu_version)) | 299 | if (!(CPU_IS_060 || CPU_IS_COLDFIRE) && |
300 | (fpstate[0] != fpu_version)) | ||
275 | goto out; | 301 | goto out; |
276 | if (CPU_IS_020_OR_030) { | 302 | if (CPU_IS_020_OR_030) { |
277 | if (m68k_fputype & FPU_68881 && | 303 | if (m68k_fputype & FPU_68881 && |
@@ -290,26 +316,50 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc) | |||
290 | fpstate[3] == 0x60 || | 316 | fpstate[3] == 0x60 || |
291 | fpstate[3] == 0xe0)) | 317 | fpstate[3] == 0xe0)) |
292 | goto out; | 318 | goto out; |
319 | } else if (CPU_IS_COLDFIRE) { | ||
320 | if (!(fpstate[3] == 0x00 || | ||
321 | fpstate[3] == 0x05 || | ||
322 | fpstate[3] == 0xe5)) | ||
323 | goto out; | ||
293 | } else | 324 | } else |
294 | goto out; | 325 | goto out; |
295 | if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, | 326 | if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, |
296 | sizeof(fpregs))) | 327 | sizeof(fpregs))) |
297 | goto out; | 328 | goto out; |
298 | __asm__ volatile (".chip 68k/68881\n\t" | 329 | |
299 | "fmovemx %0,%%fp0-%%fp7\n\t" | 330 | if (CPU_IS_COLDFIRE) { |
300 | "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" | 331 | __asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t" |
301 | ".chip 68k" | 332 | "fmovel %1,%%fpcr\n\t" |
302 | : /* no outputs */ | 333 | "fmovel %2,%%fpsr\n\t" |
303 | : "m" (*fpregs.f_fpregs), | 334 | "fmovel %3,%%fpiar" |
304 | "m" (*fpregs.f_fpcntl)); | 335 | : /* no outputs */ |
336 | : "m" (fpregs.f_fpregs[0]), | ||
337 | "m" (fpregs.f_fpcntl[0]), | ||
338 | "m" (fpregs.f_fpcntl[1]), | ||
339 | "m" (fpregs.f_fpcntl[2])); | ||
340 | } else { | ||
341 | __asm__ volatile (".chip 68k/68881\n\t" | ||
342 | "fmovemx %0,%%fp0-%%fp7\n\t" | ||
343 | "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" | ||
344 | ".chip 68k" | ||
345 | : /* no outputs */ | ||
346 | : "m" (*fpregs.f_fpregs), | ||
347 | "m" (*fpregs.f_fpcntl)); | ||
348 | } | ||
305 | } | 349 | } |
306 | if (context_size && | 350 | if (context_size && |
307 | __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, | 351 | __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, |
308 | context_size)) | 352 | context_size)) |
309 | goto out; | 353 | goto out; |
310 | __asm__ volatile (".chip 68k/68881\n\t" | 354 | |
311 | "frestore %0\n\t" | 355 | if (CPU_IS_COLDFIRE) { |
312 | ".chip 68k" : : "m" (*fpstate)); | 356 | __asm__ volatile ("frestore %0" : : "m" (*fpstate)); |
357 | } else { | ||
358 | __asm__ volatile (".chip 68k/68881\n\t" | ||
359 | "frestore %0\n\t" | ||
360 | ".chip 68k" | ||
361 | : : "m" (*fpstate)); | ||
362 | } | ||
313 | err = 0; | 363 | err = 0; |
314 | 364 | ||
315 | out: | 365 | out: |
@@ -529,10 +579,15 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) | |||
529 | return; | 579 | return; |
530 | } | 580 | } |
531 | 581 | ||
532 | __asm__ volatile (".chip 68k/68881\n\t" | 582 | if (CPU_IS_COLDFIRE) { |
533 | "fsave %0\n\t" | 583 | __asm__ volatile ("fsave %0" |
534 | ".chip 68k" | 584 | : : "m" (*sc->sc_fpstate) : "memory"); |
535 | : : "m" (*sc->sc_fpstate) : "memory"); | 585 | } else { |
586 | __asm__ volatile (".chip 68k/68881\n\t" | ||
587 | "fsave %0\n\t" | ||
588 | ".chip 68k" | ||
589 | : : "m" (*sc->sc_fpstate) : "memory"); | ||
590 | } | ||
536 | 591 | ||
537 | if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { | 592 | if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { |
538 | fpu_version = sc->sc_fpstate[0]; | 593 | fpu_version = sc->sc_fpstate[0]; |
@@ -543,21 +598,35 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) | |||
543 | if (*(unsigned short *) sc->sc_fpstate == 0x1f38) | 598 | if (*(unsigned short *) sc->sc_fpstate == 0x1f38) |
544 | sc->sc_fpstate[0x38] |= 1 << 3; | 599 | sc->sc_fpstate[0x38] |= 1 << 3; |
545 | } | 600 | } |
546 | __asm__ volatile (".chip 68k/68881\n\t" | 601 | |
547 | "fmovemx %%fp0-%%fp1,%0\n\t" | 602 | if (CPU_IS_COLDFIRE) { |
548 | "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" | 603 | __asm__ volatile ("fmovemd %%fp0-%%fp1,%0\n\t" |
549 | ".chip 68k" | 604 | "fmovel %%fpcr,%1\n\t" |
550 | : "=m" (*sc->sc_fpregs), | 605 | "fmovel %%fpsr,%2\n\t" |
551 | "=m" (*sc->sc_fpcntl) | 606 | "fmovel %%fpiar,%3" |
552 | : /* no inputs */ | 607 | : "=m" (sc->sc_fpregs[0]), |
553 | : "memory"); | 608 | "=m" (sc->sc_fpcntl[0]), |
609 | "=m" (sc->sc_fpcntl[1]), | ||
610 | "=m" (sc->sc_fpcntl[2]) | ||
611 | : /* no inputs */ | ||
612 | : "memory"); | ||
613 | } else { | ||
614 | __asm__ volatile (".chip 68k/68881\n\t" | ||
615 | "fmovemx %%fp0-%%fp1,%0\n\t" | ||
616 | "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" | ||
617 | ".chip 68k" | ||
618 | : "=m" (*sc->sc_fpregs), | ||
619 | "=m" (*sc->sc_fpcntl) | ||
620 | : /* no inputs */ | ||
621 | : "memory"); | ||
622 | } | ||
554 | } | 623 | } |
555 | } | 624 | } |
556 | 625 | ||
557 | static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) | 626 | static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) |
558 | { | 627 | { |
559 | unsigned char fpstate[FPCONTEXT_SIZE]; | 628 | unsigned char fpstate[FPCONTEXT_SIZE]; |
560 | int context_size = CPU_IS_060 ? 8 : 0; | 629 | int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0); |
561 | int err = 0; | 630 | int err = 0; |
562 | 631 | ||
563 | if (FPU_IS_EMU) { | 632 | if (FPU_IS_EMU) { |
@@ -570,15 +639,19 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs * | |||
570 | return err; | 639 | return err; |
571 | } | 640 | } |
572 | 641 | ||
573 | __asm__ volatile (".chip 68k/68881\n\t" | 642 | if (CPU_IS_COLDFIRE) { |
574 | "fsave %0\n\t" | 643 | __asm__ volatile ("fsave %0" : : "m" (*fpstate) : "memory"); |
575 | ".chip 68k" | 644 | } else { |
576 | : : "m" (*fpstate) : "memory"); | 645 | __asm__ volatile (".chip 68k/68881\n\t" |
646 | "fsave %0\n\t" | ||
647 | ".chip 68k" | ||
648 | : : "m" (*fpstate) : "memory"); | ||
649 | } | ||
577 | 650 | ||
578 | err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); | 651 | err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); |
579 | if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { | 652 | if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { |
580 | fpregset_t fpregs; | 653 | fpregset_t fpregs; |
581 | if (!CPU_IS_060) | 654 | if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) |
582 | context_size = fpstate[1]; | 655 | context_size = fpstate[1]; |
583 | fpu_version = fpstate[0]; | 656 | fpu_version = fpstate[0]; |
584 | if (CPU_IS_020_OR_030 && | 657 | if (CPU_IS_020_OR_030 && |
@@ -588,14 +661,27 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs * | |||
588 | if (*(unsigned short *) fpstate == 0x1f38) | 661 | if (*(unsigned short *) fpstate == 0x1f38) |
589 | fpstate[0x38] |= 1 << 3; | 662 | fpstate[0x38] |= 1 << 3; |
590 | } | 663 | } |
591 | __asm__ volatile (".chip 68k/68881\n\t" | 664 | if (CPU_IS_COLDFIRE) { |
592 | "fmovemx %%fp0-%%fp7,%0\n\t" | 665 | __asm__ volatile ("fmovemd %%fp0-%%fp7,%0\n\t" |
593 | "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" | 666 | "fmovel %%fpcr,%1\n\t" |
594 | ".chip 68k" | 667 | "fmovel %%fpsr,%2\n\t" |
595 | : "=m" (*fpregs.f_fpregs), | 668 | "fmovel %%fpiar,%3" |
596 | "=m" (*fpregs.f_fpcntl) | 669 | : "=m" (fpregs.f_fpregs[0]), |
597 | : /* no inputs */ | 670 | "=m" (fpregs.f_fpcntl[0]), |
598 | : "memory"); | 671 | "=m" (fpregs.f_fpcntl[1]), |
672 | "=m" (fpregs.f_fpcntl[2]) | ||
673 | : /* no inputs */ | ||
674 | : "memory"); | ||
675 | } else { | ||
676 | __asm__ volatile (".chip 68k/68881\n\t" | ||
677 | "fmovemx %%fp0-%%fp7,%0\n\t" | ||
678 | "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" | ||
679 | ".chip 68k" | ||
680 | : "=m" (*fpregs.f_fpregs), | ||
681 | "=m" (*fpregs.f_fpcntl) | ||
682 | : /* no inputs */ | ||
683 | : "memory"); | ||
684 | } | ||
599 | err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, | 685 | err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, |
600 | sizeof(fpregs)); | 686 | sizeof(fpregs)); |
601 | } | 687 | } |
@@ -692,8 +778,7 @@ static inline void push_cache (unsigned long vaddr) | |||
692 | "cpushl %%bc,(%0)\n\t" | 778 | "cpushl %%bc,(%0)\n\t" |
693 | ".chip 68k" | 779 | ".chip 68k" |
694 | : : "a" (temp)); | 780 | : : "a" (temp)); |
695 | } | 781 | } else if (!CPU_IS_COLDFIRE) { |
696 | else { | ||
697 | /* | 782 | /* |
698 | * 68030/68020 have no writeback cache; | 783 | * 68030/68020 have no writeback cache; |
699 | * still need to clear icache. | 784 | * still need to clear icache. |