|
@@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow:
|
|
|
beqz a2, 1f # if at start of vector, don't restore
|
|
|
|
|
|
addi a0, a0, -128
|
|
|
- bbsi a0, 8, 1f # don't restore except for overflow 8 and 12
|
|
|
- bbsi a0, 7, 2f
|
|
|
+ bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This fixup handler is for the extremely unlikely case where the
|
|
|
+ * overflow handler's reference thru a0 gets a hardware TLB refill
|
|
|
+ * that bumps out the (distinct, aliasing) TLB entry that mapped its
|
|
|
+ * prior references thru a9/a13, and where our reference now thru
|
|
|
+ * a9/a13 gets a 2nd-level miss exception (not hardware TLB refill).
|
|
|
+ */
|
|
|
+ movi a2, window_overflow_restore_a0_fixup
|
|
|
+ s32i a2, a3, EXC_TABLE_FIXUP
|
|
|
+ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
+ xsr a3, excsave1
|
|
|
+
|
|
|
+ bbsi.l a0, 7, 2f
|
|
|
|
|
|
/*
|
|
|
* Restore a0 as saved by _WindowOverflow8().
|
|
|
- *
|
|
|
- * FIXME: we really need a fixup handler for this L32E,
|
|
|
- * for the extremely unlikely case where the overflow handler's
|
|
|
- * reference thru a0 gets a hardware TLB refill that bumps out
|
|
|
- * the (distinct, aliasing) TLB entry that mapped its prior
|
|
|
- * references thru a9, and where our reference now thru a9
|
|
|
- * gets a 2nd-level miss exception (not hardware TLB refill).
|
|
|
*/
|
|
|
|
|
|
- l32e a2, a9, -16
|
|
|
- wsr a2, depc # replace the saved a0
|
|
|
- j 1f
|
|
|
+ l32e a0, a9, -16
|
|
|
+ wsr a0, depc # replace the saved a0
|
|
|
+ j 3f
|
|
|
|
|
|
2:
|
|
|
/*
|
|
|
* Restore a0 as saved by _WindowOverflow12().
|
|
|
- *
|
|
|
- * FIXME: we really need a fixup handler for this L32E,
|
|
|
- * for the extremely unlikely case where the overflow handler's
|
|
|
- * reference thru a0 gets a hardware TLB refill that bumps out
|
|
|
- * the (distinct, aliasing) TLB entry that mapped its prior
|
|
|
- * references thru a13, and where our reference now thru a13
|
|
|
- * gets a 2nd-level miss exception (not hardware TLB refill).
|
|
|
*/
|
|
|
|
|
|
- l32e a2, a13, -16
|
|
|
- wsr a2, depc # replace the saved a0
|
|
|
+ l32e a0, a13, -16
|
|
|
+ wsr a0, depc # replace the saved a0
|
|
|
+3:
|
|
|
+ xsr a3, excsave1
|
|
|
+ movi a0, 0
|
|
|
+ s32i a0, a3, EXC_TABLE_FIXUP
|
|
|
+ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
1:
|
|
|
/*
|
|
|
* Restore WindowBase while leaving all address registers restored.
|
|
@@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow:
|
|
|
|
|
|
s32i a0, a2, PT_DEPC
|
|
|
|
|
|
+_DoubleExceptionVector_handle_exception:
|
|
|
addx4 a0, a0, a3
|
|
|
l32i a0, a0, EXC_TABLE_FAST_USER
|
|
|
xsr a3, excsave1
|
|
@@ -464,10 +469,119 @@ _DoubleExceptionVector_WindowOverflow:
|
|
|
rotw -3
|
|
|
j 1b
|
|
|
|
|
|
- .end literal_prefix
|
|
|
|
|
|
ENDPROC(_DoubleExceptionVector)
|
|
|
|
|
|
+/*
|
|
|
+ * Fixup handler for TLB miss in double exception handler for window owerflow.
|
|
|
+ * We get here with windowbase set to the window that was being spilled and
|
|
|
+ * a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12
|
|
|
+ * (bit set) window.
|
|
|
+ *
|
|
|
+ * We do the following here:
|
|
|
+ * - go to the original window retaining a0 value;
|
|
|
+ * - set up exception stack to return back to appropriate a0 restore code
|
|
|
+ * (we'll need to rotate window back and there's no place to save this
|
|
|
+ * information, use different return address for that);
|
|
|
+ * - handle the exception;
|
|
|
+ * - go to the window that was being spilled;
|
|
|
+ * - set up window_overflow_restore_a0_fixup as a fixup routine;
|
|
|
+ * - reload a0;
|
|
|
+ * - restore the original window;
|
|
|
+ * - reset the default fixup routine;
|
|
|
+ * - return to user. By the time we get to this fixup handler all information
|
|
|
+ * about the conditions of the original double exception that happened in
|
|
|
+ * the window overflow handler is lost, so we just return to userspace to
|
|
|
+ * retry overflow from start.
|
|
|
+ *
|
|
|
+ * a0: value of depc, original value in depc
|
|
|
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
|
|
|
+ * a3: exctable, original value in excsave1
|
|
|
+ */
|
|
|
+
|
|
|
+ENTRY(window_overflow_restore_a0_fixup)
|
|
|
+
|
|
|
+ rsr a0, ps
|
|
|
+ extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH
|
|
|
+ rsr a2, windowbase
|
|
|
+ sub a0, a2, a0
|
|
|
+ extui a0, a0, 0, 3
|
|
|
+ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
+ xsr a3, excsave1
|
|
|
+
|
|
|
+ _beqi a0, 1, .Lhandle_1
|
|
|
+ _beqi a0, 3, .Lhandle_3
|
|
|
+
|
|
|
+ .macro overflow_fixup_handle_exception_pane n
|
|
|
+
|
|
|
+ rsr a0, depc
|
|
|
+ rotw -\n
|
|
|
+
|
|
|
+ xsr a3, excsave1
|
|
|
+ wsr a2, depc
|
|
|
+ l32i a2, a3, EXC_TABLE_KSTK
|
|
|
+ s32i a0, a2, PT_AREG0
|
|
|
+
|
|
|
+ movi a0, .Lrestore_\n
|
|
|
+ s32i a0, a2, PT_DEPC
|
|
|
+ rsr a0, exccause
|
|
|
+ j _DoubleExceptionVector_handle_exception
|
|
|
+
|
|
|
+ .endm
|
|
|
+
|
|
|
+ overflow_fixup_handle_exception_pane 2
|
|
|
+.Lhandle_1:
|
|
|
+ overflow_fixup_handle_exception_pane 1
|
|
|
+.Lhandle_3:
|
|
|
+ overflow_fixup_handle_exception_pane 3
|
|
|
+
|
|
|
+ .macro overflow_fixup_restore_a0_pane n
|
|
|
+
|
|
|
+ rotw \n
|
|
|
+ /* Need to preserve a0 value here to be able to handle exception
|
|
|
+ * that may occur on a0 reload from stack. It may occur because
|
|
|
+ * TLB miss handler may not be atomic and pointer to page table
|
|
|
+ * may be lost before we get here. There are no free registers,
|
|
|
+ * so we need to use EXC_TABLE_DOUBLE_SAVE area.
|
|
|
+ */
|
|
|
+ xsr a3, excsave1
|
|
|
+ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
+ movi a2, window_overflow_restore_a0_fixup
|
|
|
+ s32i a2, a3, EXC_TABLE_FIXUP
|
|
|
+ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
+ xsr a3, excsave1
|
|
|
+ bbsi.l a0, 7, 1f
|
|
|
+ l32e a0, a9, -16
|
|
|
+ j 2f
|
|
|
+1:
|
|
|
+ l32e a0, a13, -16
|
|
|
+2:
|
|
|
+ rotw -\n
|
|
|
+
|
|
|
+ .endm
|
|
|
+
|
|
|
+.Lrestore_2:
|
|
|
+ overflow_fixup_restore_a0_pane 2
|
|
|
+
|
|
|
+.Lset_default_fixup:
|
|
|
+ xsr a3, excsave1
|
|
|
+ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
+ movi a2, 0
|
|
|
+ s32i a2, a3, EXC_TABLE_FIXUP
|
|
|
+ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
|
|
+ xsr a3, excsave1
|
|
|
+ rfe
|
|
|
+
|
|
|
+.Lrestore_1:
|
|
|
+ overflow_fixup_restore_a0_pane 1
|
|
|
+ j .Lset_default_fixup
|
|
|
+.Lrestore_3:
|
|
|
+ overflow_fixup_restore_a0_pane 3
|
|
|
+ j .Lset_default_fixup
|
|
|
+
|
|
|
+ENDPROC(window_overflow_restore_a0_fixup)
|
|
|
+
|
|
|
+ .end literal_prefix
|
|
|
/*
|
|
|
* Debug interrupt vector
|
|
|
*
|