m68knommu: use user stack pointer hardware on some ColdFire cores
authorGreg Ungerer <gerg@uclinux.org>
Thu, 4 Nov 2010 03:53:26 +0000 (13:53 +1000)
committerGreg Ungerer <gerg@uclinux.org>
Wed, 5 Jan 2011 05:19:18 +0000 (15:19 +1000)
The more modern ColdFire parts (even if based on older version cores)
have separate user and supervisor stack pointers (a7 register).
Modify the ColdFire CPU setup and exception code to enable and use
this on parts that have it.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
arch/m68k/include/asm/cacheflush_no.h
arch/m68k/include/asm/entry_no.h
arch/m68k/include/asm/m54xxacr.h
arch/m68k/include/asm/mcfcache.h
arch/m68k/include/asm/processor.h
arch/m68knommu/Kconfig
arch/m68knommu/platform/coldfire/entry.S

index 9246392e13722e8063481ebff39434a1617aaf93..e295923020d3c2854bfe5ad65221227557712056 100644 (file)
@@ -37,7 +37,7 @@ static inline void __flush_cache_all(void)
 {
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x)
        __asm__ __volatile__ (
-               "movel  #0x81400100, %%d0\n\t"
+               "movel  #0x81400110, %%d0\n\t"
                "movec  %%d0, %%CACR\n\t"
                "nop\n\t"
                : : : "d0" );
@@ -65,7 +65,7 @@ static inline void __flush_cache_all(void)
 #endif /* CONFIG_M5249 */
 #ifdef CONFIG_M532x
        __asm__ __volatile__ (
-               "movel  #0x81000200, %%d0\n\t"
+               "movel  #0x81000210, %%d0\n\t"
                "movec  %%d0, %%CACR\n\t"
                "nop\n\t"
                : : : "d0" );
index 26be277394f9fc647931f2145e67173d648c20f2..627d69bacc58c6afc2412c13fa6f01282c3ada4d 100644 (file)
  */
 
 #ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
 /*
- * This is made a little more tricky on the ColdFire. There is no
- * separate kernel and user stack pointers. Need to artificially
+ * This is made a little more tricky on older ColdFires. There is no
+ * separate supervisor and user stack pointers. Need to artificially
  * construct a usp in software... When doing this we need to disable
- * interrupts, otherwise bad things could happen.
+ * interrupts, otherwise bad things will happen.
  */
+.globl sw_usp
+.globl sw_ksp
+
 .macro SAVE_ALL
        move    #0x2700,%sr             /* disable intrs */
        btst    #5,%sp@(2)              /* from user? */
@@ -74,9 +78,7 @@
        7:
 .endm
 
-.macro RESTORE_ALL
-       btst    #5,%sp@(PT_SR)          /* going user? */
-       bnes    8f                      /* no, skip */
+.macro RESTORE_USER
        move    #0x2700,%sr             /* disable intrs */
        movel   sw_usp,%a0              /* get usp */
        movel   %sp@(PT_OFF_PC),%a0@-   /* copy exception program counter */
        subql   #8,sw_usp               /* set exception */
        movel   sw_usp,%sp              /* restore usp */
        rte
-       8:
-       moveml  %sp@,%d1-%d5/%a0-%a2
-       lea     %sp@(32),%sp            /* space for 8 regs */
-       movel   %sp@+,%d0
-       addql   #4,%sp                  /* orig d0 */
-       addl    %sp@+,%sp               /* stkadj */
-       rte
 .endm
 
+.macro RDUSP
+       movel   sw_usp,%a2
+.endm
+
+.macro WRUSP
+       movel   %a0,sw_usp
+.endm
+
+#else /* !CONFIG_COLDFIRE_SW_A7 */
 /*
- * Quick exception save, use current stack only.
+ * Modern ColdFire parts have separate supervisor and user stack
+ * pointers. Simple load and restore macros for this case.
  */
-.macro SAVE_LOCAL
+.macro SAVE_ALL
        move    #0x2700,%sr             /* disable intrs */
        clrl    %sp@-                   /* stkadj */
        movel   %d0,%sp@-               /* orig d0 */
        moveml  %d1-%d5/%a0-%a2,%sp@
 .endm
 
-.macro RESTORE_LOCAL
+.macro RESTORE_USER
        moveml  %sp@,%d1-%d5/%a0-%a2
        lea     %sp@(32),%sp            /* space for 8 regs */
        movel   %sp@+,%d0
        rte
 .endm
 
+.macro RDUSP
+       /*move  %usp,%a2*/
+       .word   0x4e6a
+.endm
+
+.macro WRUSP
+       /*move  %a0,%usp*/
+       .word   0x4e60
+.endm
+
+#endif /* !CONFIG_COLDFIRE_SW_A7 */
+
 .macro SAVE_SWITCH_STACK
        lea     %sp@(-24),%sp           /* 6 regs */
        moveml  %a3-%a6/%d6-%d7,%sp@
        lea     %sp@(24),%sp            /* 6 regs */
 .endm
 
-/*
- * Software copy of the user and kernel stack pointers... Ugh...
- * Need these to get around ColdFire not having separate kernel
- * and user stack pointers.
- */
-.globl sw_usp
-.globl sw_ksp
-
 #else /* !CONFIG_COLDFIRE */
 
 /*
        moveml  %sp@+,%a3-%a6/%d6-%d7
 .endm
 
-#endif /* !CONFIG_COLDFIRE */
+#endif /* !COLDFIRE_SW_A7 */
 #endif /* __ASSEMBLY__ */
 #endif /* __M68KNOMMU_ENTRY_H */
index 76d64906aa6292b1c708ae3939d5832ca56952ae..12209c68b90401f4b91d190cd5c6f95472aee0be 100644 (file)
@@ -26,6 +26,7 @@
 #define CACR_IHLCK     0x00000800      /* Intruction cache half lock */
 #define CACR_IDCM      0x00000400      /* Intruction cache inhibit */
 #define CACR_ICINVA    0x00000100      /* Invalidate instr cache */
+#define CACR_EUSP      0x00000020      /* Enable separate user a7 */
 
 #define ACR_BASE_POS   24              /* Address Base */
 #define ACR_MASK_POS   16              /* Address Mask */
        /* Enable data store buffer */
        /* outside ACRs : No cache, precise */
        /* Enable instruction+branch caches */
+#if defined(CONFIG_M5407)
 #define CACHE_MODE (CACR_DEC+CACR_DESB+CACR_DDCM_P+CACR_BEC+CACR_IEC)
+#else
+#define CACHE_MODE (CACR_DEC+CACR_DESB+CACR_DDCM_P+CACR_BEC+CACR_IEC+CACR_EUSP)
+#endif
 
 #define DATA_CACHE_MODE (ACR_ENABLE+ACR_ANY+ACR_CM_WT)
 
index 1b66018461b817aef043830ca5b45354ff7a8ed5..437686b62feaf38f76fe892f714720e59bd66826 100644 (file)
@@ -46,7 +46,7 @@
        movec   %d0,%ACR0
        movel   #0x00000000,%d0         /* no other regions cached */
        movec   %d0,%ACR1
-       movel   #0x80400100,%d0         /* configure cache */
+       movel   #0x80400110,%d0         /* configure cache */
        movec   %d0,%CACR               /* enable cache */
        nop
 .endm
        movec   %d0,%ACR0
        movel   #0x00000000,%d0         /* no other regions cached */
        movec   %d0,%ACR1
-       movel   #0x80000200,%d0         /* setup cache mask */
+       movel   #0x80000210,%d0         /* setup cache mask */
        movec   %d0,%CACR               /* enable cache */
        nop
 .endm
        movec   %d0,%ACR0
        move.l  #0x00000000,%d0         /* no other regions cached */
        movec   %d0,%ACR1
-       move.l  #0x80400000,%d0         /* enable 8K instruction cache */
+       move.l  #0x80400010,%d0         /* enable 8K instruction cache */
        movec   %d0,%CACR
        nop
 .endm
index 7a6a7590cc02cd584d28fd9e2a98d9d1b8b30797..278c69bad57a8369a542851df92571cdcf988447 100644 (file)
 
 static inline unsigned long rdusp(void)
 {
-#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
        extern unsigned int sw_usp;
        return sw_usp;
 #else
-       unsigned long usp;
-       __asm__ __volatile__("move %/usp,%0" : "=a" (usp));
+       register unsigned long usp __asm__("a0");
+       /* move %usp,%a0 */
+       __asm__ __volatile__(".word 0x4e68" : "=a" (usp));
        return usp;
 #endif
 }
 
 static inline void wrusp(unsigned long usp)
 {
-#ifdef CONFIG_COLDFIRE
+#ifdef CONFIG_COLDFIRE_SW_A7
        extern unsigned int sw_usp;
        sw_usp = usp;
 #else
-       __asm__ __volatile__("move %0,%/usp" : : "a" (usp));
+       register unsigned long a0 __asm__("a0") = usp;
+       /* move %a0,%usp */
+       __asm__ __volatile__(".word 0x4e60" : : "a" (a0) );
 #endif
 }
 
index 266a39eebcada7f83773b17ea3093d2f3dd9c6ff..e6f482d18d05472757af3bf3f0d3a3d9b4d0b70d 100644 (file)
@@ -75,6 +75,10 @@ config GENERIC_CLOCKEVENTS
 config NO_IOPORT
        def_bool y
 
+config COLDFIRE_SW_A7
+       bool
+       default n
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -107,11 +111,13 @@ config M68360
 
 config M5206
        bool "MCF5206"
+       select COLDFIRE_SW_A7
        help
          Motorola ColdFire 5206 processor support.
 
 config M5206e
        bool "MCF5206e"
+       select COLDFIRE_SW_A7
        help
          Motorola ColdFire 5206e processor support.
 
@@ -129,6 +135,7 @@ config M523x
 
 config M5249
        bool "MCF5249"
+       select COLDFIRE_SW_A7
        help
          Motorola ColdFire 5249 processor support.
 
@@ -139,6 +146,7 @@ config M5271
 
 config M5272
        bool "MCF5272"
+       select COLDFIRE_SW_A7
        help
          Motorola ColdFire 5272 processor support.
 
@@ -155,6 +163,7 @@ config M528x
 
 config M5307
        bool "MCF5307"
+       select COLDFIRE_SW_A7
        help
          Motorola ColdFire 5307 processor support.
 
@@ -165,6 +174,7 @@ config M532x
 
 config M5407
        bool "MCF5407"
+       select COLDFIRE_SW_A7
        help
          Motorola ColdFire 5407 processor support.
 
index b9ce3196618180dcb1af3d8ebc06d2322e189802..f90e6173ccd4a56ce27e375b28f33cbfaf44a5a6 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/entry.h>
 
+#ifdef CONFIG_COLDFIRE_SW_A7
+/*
+ *     Define software copies of the supervisor and user stack pointers.
+ */
 .bss
-
 sw_ksp:
 .long  0
-
 sw_usp:
 .long  0
+#endif /* CONFIG_COLDFIRE_SW_A7 */
 
 .text
 
@@ -52,6 +55,7 @@ sw_usp:
 .globl ret_from_signal
 .globl sys_call_table
 .globl inthandler
+.globl fasthandler
 
 enosys:
        mov.l   #sys_ni_syscall,%d3
@@ -138,20 +142,7 @@ Luser_return:
        jne     Lwork_to_do             /* still work to do */
 
 Lreturn:
-       move    #0x2700,%sr             /* disable intrs */
-       movel   sw_usp,%a0              /* get usp */
-       movel   %sp@(PT_OFF_PC),%a0@-   /* copy exception program counter */
-       movel   %sp@(PT_OFF_FORMATVEC),%a0@- /* copy exception format/vector/sr */
-       moveml  %sp@,%d1-%d5/%a0-%a2
-       lea     %sp@(32),%sp            /* space for 8 regs */
-       movel   %sp@+,%d0
-       addql   #4,%sp                  /* orig d0 */
-       addl    %sp@+,%sp               /* stk adj */
-       addql   #8,%sp                  /* remove exception */
-       movel   %sp,sw_ksp              /* save ksp */
-       subql   #8,sw_usp               /* set exception */
-       movel   sw_usp,%sp              /* restore usp */
-       rte
+       RESTORE_USER
 
 Lwork_to_do:
        movel   %a0@(TI_FLAGS),%d1      /* get thread_info->flags */
@@ -201,9 +192,8 @@ ENTRY(inthandler)
  */
 ENTRY(resume)
        movel   %a0, %d1                        /* get prev thread in d1 */
-
-       movel   sw_usp,%d0                      /* save usp */
-       movel   %d0,%a0@(TASK_THREAD+THREAD_USP)
+       RDUSP
+       movel   %a2,%a0@(TASK_THREAD+THREAD_USP)
 
        SAVE_SWITCH_STACK
        movel   %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
@@ -211,5 +201,5 @@ ENTRY(resume)
        RESTORE_SWITCH_STACK
 
        movel   %a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
-       movel   %a0, sw_usp
+       WRUSP
        rts