aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@uclinux.org>2011-10-14 02:43:15 -0400
committerGreg Ungerer <gerg@uclinux.org>2011-12-29 19:20:27 -0500
commit78d705e3be4bfbd2e75157d284096d600ea6eda5 (patch)
tree794ffa49a1dbc8aa54d173a5771075c557b35d86
parent813db7fc1550687d3e42e793a67b2322df5114a4 (diff)
m68k: add ColdFire paging exception handling code
Add code to traps.c to handle MMU exceptions for the ColdFire. Most of this code is from the 2.6.25 kernel BSP code released by Freescale. Signed-off-by: Greg Ungerer <gerg@uclinux.org> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Matt Waddel <mwaddel@yahoo.com> Acked-by: Kurt Mahan <kmahan@xmission.com>
-rw-r--r--arch/m68k/kernel/traps.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 89362f2bb56a..a76452ca964e 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -706,6 +706,88 @@ create_atc_entry:
706#endif /* CPU_M68020_OR_M68030 */ 706#endif /* CPU_M68020_OR_M68030 */
707#endif /* !CONFIG_SUN3 */ 707#endif /* !CONFIG_SUN3 */
708 708
709#if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU)
710#include <asm/mcfmmu.h>
711
712/*
713 * The following table converts the FS encoding of a ColdFire
714 * exception stack frame into the error_code value needed by
715 * do_fault.
716*/
717static const unsigned char fs_err_code[] = {
718 0, /* 0000 */
719 0, /* 0001 */
720 0, /* 0010 */
721 0, /* 0011 */
722 1, /* 0100 */
723 0, /* 0101 */
724 0, /* 0110 */
725 0, /* 0111 */
726 2, /* 1000 */
727 3, /* 1001 */
728 2, /* 1010 */
729 0, /* 1011 */
730 1, /* 1100 */
731 1, /* 1101 */
732 0, /* 1110 */
733 0 /* 1111 */
734};
735
736static inline void access_errorcf(unsigned int fs, struct frame *fp)
737{
738 unsigned long mmusr, addr;
739 unsigned int err_code;
740 int need_page_fault;
741
742 mmusr = mmu_read(MMUSR);
743 addr = mmu_read(MMUAR);
744
745 /*
746 * error_code:
747 * bit 0 == 0 means no page found, 1 means protection fault
748 * bit 1 == 0 means read, 1 means write
749 */
750 switch (fs) {
751 case 5: /* 0101 TLB opword X miss */
752 need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0);
753 addr = fp->ptregs.pc;
754 break;
755 case 6: /* 0110 TLB extension word X miss */
756 need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1);
757 addr = fp->ptregs.pc + sizeof(long);
758 break;
759 case 10: /* 1010 TLB W miss */
760 need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0);
761 break;
762 case 14: /* 1110 TLB R miss */
763 need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0);
764 break;
765 default:
766 /* 0000 Normal */
767 /* 0001 Reserved */
768 /* 0010 Interrupt during debug service routine */
769 /* 0011 Reserved */
770 /* 0100 X Protection */
771 /* 0111 IFP in emulator mode */
772 /* 1000 W Protection*/
773 /* 1001 Write error*/
774 /* 1011 Reserved*/
775 /* 1100 R Protection*/
776 /* 1101 R Protection*/
777 /* 1111 OEP in emulator mode*/
778 need_page_fault = 1;
779 break;
780 }
781
782 if (need_page_fault) {
783 err_code = fs_err_code[fs];
784 if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */
785 err_code |= 2; /* bit1 - write, bit0 - protection */
786 do_page_fault(&fp->ptregs, addr, err_code);
787 }
788}
789#endif /* CONFIG_COLDFIRE CONFIG_MMU */
790
709asmlinkage void buserr_c(struct frame *fp) 791asmlinkage void buserr_c(struct frame *fp)
710{ 792{
711 /* Only set esp0 if coming from user mode */ 793 /* Only set esp0 if coming from user mode */
@@ -716,6 +798,28 @@ asmlinkage void buserr_c(struct frame *fp)
716 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); 798 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
717#endif 799#endif
718 800
801#if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU)
802 if (CPU_IS_COLDFIRE) {
803 unsigned int fs;
804 fs = (fp->ptregs.vector & 0x3) |
805 ((fp->ptregs.vector & 0xc00) >> 8);
806 switch (fs) {
807 case 0x5:
808 case 0x6:
809 case 0x7:
810 case 0x9:
811 case 0xa:
812 case 0xd:
813 case 0xe:
814 case 0xf:
815 access_errorcf(fs, fp);
816 return;
817 default:
818 break;
819 }
820 }
821#endif /* CONFIG_COLDFIRE && CONFIG_MMU */
822
719 switch (fp->ptregs.format) { 823 switch (fp->ptregs.format) {
720#if defined (CONFIG_M68060) 824#if defined (CONFIG_M68060)
721 case 4: /* 68060 access error */ 825 case 4: /* 68060 access error */