aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/kernel/traps.c')
-rw-r--r--arch/m68k/kernel/traps.c140
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*/
715static 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
734static 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
709asmlinkage void buserr_c(struct frame *fp) 789asmlinkage 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 */