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. |
