aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel/entry.S
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2013-10-14 18:22:42 -0400
committerChris Zankel <chris@zankel.net>2013-10-15 16:39:06 -0400
commit244066f4be8ce2dc2d2d60f01bceeba55c71a783 (patch)
treea1a266f7ae41b3418a1f858712c52ba3cf141100 /arch/xtensa/kernel/entry.S
parent61e6cfa80de5760bbe406f4e815b7739205754d2 (diff)
xtensa: fix fast_syscall_spill_registers_fixup
fast_syscall_spill_registers_fixup was not correctly updated by the 'keep a3 and excsave1 on entry to exception handlers' patch: it doesn't preserve a3 that it gets on entry, breaking _spill_registers in case of page fault on stack during register spilling, leading to unhandled exception in kernel mode. Preserve a3 by saving it in the original _spill_registers stack frame's a3 during exception handling and restoring it afterwards. Also fix comments and function bounds annotations. Reported-by: Baruch Siach <baruch@tkos.co.il> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Tested-by: Baruch Siach <baruch@tkos.co.il> Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'arch/xtensa/kernel/entry.S')
-rw-r--r--arch/xtensa/kernel/entry.S49
1 files changed, 30 insertions, 19 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index de1dfa18d0a1..21dbe6bdb8ed 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1122,7 +1122,7 @@ ENDPROC(fast_syscall_spill_registers)
1122 * a3: exctable, original value in excsave1 1122 * a3: exctable, original value in excsave1
1123 */ 1123 */
1124 1124
1125fast_syscall_spill_registers_fixup: 1125ENTRY(fast_syscall_spill_registers_fixup)
1126 1126
1127 rsr a2, windowbase # get current windowbase (a2 is saved) 1127 rsr a2, windowbase # get current windowbase (a2 is saved)
1128 xsr a0, depc # restore depc and a0 1128 xsr a0, depc # restore depc and a0
@@ -1134,22 +1134,26 @@ fast_syscall_spill_registers_fixup:
1134 */ 1134 */
1135 1135
1136 xsr a3, excsave1 # get spill-mask 1136 xsr a3, excsave1 # get spill-mask
1137 slli a2, a3, 1 # shift left by one 1137 slli a3, a3, 1 # shift left by one
1138 1138
1139 slli a3, a2, 32-WSBITS 1139 slli a2, a3, 32-WSBITS
1140 src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy...... 1140 src a2, a3, a2 # a2 = xxwww1yyxxxwww1yy......
1141 wsr a2, windowstart # set corrected windowstart 1141 wsr a2, windowstart # set corrected windowstart
1142 1142
1143 rsr a3, excsave1 1143 srli a3, a3, 1
1144 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2 1144 rsr a2, excsave1
1145 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task) 1145 l32i a2, a2, EXC_TABLE_DOUBLE_SAVE # restore a2
1146 xsr a2, excsave1
1147 s32i a3, a2, EXC_TABLE_DOUBLE_SAVE # save a3
1148 l32i a3, a2, EXC_TABLE_PARAM # original WB (in user task)
1149 xsr a2, excsave1
1146 1150
1147 /* Return to the original (user task) WINDOWBASE. 1151 /* Return to the original (user task) WINDOWBASE.
1148 * We leave the following frame behind: 1152 * We leave the following frame behind:
1149 * a0, a1, a2 same 1153 * a0, a1, a2 same
1150 * a3: trashed (saved in excsave_1) 1154 * a3: trashed (saved in EXC_TABLE_DOUBLE_SAVE)
1151 * depc: depc (we have to return to that address) 1155 * depc: depc (we have to return to that address)
1152 * excsave_1: a3 1156 * excsave_1: exctable
1153 */ 1157 */
1154 1158
1155 wsr a3, windowbase 1159 wsr a3, windowbase
@@ -1159,9 +1163,9 @@ fast_syscall_spill_registers_fixup:
1159 * a0: return address 1163 * a0: return address
1160 * a1: used, stack pointer 1164 * a1: used, stack pointer
1161 * a2: kernel stack pointer 1165 * a2: kernel stack pointer
1162 * a3: available, saved in EXCSAVE_1 1166 * a3: available
1163 * depc: exception address 1167 * depc: exception address
1164 * excsave: a3 1168 * excsave: exctable
1165 * Note: This frame might be the same as above. 1169 * Note: This frame might be the same as above.
1166 */ 1170 */
1167 1171
@@ -1181,9 +1185,12 @@ fast_syscall_spill_registers_fixup:
1181 rsr a0, exccause 1185 rsr a0, exccause
1182 addx4 a0, a0, a3 # find entry in table 1186 addx4 a0, a0, a3 # find entry in table
1183 l32i a0, a0, EXC_TABLE_FAST_USER # load handler 1187 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
1188 l32i a3, a3, EXC_TABLE_DOUBLE_SAVE
1184 jx a0 1189 jx a0
1185 1190
1186fast_syscall_spill_registers_fixup_return: 1191ENDPROC(fast_syscall_spill_registers_fixup)
1192
1193ENTRY(fast_syscall_spill_registers_fixup_return)
1187 1194
1188 /* When we return here, all registers have been restored (a2: DEPC) */ 1195 /* When we return here, all registers have been restored (a2: DEPC) */
1189 1196
@@ -1191,13 +1198,13 @@ fast_syscall_spill_registers_fixup_return:
1191 1198
1192 /* Restore fixup handler. */ 1199 /* Restore fixup handler. */
1193 1200
1194 xsr a3, excsave1 1201 rsr a2, excsave1
1195 movi a2, fast_syscall_spill_registers_fixup 1202 s32i a3, a2, EXC_TABLE_DOUBLE_SAVE
1196 s32i a2, a3, EXC_TABLE_FIXUP 1203 movi a3, fast_syscall_spill_registers_fixup
1197 s32i a0, a3, EXC_TABLE_DOUBLE_SAVE 1204 s32i a3, a2, EXC_TABLE_FIXUP
1198 rsr a2, windowbase 1205 rsr a3, windowbase
1199 s32i a2, a3, EXC_TABLE_PARAM 1206 s32i a3, a2, EXC_TABLE_PARAM
1200 l32i a2, a3, EXC_TABLE_KSTK 1207 l32i a2, a2, EXC_TABLE_KSTK
1201 1208
1202 /* Load WB at the time the exception occurred. */ 1209 /* Load WB at the time the exception occurred. */
1203 1210
@@ -1206,8 +1213,12 @@ fast_syscall_spill_registers_fixup_return:
1206 wsr a3, windowbase 1213 wsr a3, windowbase
1207 rsync 1214 rsync
1208 1215
1216 rsr a3, excsave1
1217 l32i a3, a3, EXC_TABLE_DOUBLE_SAVE
1218
1209 rfde 1219 rfde
1210 1220
1221ENDPROC(fast_syscall_spill_registers_fixup_return)
1211 1222
1212/* 1223/*
1213 * spill all registers. 1224 * spill all registers.