Hi All, This is a request for testing (and comment) on a patch that will use the separate kernel/user stack pointer hardware that the more modern ColdFire cores have. This has a performance benefit when used, the exception entry and exit paths are quite a few instructions shorter.
Currently the parts I know can use it are the 520[78], 523x, 527[12], 527[45], 523x (and 547x/548x). The use of the separate stack pointer is based on a config option (CONFIG_COLDFIRE_SW_A7) that is automatically selected based on ColdFure CPU selection. This may well not be the best way to do this. Maybe the selection should be based on the compiler define __mcfisaaplus__. I didn't use this because only more modern toolchains support it. My 4.2.4 based toolchain doesn't. The older toolchain also required one more ugly hack. Pre 4.3 gcc won't generate the "move usp" instructions required for this when compiling for ColdFire. So I have had to hard code the opcode values in place for these instructions for now. Maybe we need to bite the bullet and just not support this using older toolchains... Thoughts? The patch below is against 2.6.36. If you prefer living on the edge, you can pull this from from the for-linus branch of ther m68knommu git tree (along with a bunch of other updates): git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git for-linus Regards Greg --- [PATCH] m68knommu: use user stack pointer hardware on some ColdFire cores 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 <g...@uclinux.org> --- m68k/include/asm/cacheflush_no.h | 4 +- m68k/include/asm/entry_no.h | 59 ++++++++++++++++++++---------------- m68k/include/asm/mcfcache.h | 6 +-- m68k/include/asm/processor.h | 13 ++++--- m68knommu/Kconfig | 11 ++++++ m68knommu/platform/coldfire/entry.S | 56 ++++++---------------------------- 6 files changed, 68 insertions(+), 81 deletions(-) diff -Naurp linux-2.6.36/arch/m68k/include/asm/cacheflush_no.h linux-2.6.36.eusp/arch/m68k/include/asm/cacheflush_no.h --- linux-2.6.36/arch/m68k/include/asm/cacheflush_no.h 2010-10-21 06:30:22.000000000 +1000 +++ linux-2.6.36.eusp/arch/m68k/include/asm/cacheflush_no.h 2010-11-04 14:32:46.491869598 +1000 @@ -54,7 +54,7 @@ static inline void __flush_cache_all(voi #endif /* CONFIG_M5407 */ #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" ); @@ -82,7 +82,7 @@ static inline void __flush_cache_all(voi #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" ); diff -Naurp linux-2.6.36/arch/m68k/include/asm/entry_no.h linux-2.6.36.eusp/arch/m68k/include/asm/entry_no.h --- linux-2.6.36/arch/m68k/include/asm/entry_no.h 2010-10-21 06:30:22.000000000 +1000 +++ linux-2.6.36.eusp/arch/m68k/include/asm/entry_no.h 2010-11-04 14:32:46.491869598 +1000 @@ -52,12 +52,16 @@ LENOSYS = 38 */ #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? */ @@ -84,9 +88,7 @@ LENOSYS = 38 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),%...@- /* copy exception program counter */ @@ -101,19 +103,22 @@ LENOSYS = 38 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 %...@+,%d0 - addql #4,%sp /* orig d0 */ - addl %...@+,%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 %...@- /* stkadj */ movel %d0,%...@- /* orig d0 */ @@ -122,7 +127,7 @@ LENOSYS = 38 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 %...@+,%d0 @@ -131,6 +136,18 @@ LENOSYS = 38 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@ @@ -141,14 +158,6 @@ LENOSYS = 38 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 */ /* @@ -177,6 +186,6 @@ LENOSYS = 38 moveml %...@+,%a3-%a6/%d6-%d7 .endm -#endif /* !CONFIG_COLDFIRE */ +#endif /* !COLDFIRE_SW_A7 */ #endif /* __ASSEMBLY__ */ #endif /* __M68KNOMMU_ENTRY_H */ diff -Naurp linux-2.6.36/arch/m68k/include/asm/mcfcache.h linux-2.6.36.eusp/arch/m68k/include/asm/mcfcache.h --- linux-2.6.36/arch/m68k/include/asm/mcfcache.h 2010-10-21 06:30:22.000000000 +1000 +++ linux-2.6.36.eusp/arch/m68k/include/asm/mcfcache.h 2010-11-04 14:32:46.491869598 +1000 @@ -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 @@ -101,7 +101,7 @@ 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 @@ -140,7 +140,7 @@ 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 diff -Naurp linux-2.6.36/arch/m68k/include/asm/processor.h linux-2.6.36.eusp/arch/m68k/include/asm/processor.h --- linux-2.6.36/arch/m68k/include/asm/processor.h 2010-10-21 06:30:22.000000000 +1000 +++ linux-2.6.36.eusp/arch/m68k/include/asm/processor.h 2010-11-04 14:32:46.491869598 +1000 @@ -20,23 +20,26 @@ 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 } diff -Naurp linux-2.6.36/arch/m68knommu/Kconfig linux-2.6.36.eusp/arch/m68knommu/Kconfig --- linux-2.6.36/arch/m68knommu/Kconfig 2010-10-21 06:30:22.000000000 +1000 +++ linux-2.6.36.eusp/arch/m68knommu/Kconfig 2010-11-04 14:32:46.491869598 +1000 @@ -78,6 +78,10 @@ config GENERIC_CLOCKEVENTS config NO_IOPORT def_bool y +config COLDFIRE_SW_A7 + bool + default n + source "init/Kconfig" source "kernel/Kconfig.freezer" @@ -110,11 +114,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. @@ -132,6 +138,7 @@ config M523x config M5249 bool "MCF5249" + select COLDFIRE_SW_A7 help Motorola ColdFire 5249 processor support. @@ -142,6 +149,7 @@ config M5271 config M5272 bool "MCF5272" + select COLDFIRE_SW_A7 help Motorola ColdFire 5272 processor support. @@ -152,12 +160,14 @@ config M5275 config M528x bool "MCF528x" + select COLDFIRE_SW_A7 select GENERIC_CLOCKEVENTS help Motorola ColdFire 5280/5282 processor support. config M5307 bool "MCF5307" + select COLDFIRE_SW_A7 help Motorola ColdFire 5307 processor support. @@ -168,6 +178,7 @@ config M532x config M5407 bool "MCF5407" + select COLDFIRE_SW_A7 help Motorola ColdFire 5407 processor support. diff -Naurp linux-2.6.36/arch/m68knommu/platform/coldfire/entry.S linux-2.6.36.eusp/arch/m68knommu/platform/coldfire/entry.S --- linux-2.6.36/arch/m68knommu/platform/coldfire/entry.S 2010-10-21 06:30:22.000000000 +1000 +++ linux-2.6.36.eusp/arch/m68knommu/platform/coldfire/entry.S 2010-11-04 14:36:40.132706032 +1000 @@ -36,13 +36,16 @@ #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 @@ -51,7 +54,6 @@ sw_usp: .globl ret_from_exception .globl ret_from_signal .globl sys_call_table -.globl ret_from_interrupt .globl inthandler .globl fasthandler @@ -140,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),%...@- /* copy exception program counter */ - movel %sp@(PT_OFF_FORMATVEC),%...@- /* copy exception format/vector/sr */ - moveml %sp@,%d1-%d5/%a0-%a2 - lea %sp@(32),%sp /* space for 8 regs */ - movel %...@+,%d0 - addql #4,%sp /* orig d0 */ - addl %...@+,%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 */ @@ -192,31 +181,7 @@ ENTRY(inthandler) jbsr do_IRQ /* call high level irq handler */ lea %sp@(8),%sp /* pop args off stack */ - bra ret_from_interrupt /* this was fallthrough */ - -/* - * This is the fast interrupt handler (for certain hardware interrupt - * sources). Unlike the normal interrupt handler it just uses the - * current stack (doesn't care if it is user or kernel). It also - * doesn't bother doing the bottom half handlers. - */ -ENTRY(fasthandler) - SAVE_LOCAL - - movew %sp@(PT_OFF_FORMATVEC),%d0 - andl #0x03fc,%d0 /* mask out vector only */ - - movel %sp,%...@- /* push regs arg */ - lsrl #2,%d0 /* calculate real vector # */ - movel %d0,%...@- /* push vector number */ - jbsr do_IRQ /* call high level irq handler */ - lea %sp@(8),%sp /* pop args off stack */ - - RESTORE_LOCAL - -ENTRY(ret_from_interrupt) - /* the fasthandler is confusing me, haven't seen any user */ - jmp ret_from_exception + bra ret_from_exception /* * Beware - when entering resume, prev (the current task) is @@ -227,9 +192,8 @@ ENTRY(ret_from_interrupt) */ 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 */ @@ -237,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 _______________________________________________ uClinux-dev mailing list uClinux-dev@uclinux.org http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by uclinux-dev@uclinux.org To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev