[PATCH 3.10 79/97] xtensa: introduce spill_registers_kernel macro
3.10-stable review patch. If anyone has any objections, please let me know. -- From: Max Filippov commit e2fd1374c705abe4661df3fb6fadb3879c7c1846 upstream. Most in-kernel users want registers spilled on the kernel stack and don't require PS.EXCM to be set. That means that they don't need fixup routine and could reuse regular window overflow mechanism for that, which makes spill routine very simple. Suggested-by: Chris Zankel Signed-off-by: Max Filippov Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/include/asm/traps.h | 44 ++--- arch/xtensa/kernel/entry.S | 60 2 files changed, 76 insertions(+), 28 deletions(-) --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h @@ -22,25 +22,37 @@ extern void do_unhandled(struct pt_regs static inline void spill_registers(void) { - +#if XCHAL_NUM_AREGS > 16 __asm__ __volatile__ ( - "movi a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t" - "mova12, a0\n\t" - "rsra13, sar\n\t" - "xsra14, ps\n\t" - "movi a0, _spill_registers\n\t" - "rsync\n\t" - "callx0 a0\n\t" - "mova0, a12\n\t" - "wsra13, sar\n\t" - "wsra14, ps\n\t" - : : -#if defined(CONFIG_FRAME_POINTER) - : "a2", "a3", "a4", "a11", "a12", "a13", "a14", "a15", + " call12 1f\n" + " _j 2f\n" + " retw\n" + " .align 4\n" + "1:\n" + " _entry a1, 48\n" + " addia12, a0, 3\n" +#if XCHAL_NUM_AREGS > 32 + " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n" + " _entry a1, 48\n" + " mov a12, a0\n" + " .endr\n" +#endif + " _entry a1, 48\n" +#if XCHAL_NUM_AREGS % 12 == 0 + " mov a8, a8\n" +#elif XCHAL_NUM_AREGS % 12 == 4 + " mov a12, a12\n" +#elif XCHAL_NUM_AREGS % 12 == 8 + " mov a4, a4\n" +#endif + " retw\n" + "2:\n" + : : : "a12", "a13", "memory"); #else - : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", + __asm__ __volatile__ ( + " mov a12, a12\n" + : : : "memory"); #endif - "memory"); } #endif /* _XTENSA_TRAPS_H */ --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1912,6 +1912,43 @@ ENTRY(system_call) ENDPROC(system_call) +/* + * Spill live registers on the kernel stack macro. + * + * Entry condition: ps.woe is set, ps.excm is cleared + * Exit condition: windowstart has single bit set + * May clobber: a12, a13 + */ + .macro spill_registers_kernel + +#if XCHAL_NUM_AREGS > 16 + call12 1f + _j 2f + retw + .align 4 +1: + _entry a1, 48 + addia12, a0, 3 +#if XCHAL_NUM_AREGS > 32 + .rept (XCHAL_NUM_AREGS - 32) / 12 + _entry a1, 48 + mov a12, a0 + .endr +#endif + _entry a1, 48 +#if XCHAL_NUM_AREGS % 12 == 0 + mov a8, a8 +#elif XCHAL_NUM_AREGS % 12 == 4 + mov a12, a12 +#elif XCHAL_NUM_AREGS % 12 == 8 + mov a4, a4 +#endif + retw +2: +#else + mov a12, a12 +#endif + .endm /* * Task switch. @@ -1924,21 +1961,20 @@ ENTRY(_switch_to) entry a1, 16 - mov a12, a2 # preserve 'prev' (a2) - mov a13, a3 # and 'next' (a3) + mov a10, a2 # preserve 'prev' (a2) + mov a11, a3 # and 'next' (a3) l32ia4, a2, TASK_THREAD_INFO l32ia5, a3, TASK_THREAD_INFO - save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER + save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER - s32ia0, a12, THREAD_RA # save return address - s32ia1, a12, THREAD_SP # save stack pointer + s32ia0, a10, THREAD_RA # save return address + s32ia1, a10, THREAD_SP # save stack pointer /* Disable ints while we manipulate the stack pointer. */ - movia14, (1 << PS_EXCM_BIT) | LOCKLEVEL - xsr a14, ps + rsila14, LOCKLEVEL rsr a3, excsave1 rsync s32ia3, a3, EXC_TABLE_FIXUP /* enter critical section */ @@ -1953,7 +1989,7 @@ ENTRY(_switch_to) /* Flush register file. */ - call0 _spill_registers# destroys a3, a4, and SAR + spill_registers_kernel /* Set kernel stack (and leave critical section) * Note: It's save to set it here. The stack will not be overwritten @@ -1969,13 +2005,13 @@
[PATCH 3.10 79/97] xtensa: introduce spill_registers_kernel macro
3.10-stable review patch. If anyone has any objections, please let me know. -- From: Max Filippov jcmvb...@gmail.com commit e2fd1374c705abe4661df3fb6fadb3879c7c1846 upstream. Most in-kernel users want registers spilled on the kernel stack and don't require PS.EXCM to be set. That means that they don't need fixup routine and could reuse regular window overflow mechanism for that, which makes spill routine very simple. Suggested-by: Chris Zankel ch...@zankel.net Signed-off-by: Max Filippov jcmvb...@gmail.com Signed-off-by: Greg Kroah-Hartman gre...@linuxfoundation.org --- arch/xtensa/include/asm/traps.h | 44 ++--- arch/xtensa/kernel/entry.S | 60 2 files changed, 76 insertions(+), 28 deletions(-) --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h @@ -22,25 +22,37 @@ extern void do_unhandled(struct pt_regs static inline void spill_registers(void) { - +#if XCHAL_NUM_AREGS 16 __asm__ __volatile__ ( - movi a14, __stringify((1 PS_EXCM_BIT) | LOCKLEVEL)\n\t - mova12, a0\n\t - rsra13, sar\n\t - xsra14, ps\n\t - movi a0, _spill_registers\n\t - rsync\n\t - callx0 a0\n\t - mova0, a12\n\t - wsra13, sar\n\t - wsra14, ps\n\t - : : -#if defined(CONFIG_FRAME_POINTER) - : a2, a3, a4, a11, a12, a13, a14, a15, + call12 1f\n + _j 2f\n + retw\n + .align 4\n + 1:\n + _entry a1, 48\n + addia12, a0, 3\n +#if XCHAL_NUM_AREGS 32 + .rept ( __stringify(XCHAL_NUM_AREGS) - 32) / 12\n + _entry a1, 48\n + mov a12, a0\n + .endr\n +#endif + _entry a1, 48\n +#if XCHAL_NUM_AREGS % 12 == 0 + mov a8, a8\n +#elif XCHAL_NUM_AREGS % 12 == 4 + mov a12, a12\n +#elif XCHAL_NUM_AREGS % 12 == 8 + mov a4, a4\n +#endif + retw\n + 2:\n + : : : a12, a13, memory); #else - : a2, a3, a4, a7, a11, a12, a13, a14, a15, + __asm__ __volatile__ ( + mov a12, a12\n + : : : memory); #endif - memory); } #endif /* _XTENSA_TRAPS_H */ --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1912,6 +1912,43 @@ ENTRY(system_call) ENDPROC(system_call) +/* + * Spill live registers on the kernel stack macro. + * + * Entry condition: ps.woe is set, ps.excm is cleared + * Exit condition: windowstart has single bit set + * May clobber: a12, a13 + */ + .macro spill_registers_kernel + +#if XCHAL_NUM_AREGS 16 + call12 1f + _j 2f + retw + .align 4 +1: + _entry a1, 48 + addia12, a0, 3 +#if XCHAL_NUM_AREGS 32 + .rept (XCHAL_NUM_AREGS - 32) / 12 + _entry a1, 48 + mov a12, a0 + .endr +#endif + _entry a1, 48 +#if XCHAL_NUM_AREGS % 12 == 0 + mov a8, a8 +#elif XCHAL_NUM_AREGS % 12 == 4 + mov a12, a12 +#elif XCHAL_NUM_AREGS % 12 == 8 + mov a4, a4 +#endif + retw +2: +#else + mov a12, a12 +#endif + .endm /* * Task switch. @@ -1924,21 +1961,20 @@ ENTRY(_switch_to) entry a1, 16 - mov a12, a2 # preserve 'prev' (a2) - mov a13, a3 # and 'next' (a3) + mov a10, a2 # preserve 'prev' (a2) + mov a11, a3 # and 'next' (a3) l32ia4, a2, TASK_THREAD_INFO l32ia5, a3, TASK_THREAD_INFO - save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER + save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER - s32ia0, a12, THREAD_RA # save return address - s32ia1, a12, THREAD_SP # save stack pointer + s32ia0, a10, THREAD_RA # save return address + s32ia1, a10, THREAD_SP # save stack pointer /* Disable ints while we manipulate the stack pointer. */ - movia14, (1 PS_EXCM_BIT) | LOCKLEVEL - xsr a14, ps + rsila14, LOCKLEVEL rsr a3, excsave1 rsync s32ia3, a3, EXC_TABLE_FIXUP /* enter critical section */ @@ -1953,7 +1989,7 @@ ENTRY(_switch_to) /* Flush register file. */ - call0 _spill_registers# destroys a3, a4, and SAR + spill_registers_kernel /* Set kernel stack (and leave critical section) * Note: It's save to set it here. The stack will not be overwritten @@ -1969,13 +2005,13 @@ ENTRY(_switch_to) /*