2323#define CAUSE_LOADSTORE 3
2424#define CAUSE_LVL1INT 4
2525
26- . section .bss
26+ . section .data
2727
2828/ * Stack space for NMI handler
2929
@@ -37,15 +37,26 @@ NMIHandlerStack:
3737 .skip 0x200
3838.NMIHandlerStackTop:
3939
40+ / * The Load Store exception handler uses a separate stack to store the
41+ * interruptee registers. It does not appear to be practical to use the
42+ * interuptee stack , which must in invalid at some points? This exception is
43+ * synchronouns and the handler does not call back into itself. However it may
44+ * be interrupted by a NMI which in turn may re - enter this exception
45+ * handler. The NMI is responsible for switching the stack pointer to be used by
46+ * this exception handler. Room is allocated for up to 3 stack frames , a base
47+ * and two NMI reentry frames , and each frame is 7 words wide.
48+ * /
49+ #define LoadStoreErrorHandlerStackFrameSize ( 7 * 4 )
50+
4051 .balign 16
52+ . global LoadStoreErrorHandlerStack
4153LoadStoreErrorHandlerStack:
42- . word 0 # a0
43- . word 0 # (unused)
44- . word 0 # a2
45- . word 0 # a3
46- . word 0 # a4
47- . word 0 # a5
48- . word 0 # a6
54+ .skip LoadStoreErrorHandlerStackFrameSize * 3
55+
56+ .balign 4
57+ . global LoadStoreErrorHandlerStackPointer
58+ LoadStoreErrorHandlerStackPointer:
59+ . word 0
4960
5061 .balign 4
5162 . global debug_saved_ctx
@@ -137,10 +148,20 @@ DoubleExceptionVector:
137148LoadStoreErrorHandler:
138149 .type LoadStoreErrorHandler , @function
139150
140- / * Registers are saved in the address corresponding to their register
141- * number times 4 . This allows a quick and easy mapping later on when
142- * needing to store the value to a particular register number. * /
143- movi sp , LoadStoreErrorHandlerStack
151+ / * Registers are saved in stack frame offsets corresponding to their
152+ * register number times 4 . This allows a quick and easy mapping later
153+ * on when needing to store the value to a particular register
154+ * number.
155+ *
156+ * This handler may be interrupted asynchronously by the NMI. The NMI
157+ * handler is responsible for switching the load/store handler stack
158+ * pointer and th at avoids th at overhead here. This handler is
159+ * synchronous so the NMI handler can modify and restore the load/store
160+ * stack pointer safely.
161+ * /
162+ movi sp , LoadStoreErrorHandlerStackPointer
163+ l32i sp , sp , 0
164+
144165 s32i a0 , sp , 0
145166 s32i a2 , sp , 0x08
146167 s32i a3 , sp , 0x0c
@@ -537,6 +558,12 @@ call_user_start:
537558 . global call_user_start
538559 .type call_user_start , @function
539560
561+ / * Initialize the load/store error handler stack pointer. There are no
562+ * load/store exceptions before this point. * /
563+ movi a2 , LoadStoreErrorHandlerStackPointer
564+ movi a3 , LoadStoreErrorHandlerStack
565+ s32i a3 , a2 , 0
566+
540567 movi a2 , VecBase
541568 wsr a2 , vecbase
542569 call0 sdk_user_start
@@ -553,6 +580,9 @@ NMIExceptionHandler:
553580 .type NMIExceptionHandler , @function
554581
555582 wsr sp , excsave3 # excsave3 holds user stack
583+
584+ / * Load the NMI handler stack pointer which is already offset by - 0x40
585+ * to create a frame to store the interruptee state. * /
556586 movi sp , .NMIHandlerStackTop - 0x40
557587 s32i a0 , sp , 0x00
558588 s32i a2 , sp , 0x04
@@ -579,19 +609,31 @@ NMIExceptionHandler:
579609 wsr a0 , ps
580610 rsync
581611
582- / * mark the stack overflow point before we call the actual NMI handler * /
612+ / * Mark the stack overflow point before we call the actual NMI handler * /
583613 movi a0 , NMIHandlerStack
584614 movi a2 , NMI_STACK_CANARY
585615 s32i a2 , a0 , 0x00
586616
617+ / * Switch the load/store error handler stack. * /
618+ movi a2 , LoadStoreErrorHandlerStackPointer
619+ l32i a3 , a2 , 0
620+ addi a3 , a3 , LoadStoreErrorHandlerStackFrameSize
621+ s32i a3 , a2 , 0
622+
587623 call0 sdk_wDev_ProcessFiq
588624
589- / * verify we didn't overflow * /
625+ / * Verify we didn't overflow * /
590626 movi a0 , NMIHandlerStack
591627 l32i a3 , a0 , 0
592628 movi a2 , NMI_STACK_CANARY
593629 bne a3 , a2 , .NMIFatalStackOverflow
594630
631+ / * Restore the load/store error handler stack. * /
632+ movi a2 , LoadStoreErrorHandlerStackPointer
633+ l32i a3 , a2 , 0
634+ addi a3 , a3 , - LoadStoreErrorHandlerStackFrameSize
635+ s32i a3 , a2 , 0
636+
595637 l32i a0 , sp , 0x3c
596638 wsr a0 , sar
597639 l32i a0 , sp , 0x38
0 commit comments