Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 651d4af

Browse files
committed
xtensa: rearrange unaligned exception handler
- extract initialization part of the exception handler into a separate function. - use single label for invalid instruction instead of two labels, one for load and one for store, at one place. - use sext instruction for sign extension when available. - store SAR on the stack instead of in a0. - replace numeric labels for load and store writeback with .Lload_w and .Lstore_w respectively. Signed-off-by: Max Filippov <[email protected]>
1 parent 3522bcf commit 651d4af

File tree

1 file changed

+89
-82
lines changed

1 file changed

+89
-82
lines changed

arch/xtensa/kernel/align.S

Lines changed: 89 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -157,58 +157,7 @@
157157
.literal_position
158158
ENTRY(fast_unaligned)
159159

160-
/* Note: We don't expect the address to be aligned on a word
161-
* boundary. After all, the processor generated that exception
162-
* and it would be a hardware fault.
163-
*/
164-
165-
/* Save some working register */
166-
167-
s32i a4, a2, PT_AREG4
168-
s32i a5, a2, PT_AREG5
169-
s32i a6, a2, PT_AREG6
170-
s32i a7, a2, PT_AREG7
171-
s32i a8, a2, PT_AREG8
172-
173-
rsr a0, depc
174-
s32i a0, a2, PT_AREG2
175-
s32i a3, a2, PT_AREG3
176-
177-
rsr a3, excsave1
178-
movi a4, fast_unaligned_fixup
179-
s32i a4, a3, EXC_TABLE_FIXUP
180-
181-
/* Keep value of SAR in a0 */
182-
183-
rsr a0, sar
184-
rsr a8, excvaddr # load unaligned memory address
185-
186-
/* Now, identify one of the following load/store instructions.
187-
*
188-
* The only possible danger of a double exception on the
189-
* following l32i instructions is kernel code in vmalloc
190-
* memory. The processor was just executing at the EPC_1
191-
* address, and indeed, already fetched the instruction. That
192-
* guarantees a TLB mapping, which hasn't been replaced by
193-
* this unaligned exception handler that uses only static TLB
194-
* mappings. However, high-level interrupt handlers might
195-
* modify TLB entries, so for the generic case, we register a
196-
* TABLE_FIXUP handler here, too.
197-
*/
198-
199-
/* a3...a6 saved on stack, a2 = SP */
200-
201-
/* Extract the instruction that caused the unaligned access. */
202-
203-
rsr a7, epc1 # load exception address
204-
movi a3, ~3
205-
and a3, a3, a7 # mask lower bits
206-
207-
l32i a4, a3, 0 # load 2 words
208-
l32i a5, a3, 4
209-
210-
__ssa8 a7
211-
__src_b a4, a4, a5 # a4 has the instruction
160+
call0 .Lsave_and_load_instruction
212161

213162
/* Analyze the instruction (load or store?). */
214163

@@ -249,29 +198,32 @@ ENTRY(fast_unaligned)
249198
addi a7, a7, 2 # increment PC (assume 16-bit insn)
250199

251200
extui a5, a4, INSN_OP0, 4
252-
_beqi a5, OP0_L32I_N, 1f # l32i.n: jump
201+
_beqi a5, OP0_L32I_N, .Lload_w# l32i.n: jump
253202

254203
addi a7, a7, 1
255204
#else
256205
addi a7, a7, 3
257206
#endif
258207

259208
extui a5, a4, INSN_OP1, 4
260-
_beqi a5, OP1_L32I, 1f # l32i: jump
209+
_beqi a5, OP1_L32I, .Lload_w # l32i: jump
261210

262211
extui a3, a3, 0, 16 # extract lower 16 bits
263-
_beqi a5, OP1_L16UI, 1f
212+
_beqi a5, OP1_L16UI, .Lload_w
264213
addi a5, a5, -OP1_L16SI
265-
_bnez a5, .Linvalid_instruction_load
214+
_bnez a5, .Linvalid_instruction
266215

267216
/* sign extend value */
268-
217+
#if XCHAL_HAVE_SEXT
218+
sext a3, a3, 15
219+
#else
269220
slli a3, a3, 16
270221
srai a3, a3, 16
222+
#endif
271223

272224
/* Set target register. */
273225

274-
1:
226+
.Lload_w:
275227
extui a4, a4, INSN_T, 4 # extract target register
276228
movi a5, .Lload_table
277229
addx8 a4, a4, a5
@@ -297,35 +249,35 @@ ENTRY(fast_unaligned)
297249
mov a15, a3 ; _j .Lexit; .align 8
298250

299251
.Lstore_table:
300-
l32i a3, a2, PT_AREG0; _j 1f; .align 8
301-
mov a3, a1; _j 1f; .align 8 # fishy??
302-
l32i a3, a2, PT_AREG2; _j 1f; .align 8
303-
l32i a3, a2, PT_AREG3; _j 1f; .align 8
304-
l32i a3, a2, PT_AREG4; _j 1f; .align 8
305-
l32i a3, a2, PT_AREG5; _j 1f; .align 8
306-
l32i a3, a2, PT_AREG6; _j 1f; .align 8
307-
l32i a3, a2, PT_AREG7; _j 1f; .align 8
308-
l32i a3, a2, PT_AREG8; _j 1f; .align 8
309-
mov a3, a9 ; _j 1f; .align 8
310-
mov a3, a10 ; _j 1f; .align 8
311-
mov a3, a11 ; _j 1f; .align 8
312-
mov a3, a12 ; _j 1f; .align 8
313-
mov a3, a13 ; _j 1f; .align 8
314-
mov a3, a14 ; _j 1f; .align 8
315-
mov a3, a15 ; _j 1f; .align 8
252+
l32i a3, a2, PT_AREG0; _j .Lstore_w; .align 8
253+
mov a3, a1; _j .Lstore_w; .align 8 # fishy??
254+
l32i a3, a2, PT_AREG2; _j .Lstore_w; .align 8
255+
l32i a3, a2, PT_AREG3; _j .Lstore_w; .align 8
256+
l32i a3, a2, PT_AREG4; _j .Lstore_w; .align 8
257+
l32i a3, a2, PT_AREG5; _j .Lstore_w; .align 8
258+
l32i a3, a2, PT_AREG6; _j .Lstore_w; .align 8
259+
l32i a3, a2, PT_AREG7; _j .Lstore_w; .align 8
260+
l32i a3, a2, PT_AREG8; _j .Lstore_w; .align 8
261+
mov a3, a9 ; _j .Lstore_w; .align 8
262+
mov a3, a10 ; _j .Lstore_w; .align 8
263+
mov a3, a11 ; _j .Lstore_w; .align 8
264+
mov a3, a12 ; _j .Lstore_w; .align 8
265+
mov a3, a13 ; _j .Lstore_w; .align 8
266+
mov a3, a14 ; _j .Lstore_w; .align 8
267+
mov a3, a15 ; _j .Lstore_w; .align 8
316268

317269
/* We cannot handle this exception. */
318270

319271
.extern _kernel_exception
320-
.Linvalid_instruction_load:
321-
.Linvalid_instruction_store:
272+
.Linvalid_instruction:
322273

323274
movi a4, 0
324275
rsr a3, excsave1
325276
s32i a4, a3, EXC_TABLE_FIXUP
326277

327278
/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
328279

280+
l32i a0, a2, PT_SAR
329281
l32i a8, a2, PT_AREG8
330282
l32i a7, a2, PT_AREG7
331283
l32i a6, a2, PT_AREG6
@@ -343,8 +295,8 @@ ENTRY(fast_unaligned)
343295
2: movi a0, _user_exception
344296
jx a0
345297

346-
1: # a7: instruction pointer, a4: instruction, a3: value
347-
298+
# a7: instruction pointer, a4: instruction, a3: value
299+
.Lstore_w:
348300
movi a6, 0 # mask: ffffffff:00000000
349301

350302
#if XCHAL_HAVE_DENSITY
@@ -361,7 +313,7 @@ ENTRY(fast_unaligned)
361313

362314
extui a5, a4, INSN_OP1, 4 # extract OP1
363315
_beqi a5, OP1_S32I, 1f # jump if 32 bit store
364-
_bnei a5, OP1_S16I, .Linvalid_instruction_store
316+
_bnei a5, OP1_S16I, .Linvalid_instruction
365317

366318
movi a5, -1
367319
__extl a3, a3 # get 16-bit value
@@ -434,6 +386,7 @@ ENTRY(fast_unaligned)
434386

435387
/* Restore working register */
436388

389+
l32i a0, a2, PT_SAR
437390
l32i a8, a2, PT_AREG8
438391
l32i a7, a2, PT_AREG7
439392
l32i a6, a2, PT_AREG6
@@ -448,6 +401,59 @@ ENTRY(fast_unaligned)
448401
l32i a2, a2, PT_AREG2
449402
rfe
450403

404+
.align 4
405+
.Lsave_and_load_instruction:
406+
407+
/* Save some working register */
408+
409+
s32i a3, a2, PT_AREG3
410+
s32i a4, a2, PT_AREG4
411+
s32i a5, a2, PT_AREG5
412+
s32i a6, a2, PT_AREG6
413+
s32i a7, a2, PT_AREG7
414+
s32i a8, a2, PT_AREG8
415+
416+
rsr a4, depc
417+
s32i a4, a2, PT_AREG2
418+
419+
rsr a5, sar
420+
s32i a5, a2, PT_SAR
421+
422+
rsr a3, excsave1
423+
movi a4, fast_unaligned_fixup
424+
s32i a4, a3, EXC_TABLE_FIXUP
425+
426+
rsr a8, excvaddr # load unaligned memory address
427+
428+
/* Now, identify one of the following load/store instructions.
429+
*
430+
* The only possible danger of a double exception on the
431+
* following l32i instructions is kernel code in vmalloc
432+
* memory. The processor was just executing at the EPC_1
433+
* address, and indeed, already fetched the instruction. That
434+
* guarantees a TLB mapping, which hasn't been replaced by
435+
* this unaligned exception handler that uses only static TLB
436+
* mappings. However, high-level interrupt handlers might
437+
* modify TLB entries, so for the generic case, we register a
438+
* TABLE_FIXUP handler here, too.
439+
*/
440+
441+
/* a3...a6 saved on stack, a2 = SP */
442+
443+
/* Extract the instruction that caused the unaligned access. */
444+
445+
rsr a7, epc1 # load exception address
446+
movi a3, ~3
447+
and a3, a3, a7 # mask lower bits
448+
449+
l32i a4, a3, 0 # load 2 words
450+
l32i a5, a3, 4
451+
452+
__ssa8 a7
453+
__src_b a4, a4, a5 # a4 has the instruction
454+
455+
ret
456+
451457
ENDPROC(fast_unaligned)
452458

453459
ENTRY(fast_unaligned_fixup)
@@ -459,10 +465,11 @@ ENTRY(fast_unaligned_fixup)
459465
l32i a7, a2, PT_AREG7
460466
l32i a6, a2, PT_AREG6
461467
l32i a5, a2, PT_AREG5
462-
l32i a4, a2, PT_AREG4
468+
l32i a4, a2, PT_SAR
463469
l32i a0, a2, PT_AREG2
464-
xsr a0, depc # restore depc and a0
465-
wsr a0, sar
470+
wsr a4, sar
471+
wsr a0, depc # restore depc and a0
472+
l32i a4, a2, PT_AREG4
466473

467474
rsr a0, exccause
468475
s32i a0, a2, PT_DEPC # mark as a regular exception

0 commit comments

Comments
 (0)