aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2014-01-21 23:04:43 -0500
committerMax Filippov <jcmvbkbc@gmail.com>2014-01-25 14:20:09 -0500
commite2fd1374c705abe4661df3fb6fadb3879c7c1846 (patch)
treea29a6a43d3ae01253fe706a7dcd594afee388605
parent45ec8860be2f681b2e3e521a3fb4554ec29fbaac (diff)
xtensa: introduce spill_registers_kernel macro
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. Cc: stable@vger.kernel.org Suggested-by: Chris Zankel <chris@zankel.net> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r--arch/xtensa/include/asm/traps.h44
-rw-r--r--arch/xtensa/kernel/entry.S60
2 files changed, 76 insertions, 28 deletions
diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h
index 8c194f6af45e..677bfcf4ee5d 100644
--- a/arch/xtensa/include/asm/traps.h
+++ b/arch/xtensa/include/asm/traps.h
@@ -23,25 +23,37 @@ void secondary_trap_init(void);
23 23
24static inline void spill_registers(void) 24static inline void spill_registers(void)
25{ 25{
26 26#if XCHAL_NUM_AREGS > 16
27 __asm__ __volatile__ ( 27 __asm__ __volatile__ (
28 "movi a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t" 28 " call12 1f\n"
29 "mov a12, a0\n\t" 29 " _j 2f\n"
30 "rsr a13, sar\n\t" 30 " retw\n"
31 "xsr a14, ps\n\t" 31 " .align 4\n"
32 "movi a0, _spill_registers\n\t" 32 "1:\n"
33 "rsync\n\t" 33 " _entry a1, 48\n"
34 "callx0 a0\n\t" 34 " addi a12, a0, 3\n"
35 "mov a0, a12\n\t" 35#if XCHAL_NUM_AREGS > 32
36 "wsr a13, sar\n\t" 36 " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
37 "wsr a14, ps\n\t" 37 " _entry a1, 48\n"
38 : : 38 " mov a12, a0\n"
39#if defined(CONFIG_FRAME_POINTER) 39 " .endr\n"
40 : "a2", "a3", "a4", "a11", "a12", "a13", "a14", "a15", 40#endif
41 " _entry a1, 48\n"
42#if XCHAL_NUM_AREGS % 12 == 0
43 " mov a8, a8\n"
44#elif XCHAL_NUM_AREGS % 12 == 4
45 " mov a12, a12\n"
46#elif XCHAL_NUM_AREGS % 12 == 8
47 " mov a4, a4\n"
48#endif
49 " retw\n"
50 "2:\n"
51 : : : "a12", "a13", "memory");
41#else 52#else
42 : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", 53 __asm__ __volatile__ (
54 " mov a12, a12\n"
55 : : : "memory");
43#endif 56#endif
44 "memory");
45} 57}
46 58
47#endif /* _XTENSA_TRAPS_H */ 59#endif /* _XTENSA_TRAPS_H */
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 21dbe6bdb8ed..0489918e40d2 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1794,6 +1794,43 @@ ENTRY(system_call)
1794 1794
1795ENDPROC(system_call) 1795ENDPROC(system_call)
1796 1796
1797/*
1798 * Spill live registers on the kernel stack macro.
1799 *
1800 * Entry condition: ps.woe is set, ps.excm is cleared
1801 * Exit condition: windowstart has single bit set
1802 * May clobber: a12, a13
1803 */
1804 .macro spill_registers_kernel
1805
1806#if XCHAL_NUM_AREGS > 16
1807 call12 1f
1808 _j 2f
1809 retw
1810 .align 4
18111:
1812 _entry a1, 48
1813 addi a12, a0, 3
1814#if XCHAL_NUM_AREGS > 32
1815 .rept (XCHAL_NUM_AREGS - 32) / 12
1816 _entry a1, 48
1817 mov a12, a0
1818 .endr
1819#endif
1820 _entry a1, 48
1821#if XCHAL_NUM_AREGS % 12 == 0
1822 mov a8, a8
1823#elif XCHAL_NUM_AREGS % 12 == 4
1824 mov a12, a12
1825#elif XCHAL_NUM_AREGS % 12 == 8
1826 mov a4, a4
1827#endif
1828 retw
18292:
1830#else
1831 mov a12, a12
1832#endif
1833 .endm
1797 1834
1798/* 1835/*
1799 * Task switch. 1836 * Task switch.
@@ -1806,21 +1843,20 @@ ENTRY(_switch_to)
1806 1843
1807 entry a1, 16 1844 entry a1, 16
1808 1845
1809 mov a12, a2 # preserve 'prev' (a2) 1846 mov a10, a2 # preserve 'prev' (a2)
1810 mov a13, a3 # and 'next' (a3) 1847 mov a11, a3 # and 'next' (a3)
1811 1848
1812 l32i a4, a2, TASK_THREAD_INFO 1849 l32i a4, a2, TASK_THREAD_INFO
1813 l32i a5, a3, TASK_THREAD_INFO 1850 l32i a5, a3, TASK_THREAD_INFO
1814 1851
1815 save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER 1852 save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
1816 1853
1817 s32i a0, a12, THREAD_RA # save return address 1854 s32i a0, a10, THREAD_RA # save return address
1818 s32i a1, a12, THREAD_SP # save stack pointer 1855 s32i a1, a10, THREAD_SP # save stack pointer
1819 1856
1820 /* Disable ints while we manipulate the stack pointer. */ 1857 /* Disable ints while we manipulate the stack pointer. */
1821 1858
1822 movi a14, (1 << PS_EXCM_BIT) | LOCKLEVEL 1859 rsil a14, LOCKLEVEL
1823 xsr a14, ps
1824 rsr a3, excsave1 1860 rsr a3, excsave1
1825 rsync 1861 rsync
1826 s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */ 1862 s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */
@@ -1835,7 +1871,7 @@ ENTRY(_switch_to)
1835 1871
1836 /* Flush register file. */ 1872 /* Flush register file. */
1837 1873
1838 call0 _spill_registers # destroys a3, a4, and SAR 1874 spill_registers_kernel
1839 1875
1840 /* Set kernel stack (and leave critical section) 1876 /* Set kernel stack (and leave critical section)
1841 * Note: It's save to set it here. The stack will not be overwritten 1877 * Note: It's save to set it here. The stack will not be overwritten
@@ -1851,13 +1887,13 @@ ENTRY(_switch_to)
1851 1887
1852 /* restore context of the task 'next' */ 1888 /* restore context of the task 'next' */
1853 1889
1854 l32i a0, a13, THREAD_RA # restore return address 1890 l32i a0, a11, THREAD_RA # restore return address
1855 l32i a1, a13, THREAD_SP # restore stack pointer 1891 l32i a1, a11, THREAD_SP # restore stack pointer
1856 1892
1857 load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER 1893 load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
1858 1894
1859 wsr a14, ps 1895 wsr a14, ps
1860 mov a2, a12 # return 'prev' 1896 mov a2, a10 # return 'prev'
1861 rsync 1897 rsync
1862 1898
1863 retw 1899 retw