[xtensa-cvscommit] linux/arch/xtensa/kernel vectors.S,1.4,1.5 handlers.S,1.9,1.10 sys.S,1.1.1.1,1.2
Brought to you by:
zankel
|
From: <joe...@us...> - 2003-01-30 23:55:32
|
Update of /cvsroot/xtensa/linux/arch/xtensa/kernel
In directory sc8-pr-cvs1:/tmp/cvs-serv30731/arch/xtensa/kernel
Modified Files:
vectors.S handlers.S sys.S
Log Message:
Fixed a bug that hangs the kernel. We were improperly handling double exceptions that occurred during the handling of a window underflow exception.
Index: vectors.S
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/vectors.S,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** vectors.S 29 Jan 2003 06:18:00 -0000 1.4
--- vectors.S 30 Jan 2003 23:55:26 -0000 1.5
***************
*** 131,135 ****
_bltu a0, a2, 1f
addi a2, a2, XSHAL_WINDOW_VECTORS_SIZE
! _bltu a0, a2, find_handler
/* Occasionally, the kernel expects a double exception to
--- 131,135 ----
_bltu a0, a2, 1f
addi a2, a2, XSHAL_WINDOW_VECTORS_SIZE
! _bltu a0, a2, .Ldouble_in_wvec
/* Occasionally, the kernel expects a double exception to
***************
*** 147,151 ****
* fixup routine. If the variable TABLE_FIXUP is zero, the
* kernel is in trouble. If the variable is nonzero, this
! * handler jumps to the instruction that the variable
* addresses.
*
--- 147,151 ----
* fixup routine. If the variable TABLE_FIXUP is zero, the
* kernel is in trouble. If the variable is nonzero, this
! * handler jumps to the instruction that the TABLE_FIXUP
* addresses.
*
***************
*** 165,208 ****
*/
! 1: l32i a2, a1, TABLE_FIXUP
! beqz a2, CriticalExc
! jx a2
! /* The double exception did occur within a window exception
! * handler. All entry conditions below say "All other
! * registers contain their original values." These values
! * usually are not user values, but kernel values, since
! * the double exception will return to the kernel handler,
! * not the user code.
*
* find_handler has some entry conditions, but these are met
! * by the Double Exception Vector code, not the routines that
! * register find_handler with TABLE_FIXUP. They are:
*
* a0 is undefined
* a1 = &exception_handlers[0]
* EXCSAVE_1 contains original a1
! * a2 is undefined
* [ EXCSAVE_1 + TABLE_SAVEA2 ] contains original a2
* All other registers contain their original values.
*
* We setup the following conditions for the registered
! * handler:
*
* a0 is undefined
* DEPC contains original a0
* DEPC saved in [ EXCSAVE_1 + TABLE_SAVEA0 ]
* All other registers contain their original values.
*/
.global find_handler
find_handler:
rsr a0, EXCCAUSE
- l32i a2, a1, TABLE_SAVEA2 // restore a2 (in slot)
addx4 a0, a0, a1
l32i a0, a0, TABLE_OFS + EXC_CODE_DOUBLE*4 // load handler addr
xsr a1, EXCSAVE_1 // restore a1
jx a0 // jump to handler
-
--- 165,218 ----
*/
! 1: l32i a0, a1, TABLE_FIXUP
! beqz a0, CriticalExc
! movi a2, ( 0 << EXCTYPE_DOUBLE_WIND_SHIFT )
! jx a0
!
! /* Control branches to .Ldouble_in_wvec when the double
! * exception occurred within a window exception. This entry
! * point sets a2 to indicate this condition for handle_double,
! * then falls through to find_handler. Exceptions that occur
! * outside a window exception will fall into the TABLE_FIXUP
! * code, which always clears a2 for the handler.
! *
! * The entry conditions below say "All other registers contain
! * their original values." These values usually are not user
! * values, but kernel values, since the double exception will
! * return to some kernel handler, not the user code.
*
* find_handler has some entry conditions, but these are met
! * by the Double Exception Vector code above, not the routines
! * that register handlers with TABLE_FIXUP. They are:
*
* a0 is undefined
* a1 = &exception_handlers[0]
* EXCSAVE_1 contains original a1
! * a2 sets the EXCTYPE_DOUBLE_WIND_SHIFT bit if in window vector, 0 otherwise.
* [ EXCSAVE_1 + TABLE_SAVEA2 ] contains original a2
* All other registers contain their original values.
*
* We setup the following conditions for the registered
! * handler (probably handle_double):
*
* a0 is undefined
+ * a2 sets the EXCTYPE_DOUBLE_WIND_SHIFT bit if in window vector, 0 otherwise.
* DEPC contains original a0
* DEPC saved in [ EXCSAVE_1 + TABLE_SAVEA0 ]
+ * [ EXCSAVE_1 + TABLE_SAVEA2 ] contains original a2
* All other registers contain their original values.
*/
.global find_handler
+
+ .Ldouble_in_wvec:
+ movi a2, ( 1 << EXCTYPE_DOUBLE_WIND_SHIFT )
find_handler:
rsr a0, EXCCAUSE
addx4 a0, a0, a1
l32i a0, a0, TABLE_OFS + EXC_CODE_DOUBLE*4 // load handler addr
xsr a1, EXCSAVE_1 // restore a1
jx a0 // jump to handler
Index: handlers.S
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/handlers.S,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** handlers.S 29 Jan 2003 06:17:59 -0000 1.9
--- handlers.S 30 Jan 2003 23:55:26 -0000 1.10
***************
*** 128,133 ****
--- 128,135 ----
*
* a0 is undefined (okay, it contains handle_double)
+ * a2 sets the EXCTYPE_DOUBLE_WIND_SHIFT bit if in window vector, 0 otherwise.
* DEPC contains original a0
* DEPC saved in [ EXCSAVE_1 + TABLE_SAVEA0 ]
+ * [ EXCSAVE_1 + TABLE_SAVEA2 ] contains original a2
* All other register contain their original values.
*/
***************
*** 145,149 ****
bbci.l a0, PS_PROGSTACK_SHIFT, doubleram_kernel // stacked (kernel) mode?
! /* Program (user) mode, so switch stack pointers. Get pointer
* to kernel stack, pre-decremented by 16+PT_SIZE */
--- 147,151 ----
bbci.l a0, PS_PROGSTACK_SHIFT, doubleram_kernel // stacked (kernel) mode?
! /* User mode, so switch stack pointers. Get pointer
* to kernel stack, pre-decremented by 16+PT_SIZE */
***************
*** 166,180 ****
mov a1, a0 // set sp to system stack
/* Now unshuffle the way state was saved in the vector, and save
! * state that is specific to exceptions in window handlers.
! */
xsr a1, EXCSAVE_1 // a1 <-- ptr to handler table, save a1
! /* slot */
l32i a0, a1, TABLE_SAVEA0 // get saved DEPC
xsr a1, EXCSAVE_1 // restore a1, save table ptr
/* slot */
s32i a0, a1, PT_DEPC // store DEPC in exc stack frame
#if 0
/* XTFIXME: For now, don't restart anything. Just get it to
--- 168,253 ----
mov a1, a0 // set sp to system stack
+ /* Branch if the double exception happened during a window
+ * exception handler. */
+
+ bnez a2, double_convert
+
+ double_noconversion:
+ /* Compute the exception type. PS (in a0) indicates user vs
+ * kernel. MISC_REG_0 indicates whether the double exception
+ * occurred in the window vector. */
+
+ movi a0, EXCTYPE_DOUBLE_KERNEL
+ bbci.l a0, PS_PROGSTACK_SHIFT, 1f // branch if kernel mode
+ movi a0, EXCTYPE_DOUBLE_USER
+ 1: or a2, a2, a0 // add in window vector bit
+ // (may be zero)
+
/* Now unshuffle the way state was saved in the vector, and save
! * state that is specific to exceptions in window handlers. */
xsr a1, EXCSAVE_1 // a1 <-- ptr to handler table, save a1
! wsr a2, MISC_REG_0 // save off exctype
l32i a0, a1, TABLE_SAVEA0 // get saved DEPC
+ l32i a2, a1, TABLE_SAVEA2 // get original a2
xsr a1, EXCSAVE_1 // restore a1, save table ptr
/* slot */
s32i a0, a1, PT_DEPC // store DEPC in exc stack frame
+ /* Load up the exctype and jump to common exception handling. */
+
+ rsr a0, MISC_REG_0
+ j _excCommonException
+
+
+ double_convert:
+ /* We need DEPC to distinguish between overflows and
+ * underflows. It is currently saved in TABLE_SAVEA0.
+ * Did the double exception occur in a window overflow or
+ * underflow? We restart underflows, but not overflows. */
+
+ xsr a1, EXCSAVE_1 // a1 <-- exception_handlers
+ l32i a0, a1, TABLE_SAVEA0 // load DEPC
+ xsr a1, EXCSAVE_1 // a1 <-- kernel stack pointer
+ bbci.l a0, 6, double_noconversion // branch if window overflow
+
+ /* Restart window underflow exception.
+ * Just set WINDOWBASE to PS.OWB. This is feasible for underflows
+ * because registers are available to do this. */
+
+ wsr a1, DEPC // save kernel stack ptr across window change
+ // (out of scope a0 is clobbered)
+ rsr a0, PS // get PS
+ l32i a1, a1, PT_AREG1 // restore a1 of this window
+ // (not needed but might help debugging)
+ extui a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+ wsr a0, WINDOWBASE // WB <-- PS.OWB
+ rsync
+ xsr a0, DEPC // save a0 in DEPC, restore kernel stack ptr
+ /* slot */
+ s32i a1, a0, PT_AREG1 // save a1 of active window
+ mov a1, a0 // set kernel stack ptr
+
+ /* We ignore the out-of-scope value of a2 still in TABLE_SAVEA2. */
+
+ /* Use PS to mark proper exception type. Note that since we
+ * are restarting the window underflow, we want to change the
+ * exception type from double to user or kernel. This change
+ * will trigger the use of "rfe" instead of "rfde" when
+ * exception processing is complete.
+ */
+
+ rsr a0, PS // get PS
+ /* slot */
+ bbci.l a0, PS_PROGSTACK_SHIFT, 1f // stacked (kernel) mode?
+
+ movi a0, EXCTYPE_USER // mark exception as "double-window-user"
+ j _excCommonException // jump to common exception handling
+
+ 1: movi a0, EXCTYPE_KERNEL // mark exception as "double-window-kernel"
+ j _excCommonException // jump to common exception handling
+
+
+
#if 0
/* XTFIXME: For now, don't restart anything. Just get it to
***************
*** 237,256 ****
- #ifndef RESTART_OVERFLOW
- restart_overflow:
- #endif
-
- /* Use PS to mark proper exception type: */
- rsr a0, PS // get PS
- /* slot */
- bbci.l a0, PS_PROGSTACK_SHIFT, 1f // stacked (kernel) mode?
-
- movi a0, EXCTYPE_DOUBLE_WIND_USER // mark exception as "double-window-user"
- j _excCommonException // jump to common exception handling
-
- 1: movi a0, EXCTYPE_DOUBLE_WIND_KERNEL // mark exception as "double-window-kernel"
- j _excCommonException // jump to common exception handling
-
-
#ifdef RESTART_OVERFLOW
restart_overflow:
--- 310,313 ----
***************
*** 582,588 ****
* interrupts which we don't currently do], for user
* exceptions we might have more leeway but we leave it as is
! * for now.) */
!
! /* Here, a0 still contains exception type. Type values are
* such that bit EXCTYPE_QUICKSPILL_SHIFT of each value is
* clear if all live register windows must be spilled for that
--- 639,645 ----
* interrupts which we don't currently do], for user
* exceptions we might have more leeway but we leave it as is
! * for now.)
! *
! * Here, a0 still contains exception type. Type values are
* such that bit EXCTYPE_QUICKSPILL_SHIFT of each value is
* clear if all live register windows must be spilled for that
***************
*** 610,617 ****
* PS.EXCM = 1
* a0 thru a3 saved already
! * a4 thru a15 valid
! * a0,a2,a3 undefined
* a1 = current PS pointing to exception frame
! * WINDOWSTART[WINDOWBASE] = 1 ???
* LCOUNT = 0
*
--- 667,675 ----
* PS.EXCM = 1
* a0 thru a3 saved already
! * a0,a2 undefined
* a1 = current PS pointing to exception frame
! * a3 has WINDOWSTART
! * a4 thru a15 valid
! * WINDOWSTART[WINDOWBASE] = 1
* LCOUNT = 0
*
***************
*** 807,810 ****
--- 865,869 ----
// a3 = 0 .. WSBITS-4 (number of panes to save, other than current window's 4)
ut_save:
+
s32i a3, a1, PT_WMASK // save this number, rather than recompute it on restore
***************
*** 818,822 ****
#if 1
j simple_save_end
-
simple_save:
rotw -1 // a2,a3 become a6,a7
--- 877,880 ----
***************
*** 1552,1563 ****
excdone:
! /* Return from user/kernel exception, or double exception?
! * Branch if double exception occurred (uncommon case).
*/
! #if (EXCTYPE_DOUBLE_WIND_USER > EXCTYPE_DOUBLE_WIND_KERNEL)
! #error Bad assumption by next instruction.
! #endif
! bgeui a0, EXCTYPE_DOUBLE_WIND_USER, 4f
l32i a0, a1, PT_AREG0 // restore a0
--- 1610,1620 ----
excdone:
! /* Return from the exception. Two cases:
! *
! * 1. Return from double exception
! * 2. Return from user or kernel exception (common case)
*/
! bbsi.l a0, EXCTYPE_DOUBLE_SHIFT, 4f
l32i a0, a1, PT_AREG0 // restore a0
***************
*** 1565,1582 ****
rfe
-
- /* Control comes here only when returning from double
- * exceptions that happened in a window-overflow handler.
- * (Double exceptions occuring in window-underflow handlers
- * are converted to EXCTYPE_{USER,KERNEL} exceptions.)
- * Restarting window overflows is not yet implemented, so we
- * must "return from double exception" (rfde) into the
- * window-overflow handler.
- */
-
4: l32i a0, a1, PT_AREG0 // restore a0
l32i a1, a1, PT_AREG1 // restore a1
rfde
-
--- 1622,1628 ----
Index: sys.S
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/sys.S,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -C2 -d -r1.1.1.1 -r1.2
*** sys.S 28 Aug 2002 16:10:14 -0000 1.1.1.1
--- sys.S 30 Jan 2003 23:55:27 -0000 1.2
***************
*** 814,818 ****
s32i a0, a1, PT_DEPC // store DEPC in ESF
! movi a0, EXCTYPE_DOUBLE_WIND_KERNEL
j _excCommonException
--- 814,818 ----
s32i a0, a1, PT_DEPC // store DEPC in ESF
! movi a0, EXCTYPE_DOUBLE_KERNEL
j _excCommonException
|