diff options
Diffstat (limited to 'arch/m68k/kernel/traps.c')
-rw-r--r-- | arch/m68k/kernel/traps.c | 140 |
1 files changed, 121 insertions, 19 deletions
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 89362f2bb56a..daaa9187654c 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c | |||
@@ -552,13 +552,13 @@ static inline void bus_error030 (struct frame *fp) | |||
552 | 552 | ||
553 | #ifdef DEBUG | 553 | #ifdef DEBUG |
554 | asm volatile ("ptestr %3,%2@,#7,%0\n\t" | 554 | asm volatile ("ptestr %3,%2@,#7,%0\n\t" |
555 | "pmove %%psr,%1@" | 555 | "pmove %%psr,%1" |
556 | : "=a&" (desc) | 556 | : "=a&" (desc), "=m" (temp) |
557 | : "a" (&temp), "a" (addr), "d" (ssw)); | 557 | : "a" (addr), "d" (ssw)); |
558 | #else | 558 | #else |
559 | asm volatile ("ptestr %2,%1@,#7\n\t" | 559 | asm volatile ("ptestr %2,%1@,#7\n\t" |
560 | "pmove %%psr,%0@" | 560 | "pmove %%psr,%0" |
561 | : : "a" (&temp), "a" (addr), "d" (ssw)); | 561 | : "=m" (temp) : "a" (addr), "d" (ssw)); |
562 | #endif | 562 | #endif |
563 | mmusr = temp; | 563 | mmusr = temp; |
564 | 564 | ||
@@ -605,20 +605,18 @@ static inline void bus_error030 (struct frame *fp) | |||
605 | !(ssw & RW) ? "write" : "read", addr, | 605 | !(ssw & RW) ? "write" : "read", addr, |
606 | fp->ptregs.pc, ssw); | 606 | fp->ptregs.pc, ssw); |
607 | asm volatile ("ptestr #1,%1@,#0\n\t" | 607 | asm volatile ("ptestr #1,%1@,#0\n\t" |
608 | "pmove %%psr,%0@" | 608 | "pmove %%psr,%0" |
609 | : /* no outputs */ | 609 | : "=m" (temp) |
610 | : "a" (&temp), "a" (addr)); | 610 | : "a" (addr)); |
611 | mmusr = temp; | 611 | mmusr = temp; |
612 | 612 | ||
613 | printk ("level 0 mmusr is %#x\n", mmusr); | 613 | printk ("level 0 mmusr is %#x\n", mmusr); |
614 | #if 0 | 614 | #if 0 |
615 | asm volatile ("pmove %%tt0,%0@" | 615 | asm volatile ("pmove %%tt0,%0" |
616 | : /* no outputs */ | 616 | : "=m" (tlong)); |
617 | : "a" (&tlong)); | ||
618 | printk("tt0 is %#lx, ", tlong); | 617 | printk("tt0 is %#lx, ", tlong); |
619 | asm volatile ("pmove %%tt1,%0@" | 618 | asm volatile ("pmove %%tt1,%0" |
620 | : /* no outputs */ | 619 | : "=m" (tlong)); |
621 | : "a" (&tlong)); | ||
622 | printk("tt1 is %#lx\n", tlong); | 620 | printk("tt1 is %#lx\n", tlong); |
623 | #endif | 621 | #endif |
624 | #ifdef DEBUG | 622 | #ifdef DEBUG |
@@ -668,13 +666,13 @@ static inline void bus_error030 (struct frame *fp) | |||
668 | 666 | ||
669 | #ifdef DEBUG | 667 | #ifdef DEBUG |
670 | asm volatile ("ptestr #1,%2@,#7,%0\n\t" | 668 | asm volatile ("ptestr #1,%2@,#7,%0\n\t" |
671 | "pmove %%psr,%1@" | 669 | "pmove %%psr,%1" |
672 | : "=a&" (desc) | 670 | : "=a&" (desc), "=m" (temp) |
673 | : "a" (&temp), "a" (addr)); | 671 | : "a" (addr)); |
674 | #else | 672 | #else |
675 | asm volatile ("ptestr #1,%1@,#7\n\t" | 673 | asm volatile ("ptestr #1,%1@,#7\n\t" |
676 | "pmove %%psr,%0@" | 674 | "pmove %%psr,%0" |
677 | : : "a" (&temp), "a" (addr)); | 675 | : "=m" (temp) : "a" (addr)); |
678 | #endif | 676 | #endif |
679 | mmusr = temp; | 677 | mmusr = temp; |
680 | 678 | ||
@@ -706,6 +704,88 @@ create_atc_entry: | |||
706 | #endif /* CPU_M68020_OR_M68030 */ | 704 | #endif /* CPU_M68020_OR_M68030 */ |
707 | #endif /* !CONFIG_SUN3 */ | 705 | #endif /* !CONFIG_SUN3 */ |
708 | 706 | ||
707 | #if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) | ||
708 | #include <asm/mcfmmu.h> | ||
709 | |||
710 | /* | ||
711 | * The following table converts the FS encoding of a ColdFire | ||
712 | * exception stack frame into the error_code value needed by | ||
713 | * do_fault. | ||
714 | */ | ||
715 | static const unsigned char fs_err_code[] = { | ||
716 | 0, /* 0000 */ | ||
717 | 0, /* 0001 */ | ||
718 | 0, /* 0010 */ | ||
719 | 0, /* 0011 */ | ||
720 | 1, /* 0100 */ | ||
721 | 0, /* 0101 */ | ||
722 | 0, /* 0110 */ | ||
723 | 0, /* 0111 */ | ||
724 | 2, /* 1000 */ | ||
725 | 3, /* 1001 */ | ||
726 | 2, /* 1010 */ | ||
727 | 0, /* 1011 */ | ||
728 | 1, /* 1100 */ | ||
729 | 1, /* 1101 */ | ||
730 | 0, /* 1110 */ | ||
731 | 0 /* 1111 */ | ||
732 | }; | ||
733 | |||
734 | static inline void access_errorcf(unsigned int fs, struct frame *fp) | ||
735 | { | ||
736 | unsigned long mmusr, addr; | ||
737 | unsigned int err_code; | ||
738 | int need_page_fault; | ||
739 | |||
740 | mmusr = mmu_read(MMUSR); | ||
741 | addr = mmu_read(MMUAR); | ||
742 | |||
743 | /* | ||
744 | * error_code: | ||
745 | * bit 0 == 0 means no page found, 1 means protection fault | ||
746 | * bit 1 == 0 means read, 1 means write | ||
747 | */ | ||
748 | switch (fs) { | ||
749 | case 5: /* 0101 TLB opword X miss */ | ||
750 | need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0); | ||
751 | addr = fp->ptregs.pc; | ||
752 | break; | ||
753 | case 6: /* 0110 TLB extension word X miss */ | ||
754 | need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1); | ||
755 | addr = fp->ptregs.pc + sizeof(long); | ||
756 | break; | ||
757 | case 10: /* 1010 TLB W miss */ | ||
758 | need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0); | ||
759 | break; | ||
760 | case 14: /* 1110 TLB R miss */ | ||
761 | need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0); | ||
762 | break; | ||
763 | default: | ||
764 | /* 0000 Normal */ | ||
765 | /* 0001 Reserved */ | ||
766 | /* 0010 Interrupt during debug service routine */ | ||
767 | /* 0011 Reserved */ | ||
768 | /* 0100 X Protection */ | ||
769 | /* 0111 IFP in emulator mode */ | ||
770 | /* 1000 W Protection*/ | ||
771 | /* 1001 Write error*/ | ||
772 | /* 1011 Reserved*/ | ||
773 | /* 1100 R Protection*/ | ||
774 | /* 1101 R Protection*/ | ||
775 | /* 1111 OEP in emulator mode*/ | ||
776 | need_page_fault = 1; | ||
777 | break; | ||
778 | } | ||
779 | |||
780 | if (need_page_fault) { | ||
781 | err_code = fs_err_code[fs]; | ||
782 | if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */ | ||
783 | err_code |= 2; /* bit1 - write, bit0 - protection */ | ||
784 | do_page_fault(&fp->ptregs, addr, err_code); | ||
785 | } | ||
786 | } | ||
787 | #endif /* CONFIG_COLDFIRE CONFIG_MMU */ | ||
788 | |||
709 | asmlinkage void buserr_c(struct frame *fp) | 789 | asmlinkage void buserr_c(struct frame *fp) |
710 | { | 790 | { |
711 | /* Only set esp0 if coming from user mode */ | 791 | /* Only set esp0 if coming from user mode */ |
@@ -716,6 +796,28 @@ asmlinkage void buserr_c(struct frame *fp) | |||
716 | printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); | 796 | printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); |
717 | #endif | 797 | #endif |
718 | 798 | ||
799 | #if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) | ||
800 | if (CPU_IS_COLDFIRE) { | ||
801 | unsigned int fs; | ||
802 | fs = (fp->ptregs.vector & 0x3) | | ||
803 | ((fp->ptregs.vector & 0xc00) >> 8); | ||
804 | switch (fs) { | ||
805 | case 0x5: | ||
806 | case 0x6: | ||
807 | case 0x7: | ||
808 | case 0x9: | ||
809 | case 0xa: | ||
810 | case 0xd: | ||
811 | case 0xe: | ||
812 | case 0xf: | ||
813 | access_errorcf(fs, fp); | ||
814 | return; | ||
815 | default: | ||
816 | break; | ||
817 | } | ||
818 | } | ||
819 | #endif /* CONFIG_COLDFIRE && CONFIG_MMU */ | ||
820 | |||
719 | switch (fp->ptregs.format) { | 821 | switch (fp->ptregs.format) { |
720 | #if defined (CONFIG_M68060) | 822 | #if defined (CONFIG_M68060) |
721 | case 4: /* 68060 access error */ | 823 | case 4: /* 68060 access error */ |