aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa')
-rw-r--r--arch/xtensa/include/asm/regs.h1
-rw-r--r--arch/xtensa/kernel/align.S5
-rw-r--r--arch/xtensa/kernel/coprocessor.S9
-rw-r--r--arch/xtensa/kernel/entry.S115
-rw-r--r--arch/xtensa/kernel/vectors.S250
5 files changed, 238 insertions, 142 deletions
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
index b24de6717020..4ba9f516b0e2 100644
--- a/arch/xtensa/include/asm/regs.h
+++ b/arch/xtensa/include/asm/regs.h
@@ -82,6 +82,7 @@
82#define PS_CALLINC_SHIFT 16 82#define PS_CALLINC_SHIFT 16
83#define PS_CALLINC_MASK 0x00030000 83#define PS_CALLINC_MASK 0x00030000
84#define PS_OWB_SHIFT 8 84#define PS_OWB_SHIFT 8
85#define PS_OWB_WIDTH 4
85#define PS_OWB_MASK 0x00000F00 86#define PS_OWB_MASK 0x00000F00
86#define PS_RING_SHIFT 6 87#define PS_RING_SHIFT 6
87#define PS_RING_MASK 0x000000C0 88#define PS_RING_MASK 0x000000C0
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
index aa2e87b8566a..d4cef6039a5c 100644
--- a/arch/xtensa/kernel/align.S
+++ b/arch/xtensa/kernel/align.S
@@ -146,9 +146,9 @@
146 * a0: trashed, original value saved on stack (PT_AREG0) 146 * a0: trashed, original value saved on stack (PT_AREG0)
147 * a1: a1 147 * a1: a1
148 * a2: new stack pointer, original in DEPC 148 * a2: new stack pointer, original in DEPC
149 * a3: dispatch table 149 * a3: a3
150 * depc: a2, original value saved on stack (PT_DEPC) 150 * depc: a2, original value saved on stack (PT_DEPC)
151 * excsave_1: a3 151 * excsave_1: dispatch table
152 * 152 *
153 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 153 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
154 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 154 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -171,7 +171,6 @@ ENTRY(fast_unaligned)
171 s32i a8, a2, PT_AREG8 171 s32i a8, a2, PT_AREG8
172 172
173 rsr a0, depc 173 rsr a0, depc
174 xsr a3, excsave1
175 s32i a0, a2, PT_AREG2 174 s32i a0, a2, PT_AREG2
176 s32i a3, a2, PT_AREG3 175 s32i a3, a2, PT_AREG3
177 176
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index 647657484866..a482df5df2b2 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -32,9 +32,9 @@
32 * a0: trashed, original value saved on stack (PT_AREG0) 32 * a0: trashed, original value saved on stack (PT_AREG0)
33 * a1: a1 33 * a1: a1
34 * a2: new stack pointer, original in DEPC 34 * a2: new stack pointer, original in DEPC
35 * a3: dispatch table 35 * a3: a3
36 * depc: a2, original value saved on stack (PT_DEPC) 36 * depc: a2, original value saved on stack (PT_DEPC)
37 * excsave_1: a3 37 * excsave_1: dispatch table
38 * 38 *
39 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 39 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
40 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 40 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -225,9 +225,9 @@ ENDPROC(coprocessor_restore)
225 * a0: trashed, original value saved on stack (PT_AREG0) 225 * a0: trashed, original value saved on stack (PT_AREG0)
226 * a1: a1 226 * a1: a1
227 * a2: new stack pointer, original in DEPC 227 * a2: new stack pointer, original in DEPC
228 * a3: dispatch table 228 * a3: a3
229 * depc: a2, original value saved on stack (PT_DEPC) 229 * depc: a2, original value saved on stack (PT_DEPC)
230 * excsave_1: a3 230 * excsave_1: dispatch table
231 * 231 *
232 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 232 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
233 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 233 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -245,7 +245,6 @@ ENTRY(fast_coprocessor)
245 245
246 /* Save remaining registers a1-a3 and SAR */ 246 /* Save remaining registers a1-a3 and SAR */
247 247
248 xsr a3, excsave1
249 s32i a3, a2, PT_AREG3 248 s32i a3, a2, PT_AREG3
250 rsr a3, sar 249 rsr a3, sar
251 s32i a1, a2, PT_AREG1 250 s32i a1, a2, PT_AREG1
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 3f3de283d707..ab025c1f6e23 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -91,9 +91,9 @@
91 * a0: trashed, original value saved on stack (PT_AREG0) 91 * a0: trashed, original value saved on stack (PT_AREG0)
92 * a1: a1 92 * a1: a1
93 * a2: new stack pointer, original value in depc 93 * a2: new stack pointer, original value in depc
94 * a3: dispatch table 94 * a3: a3
95 * depc: a2, original value saved on stack (PT_DEPC) 95 * depc: a2, original value saved on stack (PT_DEPC)
96 * excsave1: a3 96 * excsave1: dispatch table
97 * 97 *
98 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 98 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
99 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 99 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -109,9 +109,8 @@
109 109
110ENTRY(user_exception) 110ENTRY(user_exception)
111 111
112 /* Save a2, a3, and depc, restore excsave_1 and set SP. */ 112 /* Save a1, a2, a3, and set SP. */
113 113
114 xsr a3, excsave1
115 rsr a0, depc 114 rsr a0, depc
116 s32i a1, a2, PT_AREG1 115 s32i a1, a2, PT_AREG1
117 s32i a0, a2, PT_AREG2 116 s32i a0, a2, PT_AREG2
@@ -237,9 +236,9 @@ ENDPROC(user_exception)
237 * a0: trashed, original value saved on stack (PT_AREG0) 236 * a0: trashed, original value saved on stack (PT_AREG0)
238 * a1: a1 237 * a1: a1
239 * a2: new stack pointer, original in DEPC 238 * a2: new stack pointer, original in DEPC
240 * a3: dispatch table 239 * a3: a3
241 * depc: a2, original value saved on stack (PT_DEPC) 240 * depc: a2, original value saved on stack (PT_DEPC)
242 * excsave_1: a3 241 * excsave_1: dispatch table
243 * 242 *
244 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 243 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
245 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 244 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -255,9 +254,8 @@ ENDPROC(user_exception)
255 254
256ENTRY(kernel_exception) 255ENTRY(kernel_exception)
257 256
258 /* Save a0, a2, a3, DEPC and set SP. */ 257 /* Save a1, a2, a3, and set SP. */
259 258
260 xsr a3, excsave1 # restore a3, excsave_1
261 rsr a0, depc # get a2 259 rsr a0, depc # get a2
262 s32i a1, a2, PT_AREG1 260 s32i a1, a2, PT_AREG1
263 s32i a0, a2, PT_AREG2 261 s32i a0, a2, PT_AREG2
@@ -408,7 +406,7 @@ common_exception:
408 * exception handler and call the exception handler. 406 * exception handler and call the exception handler.
409 */ 407 */
410 408
411 movi a4, exc_table 409 rsr a4, excsave1
412 mov a6, a1 # pass stack frame 410 mov a6, a1 # pass stack frame
413 mov a7, a0 # pass EXCCAUSE 411 mov a7, a0 # pass EXCCAUSE
414 addx4 a4, a0, a4 412 addx4 a4, a0, a4
@@ -832,9 +830,9 @@ ENDPROC(unrecoverable_exception)
832 * a0: trashed, original value saved on stack (PT_AREG0) 830 * a0: trashed, original value saved on stack (PT_AREG0)
833 * a1: a1 831 * a1: a1
834 * a2: new stack pointer, original in DEPC 832 * a2: new stack pointer, original in DEPC
835 * a3: dispatch table 833 * a3: a3
836 * depc: a2, original value saved on stack (PT_DEPC) 834 * depc: a2, original value saved on stack (PT_DEPC)
837 * excsave_1: a3 835 * excsave_1: dispatch table
838 * 836 *
839 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 837 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
840 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 838 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -857,18 +855,16 @@ ENTRY(fast_alloca)
857 855
858 rsr a0, depc # get a2 856 rsr a0, depc # get a2
859 s32i a4, a2, PT_AREG4 # save a4 and 857 s32i a4, a2, PT_AREG4 # save a4 and
858 s32i a3, a2, PT_AREG3
860 s32i a0, a2, PT_AREG2 # a2 to stack 859 s32i a0, a2, PT_AREG2 # a2 to stack
861 860
862 /* Exit critical section. */ 861 /* Exit critical section. */
863 862
864 movi a0, 0 863 movi a0, 0
864 rsr a3, excsave1
865 s32i a0, a3, EXC_TABLE_FIXUP 865 s32i a0, a3, EXC_TABLE_FIXUP
866 866
867 /* Restore a3, excsave_1 */
868
869 xsr a3, excsave1 # make sure excsave_1 is valid for dbl.
870 rsr a4, epc1 # get exception address 867 rsr a4, epc1 # get exception address
871 s32i a3, a2, PT_AREG3 # save a3 to stack
872 868
873#ifdef ALLOCA_EXCEPTION_IN_IRAM 869#ifdef ALLOCA_EXCEPTION_IN_IRAM
874#error iram not supported 870#error iram not supported
@@ -1007,9 +1003,9 @@ ENDPROC(fast_alloca)
1007 * a0: trashed, original value saved on stack (PT_AREG0) 1003 * a0: trashed, original value saved on stack (PT_AREG0)
1008 * a1: a1 1004 * a1: a1
1009 * a2: new stack pointer, original in DEPC 1005 * a2: new stack pointer, original in DEPC
1010 * a3: dispatch table 1006 * a3: a3
1011 * depc: a2, original value saved on stack (PT_DEPC) 1007 * depc: a2, original value saved on stack (PT_DEPC)
1012 * excsave_1: a3 1008 * excsave_1: dispatch table
1013 */ 1009 */
1014 1010
1015ENTRY(fast_syscall_kernel) 1011ENTRY(fast_syscall_kernel)
@@ -1056,7 +1052,6 @@ ENTRY(fast_syscall_unrecoverable)
1056 1052
1057 l32i a0, a2, PT_AREG0 # restore a0 1053 l32i a0, a2, PT_AREG0 # restore a0
1058 xsr a2, depc # restore a2, depc 1054 xsr a2, depc # restore a2, depc
1059 rsr a3, excsave1
1060 1055
1061 wsr a0, excsave1 1056 wsr a0, excsave1
1062 movi a0, unrecoverable_exception 1057 movi a0, unrecoverable_exception
@@ -1078,10 +1073,10 @@ ENDPROC(fast_syscall_unrecoverable)
1078 * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0) 1073 * a0: a2 (syscall-nr), original value saved on stack (PT_AREG0)
1079 * a1: a1 1074 * a1: a1
1080 * a2: new stack pointer, original in a0 and DEPC 1075 * a2: new stack pointer, original in a0 and DEPC
1081 * a3: dispatch table, original in excsave_1 1076 * a3: a3
1082 * a4..a15: unchanged 1077 * a4..a15: unchanged
1083 * depc: a2, original value saved on stack (PT_DEPC) 1078 * depc: a2, original value saved on stack (PT_DEPC)
1084 * excsave_1: a3 1079 * excsave_1: dispatch table
1085 * 1080 *
1086 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 1081 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1087 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 1082 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1114,8 +1109,6 @@ ENDPROC(fast_syscall_unrecoverable)
1114 1109
1115ENTRY(fast_syscall_xtensa) 1110ENTRY(fast_syscall_xtensa)
1116 1111
1117 xsr a3, excsave1 # restore a3, excsave1
1118
1119 s32i a7, a2, PT_AREG7 # we need an additional register 1112 s32i a7, a2, PT_AREG7 # we need an additional register
1120 movi a7, 4 # sizeof(unsigned int) 1113 movi a7, 4 # sizeof(unsigned int)
1121 access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp 1114 access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
@@ -1178,9 +1171,9 @@ ENDPROC(fast_syscall_xtensa)
1178 * a0: trashed, original value saved on stack (PT_AREG0) 1171 * a0: trashed, original value saved on stack (PT_AREG0)
1179 * a1: a1 1172 * a1: a1
1180 * a2: new stack pointer, original in DEPC 1173 * a2: new stack pointer, original in DEPC
1181 * a3: dispatch table 1174 * a3: a3
1182 * depc: a2, original value saved on stack (PT_DEPC) 1175 * depc: a2, original value saved on stack (PT_DEPC)
1183 * excsave_1: a3 1176 * excsave_1: dispatch table
1184 * 1177 *
1185 * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. 1178 * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
1186 */ 1179 */
@@ -1189,15 +1182,16 @@ ENTRY(fast_syscall_spill_registers)
1189 1182
1190 /* Register a FIXUP handler (pass current wb as a parameter) */ 1183 /* Register a FIXUP handler (pass current wb as a parameter) */
1191 1184
1185 xsr a3, excsave1
1192 movi a0, fast_syscall_spill_registers_fixup 1186 movi a0, fast_syscall_spill_registers_fixup
1193 s32i a0, a3, EXC_TABLE_FIXUP 1187 s32i a0, a3, EXC_TABLE_FIXUP
1194 rsr a0, windowbase 1188 rsr a0, windowbase
1195 s32i a0, a3, EXC_TABLE_PARAM 1189 s32i a0, a3, EXC_TABLE_PARAM
1190 xsr a3, excsave1 # restore a3 and excsave_1
1196 1191
1197 /* Save a3 and SAR on stack. */ 1192 /* Save a3, a4 and SAR on stack. */
1198 1193
1199 rsr a0, sar 1194 rsr a0, sar
1200 xsr a3, excsave1 # restore a3 and excsave_1
1201 s32i a3, a2, PT_AREG3 1195 s32i a3, a2, PT_AREG3
1202 s32i a4, a2, PT_AREG4 1196 s32i a4, a2, PT_AREG4
1203 s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5 1197 s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5
@@ -1251,14 +1245,14 @@ fast_syscall_spill_registers_fixup:
1251 * in WS, so that the exception handlers save them to the task stack. 1245 * in WS, so that the exception handlers save them to the task stack.
1252 */ 1246 */
1253 1247
1254 rsr a3, excsave1 # get spill-mask 1248 xsr a3, excsave1 # get spill-mask
1255 slli a2, a3, 1 # shift left by one 1249 slli a2, a3, 1 # shift left by one
1256 1250
1257 slli a3, a2, 32-WSBITS 1251 slli a3, a2, 32-WSBITS
1258 src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy...... 1252 src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy......
1259 wsr a2, windowstart # set corrected windowstart 1253 wsr a2, windowstart # set corrected windowstart
1260 1254
1261 movi a3, exc_table 1255 rsr a3, excsave1
1262 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2 1256 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2
1263 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task) 1257 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task)
1264 1258
@@ -1295,7 +1289,7 @@ fast_syscall_spill_registers_fixup:
1295 1289
1296 /* Jump to the exception handler. */ 1290 /* Jump to the exception handler. */
1297 1291
1298 movi a3, exc_table 1292 rsr a3, excsave1
1299 rsr a0, exccause 1293 rsr a0, exccause
1300 addx4 a0, a0, a3 # find entry in table 1294 addx4 a0, a0, a3 # find entry in table
1301 l32i a0, a0, EXC_TABLE_FAST_USER # load handler 1295 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
@@ -1312,6 +1306,7 @@ fast_syscall_spill_registers_fixup_return:
1312 xsr a3, excsave1 1306 xsr a3, excsave1
1313 movi a2, fast_syscall_spill_registers_fixup 1307 movi a2, fast_syscall_spill_registers_fixup
1314 s32i a2, a3, EXC_TABLE_FIXUP 1308 s32i a2, a3, EXC_TABLE_FIXUP
1309 s32i a0, a3, EXC_TABLE_DOUBLE_SAVE
1315 rsr a2, windowbase 1310 rsr a2, windowbase
1316 s32i a2, a3, EXC_TABLE_PARAM 1311 s32i a2, a3, EXC_TABLE_PARAM
1317 l32i a2, a3, EXC_TABLE_KSTK 1312 l32i a2, a3, EXC_TABLE_KSTK
@@ -1323,11 +1318,6 @@ fast_syscall_spill_registers_fixup_return:
1323 wsr a3, windowbase 1318 wsr a3, windowbase
1324 rsync 1319 rsync
1325 1320
1326 /* Restore a3 and return. */
1327
1328 movi a3, exc_table
1329 xsr a3, excsave1
1330
1331 rfde 1321 rfde
1332 1322
1333 1323
@@ -1514,9 +1504,8 @@ ENTRY(_spill_registers)
1514 1504
1515 movi a0, 0 1505 movi a0, 0
1516 1506
1517 movi a3, exc_table 1507 rsr a3, excsave1
1518 l32i a1, a3, EXC_TABLE_KSTK 1508 l32i a1, a3, EXC_TABLE_KSTK
1519 wsr a3, excsave1
1520 1509
1521 movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL 1510 movi a4, (1 << PS_WOE_BIT) | LOCKLEVEL
1522 wsr a4, ps 1511 wsr a4, ps
@@ -1560,9 +1549,9 @@ ENDPROC(fast_second_level_miss_double_kernel)
1560 * a0: trashed, original value saved on stack (PT_AREG0) 1549 * a0: trashed, original value saved on stack (PT_AREG0)
1561 * a1: a1 1550 * a1: a1
1562 * a2: new stack pointer, original in DEPC 1551 * a2: new stack pointer, original in DEPC
1563 * a3: dispatch table 1552 * a3: a3
1564 * depc: a2, original value saved on stack (PT_DEPC) 1553 * depc: a2, original value saved on stack (PT_DEPC)
1565 * excsave_1: a3 1554 * excsave_1: dispatch table
1566 * 1555 *
1567 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 1556 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1568 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 1557 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1570,9 +1559,10 @@ ENDPROC(fast_second_level_miss_double_kernel)
1570 1559
1571ENTRY(fast_second_level_miss) 1560ENTRY(fast_second_level_miss)
1572 1561
1573 /* Save a1. Note: we don't expect a double exception. */ 1562 /* Save a1 and a3. Note: we don't expect a double exception. */
1574 1563
1575 s32i a1, a2, PT_AREG1 1564 s32i a1, a2, PT_AREG1
1565 s32i a3, a2, PT_AREG3
1576 1566
1577 /* We need to map the page of PTEs for the user task. Find 1567 /* We need to map the page of PTEs for the user task. Find
1578 * the pointer to that page. Also, it's possible for tsk->mm 1568 * the pointer to that page. Also, it's possible for tsk->mm
@@ -1594,9 +1584,6 @@ ENTRY(fast_second_level_miss)
1594 l32i a0, a1, TASK_MM # tsk->mm 1584 l32i a0, a1, TASK_MM # tsk->mm
1595 beqz a0, 9f 1585 beqz a0, 9f
1596 1586
1597
1598 /* We deliberately destroy a3 that holds the exception table. */
1599
16008: rsr a3, excvaddr # fault address 15878: rsr a3, excvaddr # fault address
1601 _PGD_OFFSET(a0, a3, a1) 1588 _PGD_OFFSET(a0, a3, a1)
1602 l32i a0, a0, 0 # read pmdval 1589 l32i a0, a0, 0 # read pmdval
@@ -1647,7 +1634,7 @@ ENTRY(fast_second_level_miss)
1647 1634
1648 /* Exit critical section. */ 1635 /* Exit critical section. */
1649 1636
16504: movi a3, exc_table # restore a3 16374: rsr a3, excsave1
1651 movi a0, 0 1638 movi a0, 0
1652 s32i a0, a3, EXC_TABLE_FIXUP 1639 s32i a0, a3, EXC_TABLE_FIXUP
1653 1640
@@ -1655,8 +1642,8 @@ ENTRY(fast_second_level_miss)
1655 1642
1656 l32i a0, a2, PT_AREG0 1643 l32i a0, a2, PT_AREG0
1657 l32i a1, a2, PT_AREG1 1644 l32i a1, a2, PT_AREG1
1645 l32i a3, a2, PT_AREG3
1658 l32i a2, a2, PT_DEPC 1646 l32i a2, a2, PT_DEPC
1659 xsr a3, excsave1
1660 1647
1661 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f 1648 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1662 1649
@@ -1743,11 +1730,8 @@ ENTRY(fast_second_level_miss)
1743 1730
17442: /* Invalid PGD, default exception handling */ 17312: /* Invalid PGD, default exception handling */
1745 1732
1746 movi a3, exc_table
1747 rsr a1, depc 1733 rsr a1, depc
1748 xsr a3, excsave1
1749 s32i a1, a2, PT_AREG2 1734 s32i a1, a2, PT_AREG2
1750 s32i a3, a2, PT_AREG3
1751 mov a1, a2 1735 mov a1, a2
1752 1736
1753 rsr a2, ps 1737 rsr a2, ps
@@ -1767,9 +1751,9 @@ ENDPROC(fast_second_level_miss)
1767 * a0: trashed, original value saved on stack (PT_AREG0) 1751 * a0: trashed, original value saved on stack (PT_AREG0)
1768 * a1: a1 1752 * a1: a1
1769 * a2: new stack pointer, original in DEPC 1753 * a2: new stack pointer, original in DEPC
1770 * a3: dispatch table 1754 * a3: a3
1771 * depc: a2, original value saved on stack (PT_DEPC) 1755 * depc: a2, original value saved on stack (PT_DEPC)
1772 * excsave_1: a3 1756 * excsave_1: dispatch table
1773 * 1757 *
1774 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC 1758 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
1775 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 1759 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1777,17 +1761,17 @@ ENDPROC(fast_second_level_miss)
1777 1761
1778ENTRY(fast_store_prohibited) 1762ENTRY(fast_store_prohibited)
1779 1763
1780 /* Save a1 and a4. */ 1764 /* Save a1 and a3. */
1781 1765
1782 s32i a1, a2, PT_AREG1 1766 s32i a1, a2, PT_AREG1
1783 s32i a4, a2, PT_AREG4 1767 s32i a3, a2, PT_AREG3
1784 1768
1785 GET_CURRENT(a1,a2) 1769 GET_CURRENT(a1,a2)
1786 l32i a0, a1, TASK_MM # tsk->mm 1770 l32i a0, a1, TASK_MM # tsk->mm
1787 beqz a0, 9f 1771 beqz a0, 9f
1788 1772
17898: rsr a1, excvaddr # fault address 17738: rsr a1, excvaddr # fault address
1790 _PGD_OFFSET(a0, a1, a4) 1774 _PGD_OFFSET(a0, a1, a3)
1791 l32i a0, a0, 0 1775 l32i a0, a0, 0
1792 beqz a0, 2f 1776 beqz a0, 2f
1793 1777
@@ -1796,39 +1780,37 @@ ENTRY(fast_store_prohibited)
1796 * and is not PAGE_NONE. See pgtable.h for possible PTE layouts. 1780 * and is not PAGE_NONE. See pgtable.h for possible PTE layouts.
1797 */ 1781 */
1798 1782
1799 _PTE_OFFSET(a0, a1, a4) 1783 _PTE_OFFSET(a0, a1, a3)
1800 l32i a4, a0, 0 # read pteval 1784 l32i a3, a0, 0 # read pteval
1801 movi a1, _PAGE_CA_INVALID 1785 movi a1, _PAGE_CA_INVALID
1802 ball a4, a1, 2f 1786 ball a3, a1, 2f
1803 bbci.l a4, _PAGE_WRITABLE_BIT, 2f 1787 bbci.l a3, _PAGE_WRITABLE_BIT, 2f
1804 1788
1805 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE 1789 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
1806 or a4, a4, a1 1790 or a3, a3, a1
1807 rsr a1, excvaddr 1791 rsr a1, excvaddr
1808 s32i a4, a0, 0 1792 s32i a3, a0, 0
1809 1793
1810 /* We need to flush the cache if we have page coloring. */ 1794 /* We need to flush the cache if we have page coloring. */
1811#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK 1795#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
1812 dhwb a0, 0 1796 dhwb a0, 0
1813#endif 1797#endif
1814 pdtlb a0, a1 1798 pdtlb a0, a1
1815 wdtlb a4, a0 1799 wdtlb a3, a0
1816 1800
1817 /* Exit critical section. */ 1801 /* Exit critical section. */
1818 1802
1819 movi a0, 0 1803 movi a0, 0
1804 rsr a3, excsave1
1820 s32i a0, a3, EXC_TABLE_FIXUP 1805 s32i a0, a3, EXC_TABLE_FIXUP
1821 1806
1822 /* Restore the working registers, and return. */ 1807 /* Restore the working registers, and return. */
1823 1808
1824 l32i a4, a2, PT_AREG4 1809 l32i a3, a2, PT_AREG3
1825 l32i a1, a2, PT_AREG1 1810 l32i a1, a2, PT_AREG1
1826 l32i a0, a2, PT_AREG0 1811 l32i a0, a2, PT_AREG0
1827 l32i a2, a2, PT_DEPC 1812 l32i a2, a2, PT_DEPC
1828 1813
1829 /* Restore excsave1 and a3. */
1830
1831 xsr a3, excsave1
1832 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f 1814 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
1833 1815
1834 rsr a2, depc 1816 rsr a2, depc
@@ -1845,11 +1827,8 @@ ENTRY(fast_store_prohibited)
1845 1827
18462: /* If there was a problem, handle fault in C */ 18282: /* If there was a problem, handle fault in C */
1847 1829
1848 rsr a4, depc # still holds a2 1830 rsr a3, depc # still holds a2
1849 xsr a3, excsave1 1831 s32i a3, a2, PT_AREG2
1850 s32i a4, a2, PT_AREG2
1851 s32i a3, a2, PT_AREG3
1852 l32i a4, a2, PT_AREG4
1853 mov a1, a2 1832 mov a1, a2
1854 1833
1855 rsr a2, ps 1834 rsr a2, ps
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index f9e175382aa9..cb8fd44caabc 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -78,6 +78,7 @@ ENTRY(_UserExceptionVector)
78 s32i a0, a2, PT_DEPC # mark it as a regular exception 78 s32i a0, a2, PT_DEPC # mark it as a regular exception
79 addx4 a0, a0, a3 # find entry in table 79 addx4 a0, a0, a3 # find entry in table
80 l32i a0, a0, EXC_TABLE_FAST_USER # load handler 80 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
81 xsr a3, excsave1 # restore a3 and dispatch table
81 jx a0 82 jx a0
82 83
83ENDPROC(_UserExceptionVector) 84ENDPROC(_UserExceptionVector)
@@ -104,6 +105,7 @@ ENTRY(_KernelExceptionVector)
104 s32i a0, a2, PT_DEPC # mark it as a regular exception 105 s32i a0, a2, PT_DEPC # mark it as a regular exception
105 addx4 a0, a0, a3 # find entry in table 106 addx4 a0, a0, a3 # find entry in table
106 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address 107 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address
108 xsr a3, excsave1 # restore a3 and dispatch table
107 jx a0 109 jx a0
108 110
109ENDPROC(_KernelExceptionVector) 111ENDPROC(_KernelExceptionVector)
@@ -168,7 +170,7 @@ ENDPROC(_KernelExceptionVector)
168 * 170 *
169 * a0: DEPC 171 * a0: DEPC
170 * a1: a1 172 * a1: a1
171 * a2: trashed, original value in EXC_TABLE_DOUBLE_A2 173 * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
172 * a3: exctable 174 * a3: exctable
173 * depc: a0 175 * depc: a0
174 * excsave_1: a3 176 * excsave_1: a3
@@ -204,47 +206,46 @@ ENDPROC(_KernelExceptionVector)
204 206
205 .section .DoubleExceptionVector.text, "ax" 207 .section .DoubleExceptionVector.text, "ax"
206 .begin literal_prefix .DoubleExceptionVector 208 .begin literal_prefix .DoubleExceptionVector
209 .globl _DoubleExceptionVector_WindowUnderflow
210 .globl _DoubleExceptionVector_WindowOverflow
207 211
208ENTRY(_DoubleExceptionVector) 212ENTRY(_DoubleExceptionVector)
209 213
210 /* Deliberately destroy excsave (don't assume it's value was valid). */ 214 xsr a3, excsave1
211 215 s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
212 wsr a3, excsave1 # save a3
213 216
214 /* Check for kernel double exception (usually fatal). */ 217 /* Check for kernel double exception (usually fatal). */
215 218
216 rsr a3, ps 219 rsr a2, ps
217 _bbci.l a3, PS_UM_BIT, .Lksp 220 _bbci.l a2, PS_UM_BIT, .Lksp
218 221
219 /* Check if we are currently handling a window exception. */ 222 /* Check if we are currently handling a window exception. */
220 /* Note: We don't need to indicate that we enter a critical section. */ 223 /* Note: We don't need to indicate that we enter a critical section. */
221 224
222 xsr a0, depc # get DEPC, save a0 225 xsr a0, depc # get DEPC, save a0
223 226
224 movi a3, WINDOW_VECTORS_VADDR 227 movi a2, WINDOW_VECTORS_VADDR
225 _bltu a0, a3, .Lfixup 228 _bltu a0, a2, .Lfixup
226 addi a3, a3, WINDOW_VECTORS_SIZE 229 addi a2, a2, WINDOW_VECTORS_SIZE
227 _bgeu a0, a3, .Lfixup 230 _bgeu a0, a2, .Lfixup
228 231
229 /* Window overflow/underflow exception. Get stack pointer. */ 232 /* Window overflow/underflow exception. Get stack pointer. */
230 233
231 mov a3, a2 234 l32i a2, a3, EXC_TABLE_KSTK
232 /* This explicit literal and the following references to it are made
233 * in order to fit DoubleExceptionVector.literals into the available
234 * 16-byte gap before DoubleExceptionVector.text in the absence of
235 * link time relaxation. See kernel/vmlinux.lds.S
236 */
237 .literal .Lexc_table, exc_table
238 l32r a2, .Lexc_table
239 l32i a2, a2, EXC_TABLE_KSTK
240 235
241 /* Check for overflow/underflow exception, jump if overflow. */ 236 /* Check for overflow/underflow exception, jump if overflow. */
242 237
243 _bbci.l a0, 6, .Lovfl 238 _bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow
244
245 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
246 239
247 /* Restart window underflow exception. 240 /*
241 * Restart window underflow exception.
242 * Currently:
243 * depc = orig a0,
244 * a0 = orig DEPC,
245 * a2 = new sp based on KSTK from exc_table
246 * a3 = excsave_1
247 * excsave_1 = orig a3
248 *
248 * We return to the instruction in user space that caused the window 249 * We return to the instruction in user space that caused the window
249 * underflow exception. Therefore, we change window base to the value 250 * underflow exception. Therefore, we change window base to the value
250 * before we entered the window underflow exception and prepare the 251 * before we entered the window underflow exception and prepare the
@@ -252,10 +253,11 @@ ENTRY(_DoubleExceptionVector)
252 * by changing depc (in a0). 253 * by changing depc (in a0).
253 * Note: We can trash the current window frame (a0...a3) and depc! 254 * Note: We can trash the current window frame (a0...a3) and depc!
254 */ 255 */
255 256_DoubleExceptionVector_WindowUnderflow:
257 xsr a3, excsave1
256 wsr a2, depc # save stack pointer temporarily 258 wsr a2, depc # save stack pointer temporarily
257 rsr a0, ps 259 rsr a0, ps
258 extui a0, a0, PS_OWB_SHIFT, 4 260 extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
259 wsr a0, windowbase 261 wsr a0, windowbase
260 rsync 262 rsync
261 263
@@ -263,28 +265,57 @@ ENTRY(_DoubleExceptionVector)
263 265
264 xsr a2, depc # save a2 and get stack pointer 266 xsr a2, depc # save a2 and get stack pointer
265 s32i a0, a2, PT_AREG0 267 s32i a0, a2, PT_AREG0
266 268 xsr a3, excsave1
267 wsr a3, excsave1 # save a3
268 l32r a3, .Lexc_table
269
270 rsr a0, exccause 269 rsr a0, exccause
271 s32i a0, a2, PT_DEPC # mark it as a regular exception 270 s32i a0, a2, PT_DEPC # mark it as a regular exception
272 addx4 a0, a0, a3 271 addx4 a0, a0, a3
272 xsr a3, excsave1
273 l32i a0, a0, EXC_TABLE_FAST_USER 273 l32i a0, a0, EXC_TABLE_FAST_USER
274 jx a0 274 jx a0
275 275
276.Lfixup:/* Check for a fixup handler or if we were in a critical section. */ 276 /*
277 * We only allow the ITLB miss exception if we are in kernel space.
278 * All other exceptions are unexpected and thus unrecoverable!
279 */
280
281#ifdef CONFIG_MMU
282 .extern fast_second_level_miss_double_kernel
283
284.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
285
286 rsr a3, exccause
287 beqi a3, EXCCAUSE_ITLB_MISS, 1f
288 addi a3, a3, -EXCCAUSE_DTLB_MISS
289 bnez a3, .Lunrecoverable
2901: movi a3, fast_second_level_miss_double_kernel
291 jx a3
292#else
293.equ .Lksp, .Lunrecoverable
294#endif
295
296 /* Critical! We can't handle this situation. PANIC! */
277 297
278 /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */ 298 .extern unrecoverable_exception
279 299
280 l32r a3, .Lexc_table 300.Lunrecoverable_fixup:
281 s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable 301 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
302 xsr a0, depc
303
304.Lunrecoverable:
305 rsr a3, excsave1
306 wsr a0, excsave1
307 movi a0, unrecoverable_exception
308 callx0 a0
309
310.Lfixup:/* Check for a fixup handler or if we were in a critical section. */
311
312 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave1: a3 */
282 313
283 /* Enter critical section. */ 314 /* Enter critical section. */
284 315
285 l32i a2, a3, EXC_TABLE_FIXUP 316 l32i a2, a3, EXC_TABLE_FIXUP
286 s32i a3, a3, EXC_TABLE_FIXUP 317 s32i a3, a3, EXC_TABLE_FIXUP
287 beq a2, a3, .Lunrecoverable_fixup # critical! 318 beq a2, a3, .Lunrecoverable_fixup # critical section
288 beqz a2, .Ldflt # no handler was registered 319 beqz a2, .Ldflt # no handler was registered
289 320
290 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */ 321 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */
@@ -293,58 +324,145 @@ ENTRY(_DoubleExceptionVector)
293 324
294.Ldflt: /* Get stack pointer. */ 325.Ldflt: /* Get stack pointer. */
295 326
296 l32i a3, a3, EXC_TABLE_DOUBLE_SAVE 327 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
297 addi a2, a3, -PT_USER_SIZE 328 addi a2, a2, -PT_USER_SIZE
298
299.Lovfl: /* Jump to default handlers. */
300 329
301 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */ 330 /* a0: depc, a1: a1, a2: kstk, a3: exctable, depc: a0, excsave: a3 */
302 331
303 xsr a3, depc
304 s32i a0, a2, PT_DEPC 332 s32i a0, a2, PT_DEPC
305 s32i a3, a2, PT_AREG0 333 l32i a0, a3, EXC_TABLE_DOUBLE_SAVE
334 xsr a0, depc
335 s32i a0, a2, PT_AREG0
306 336
307 /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ 337 /* a0: avail, a1: a1, a2: kstk, a3: exctable, depc: a2, excsave: a3 */
308 338
309 l32r a3, .Lexc_table
310 rsr a0, exccause 339 rsr a0, exccause
311 addx4 a0, a0, a3 340 addx4 a0, a0, a3
341 xsr a3, excsave1
312 l32i a0, a0, EXC_TABLE_FAST_USER 342 l32i a0, a0, EXC_TABLE_FAST_USER
313 jx a0 343 jx a0
314 344
315 /* 345 /*
316 * We only allow the ITLB miss exception if we are in kernel space. 346 * Restart window OVERFLOW exception.
317 * All other exceptions are unexpected and thus unrecoverable! 347 * Currently:
348 * depc = orig a0,
349 * a0 = orig DEPC,
350 * a2 = new sp based on KSTK from exc_table
351 * a3 = EXCSAVE_1
352 * excsave_1 = orig a3
353 *
354 * We return to the instruction in user space that caused the window
355 * overflow exception. Therefore, we change window base to the value
356 * before we entered the window overflow exception and prepare the
357 * registers to return as if we were coming from a regular exception
358 * by changing DEPC (in a0).
359 *
360 * NOTE: We CANNOT trash the current window frame (a0...a3), but we
361 * can clobber depc.
362 *
363 * The tricky part here is that overflow8 and overflow12 handlers
364 * save a0, then clobber a0. To restart the handler, we have to restore
365 * a0 if the double exception was past the point where a0 was clobbered.
366 *
367 * To keep things simple, we take advantage of the fact all overflow
368 * handlers save a0 in their very first instruction. If DEPC was past
369 * that instruction, we can safely restore a0 from where it was saved
370 * on the stack.
371 *
372 * a0: depc, a1: a1, a2: kstk, a3: exc_table, depc: a0, excsave1: a3
318 */ 373 */
374_DoubleExceptionVector_WindowOverflow:
375 extui a2, a0, 0, 6 # get offset into 64-byte vector handler
376 beqz a2, 1f # if at start of vector, don't restore
319 377
320#ifdef CONFIG_MMU 378 addi a0, a0, -128
321 .extern fast_second_level_miss_double_kernel 379 bbsi a0, 8, 1f # don't restore except for overflow 8 and 12
380 bbsi a0, 7, 2f
322 381
323.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ 382 /*
383 * Restore a0 as saved by _WindowOverflow8().
384 *
385 * FIXME: we really need a fixup handler for this L32E,
386 * for the extremely unlikely case where the overflow handler's
387 * reference thru a0 gets a hardware TLB refill that bumps out
388 * the (distinct, aliasing) TLB entry that mapped its prior
389 * references thru a9, and where our reference now thru a9
390 * gets a 2nd-level miss exception (not hardware TLB refill).
391 */
324 392
325 rsr a3, exccause 393 l32e a2, a9, -16
326 beqi a3, EXCCAUSE_ITLB_MISS, 1f 394 wsr a2, depc # replace the saved a0
327 addi a3, a3, -EXCCAUSE_DTLB_MISS 395 j 1f
328 bnez a3, .Lunrecoverable
3291: movi a3, fast_second_level_miss_double_kernel
330 jx a3
331#else
332.equ .Lksp, .Lunrecoverable
333#endif
334 396
335 /* Critical! We can't handle this situation. PANIC! */ 3972:
398 /*
399 * Restore a0 as saved by _WindowOverflow12().
400 *
401 * FIXME: we really need a fixup handler for this L32E,
402 * for the extremely unlikely case where the overflow handler's
403 * reference thru a0 gets a hardware TLB refill that bumps out
404 * the (distinct, aliasing) TLB entry that mapped its prior
405 * references thru a13, and where our reference now thru a13
406 * gets a 2nd-level miss exception (not hardware TLB refill).
407 */
336 408
337 .extern unrecoverable_exception 409 l32e a2, a13, -16
410 wsr a2, depc # replace the saved a0
4111:
412 /*
413 * Restore WindowBase while leaving all address registers restored.
414 * We have to use ROTW for this, because WSR.WINDOWBASE requires
415 * an address register (which would prevent restore).
416 *
417 * Window Base goes from 0 ... 7 (Module 8)
418 * Window Start is 8 bits; Ex: (0b1010 1010):0x55 from series of call4s
419 */
420
421 rsr a0, ps
422 extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
423 rsr a2, windowbase
424 sub a0, a2, a0
425 extui a0, a0, 0, 3
338 426
339.Lunrecoverable_fixup:
340 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE 427 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
341 xsr a0, depc 428 xsr a3, excsave1
429 beqi a0, 1, .L1pane
430 beqi a0, 3, .L3pane
342 431
343.Lunrecoverable: 432 rsr a0, depc
344 rsr a3, excsave1 433 rotw -2
345 wsr a0, excsave1 434
346 movi a0, unrecoverable_exception 435 /*
347 callx0 a0 436 * We are now in the user code's original window frame.
437 * Process the exception as a user exception as if it was
438 * taken by the user code.
439 *
440 * This is similar to the user exception vector,
441 * except that PT_DEPC isn't set to EXCCAUSE.
442 */
4431:
444 xsr a3, excsave1
445 wsr a2, depc
446 l32i a2, a3, EXC_TABLE_KSTK
447 s32i a0, a2, PT_AREG0
448 rsr a0, exccause
449
450 s32i a0, a2, PT_DEPC
451
452 addx4 a0, a0, a3
453 l32i a0, a0, EXC_TABLE_FAST_USER
454 xsr a3, excsave1
455 jx a0
456
457.L1pane:
458 rsr a0, depc
459 rotw -1
460 j 1b
461
462.L3pane:
463 rsr a0, depc
464 rotw -3
465 j 1b
348 466
349 .end literal_prefix 467 .end literal_prefix
350 468