[xtensa-cvscommit] linux/arch/xtensa/kernel handlers.S,1.6,1.7 traps.c,1.3,1.4 vectors.S,1.1.1.1,1.2
Brought to you by:
zankel
|
From: <joe...@us...> - 2002-11-11 22:25:29
|
Update of /cvsroot/xtensa/linux/arch/xtensa/kernel In directory usw-pr-cvs1:/tmp/cvs-serv18841/kernel Modified Files: handlers.S traps.c vectors.S Log Message: We need to backout some exception-handling cleverness that packs state information into unused least-significant bits of a table pointer. We still use EXCSAVE_1 as the table pointer, but when we introduce unaligned exceptions (soon), that table pointer must always be on a 32-bit boundary. Index: handlers.S =================================================================== RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/handlers.S,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** handlers.S 8 Nov 2002 21:39:28 -0000 1.6 --- handlers.S 11 Nov 2002 22:25:25 -0000 1.7 *************** *** 87,144 **** - /* - EXCSAVE_1 Usage Conventions - - The new XSR instruction, introduced at the same time as the PS.EXCM - bit and other MMU related additions and changes, adds more flexibility - to how EXCSAVE_1 can be used. - - This section describes the conventions adopted for using EXCSAVE_1 in - this kernel implementation. - - EXCSAVE_1 is divided into 2 fields: - - bits 31-2 a 4-byte aligned pointer - bits 1-0 recovery/handling mode - - The contents of the pointer depends on the mode bits as follows: - - bit 1 bit 0 pointer - ----- ----- ------- - 0 0 invalid EXCSAVE_1 value, jump to local critical handling - 0 1 pointer to L32E/S32E recovery routine - 1 0 pointer to RAM vector table - 1 1 pointer to ROM vector table - - Normally, EXCSAVE_1 is set to point to a vector table (e.g., the - first-level dispatch table). The handling code for RAM vector tables - is more efficient (the vector table includes a temporary save area - that can be accessed immediately, rather than having to resolve the - type of exception first) and allows saving the full EPC_1 to provide - more detail on where a window handler got an exception (useful for - debugging), and thus is preferred. However, ROM startup or memory - diagnostic functions may need or want the vector to be placed in ROM, - and have fewer requirements for efficiency etc, so the ROM vector - table option is provided. - - When exception handling code (other than window handlers) executes - L32E and/or S32E instructions, it must be ready to handle exceptions - occurring during these instructions. What must be done when such a - (double) exception occurs is specific to the code executing L32E/S32E. - The recovery code to execute is specified via EXCSAVE_1, by setting a1 - as follows then exchanging it (via xsr) with EXCSAVE_1 just prior to - executing L32E/S32E, then exchanging it again immediately after. a1 - should thus contain the usual EXCSAVE_1 value during execution of - L32E/S32E. The recovery value of EXCSAVE_1 (set first in a1) is: bit - 1 set, bit 0 clear, and pointer set to the recovery routine. When the - double exception vector sees this EXCSAVE_1 mode setting, it simply - jumps to the recovery routine. See the double exception vector - implementation for more details on register conventions. Note that a1 - was chosen because its 2 lsbits are usually 0, so if an exception - occurs when a1 was temporarily saved in EXCSAVE_1, chances are that - will be detected as a critical condition and be handled as such. - */ - - /******************************************************************* * EXCEPTION STACK FRAME FORMAT --- 87,90 ---- Index: traps.c =================================================================== RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/traps.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** traps.c 10 Oct 2002 17:01:17 -0000 1.3 --- traps.c 11 Nov 2002 22:25:25 -0000 1.4 *************** *** 425,429 **** * Initialize EXCSAVE_1: */ ! i = (unsigned long)exception_handlers + 2; __asm__ __volatile__( "wsr %0, "XTSTR(EXCSAVE_1)"\n" : --- 425,429 ---- * Initialize EXCSAVE_1: */ ! i = (unsigned long)exception_handlers; __asm__ __volatile__( "wsr %0, "XTSTR(EXCSAVE_1)"\n" : Index: vectors.S =================================================================== RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/vectors.S,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** vectors.S 28 Aug 2002 16:10:14 -0000 1.1.1.1 --- vectors.S 11 Nov 2002 22:25:25 -0000 1.2 *************** *** 75,131 **** /* - EXCSAVE_1 Usage Conventions - - The new XSR instruction, introduced at the same time as the PS.EXCM - bit and other MMU related additions and changes, adds more flexibility - to how EXCSAVE_1 can be used. - - This section describes the conventions adopted for using EXCSAVE_1 in - this kernel implementation. - - EXCSAVE_1 is divided into 2 fields: - - bits 31-2 a 4-byte aligned pointer - bits 1-0 recovery/handling mode - - The contents of the pointer depends on the mode bits as follows: - - bit 1 bit 0 pointer - ----- ----- ------- - 0 0 invalid EXCSAVE_1 value, jump to local critical handling - 0 1 pointer to L32E/S32E recovery routine - 1 0 pointer to RAM vector table - 1 1 pointer to ROM vector table - - Normally, EXCSAVE_1 is set to point to a vector table (e.g., the - first-level dispatch table). The handling code for RAM vector tables - is more efficient (the vector table includes a temporary save area - that can be accessed immediately, rather than having to resolve the - type of exception first) and allows saving the full EPC_1 to provide - more detail on where a window handler got an exception (useful for - debugging), and thus is preferred. However, ROM startup or memory - diagnostic functions may need or want the vector to be placed in ROM, - and have fewer requirements for efficiency etc, so the ROM vector - table option is provided. - - When exception handling code (other than window handlers) executes - L32E and/or S32E instructions, it must be ready to handle exceptions - occurring during these instructions. What must be done when such a - (double) exception occurs is specific to the code executing L32E/S32E. - The recovery code to execute is specified via EXCSAVE_1, by setting a1 - as follows then exchanging it (via xsr) with EXCSAVE_1 just prior to - executing L32E/S32E, then exchanging it again immediately after. a1 - should thus contain the usual EXCSAVE_1 value during execution of - L32E/S32E. The recovery value of EXCSAVE_1 (set first in a1) is: bit - 1 set, bit 0 clear, and pointer set to the recovery routine. When the - double exception vector sees this EXCSAVE_1 mode setting, it simply - jumps to the recovery routine. See the double exception vector - implementation for more details on register conventions. Note that a1 - was chosen because its 2 lsbits are usually 0, so if an exception - occurs when a1 was temporarily saved in EXCSAVE_1, chances are that - will be detected as a critical condition and be handled as such. - */ - - /* _DoubleExceptionVector --- 75,78 ---- *************** *** 157,162 **** _DoubleExceptionVector: - /* See comments above for conventions on the use of EXCSAVE_1. */ - /* Various TABLE_FIXUP functions depend on specific actions in * the DoubleExceptionVector. If you change this code, you also --- 104,107 ---- *************** *** 164,225 **** */ ! /* XTFIXME: Support for unaligned exceptions is coming. We ! need to remove the functionality of using the lower two bits ! of the EXCSAVE_1 pointer as bit flags. */ ! ! xsr a1, EXCSAVE_1 // get EXCSAVE_1, save a1 ! xsr a0, DEPC // get return PC, save a0 ! _bbci.l a1, 1, recover_or_crit // jump to L32E/S32E recovery code or critical handling ! _bbsi.l a1, 0, slowdeh // EXCSAVE_1 points to ROM, not RAM, use slower handler ! // that doesn't requires as many temp registers ! ! /* ! * Okay, now the slightly tricky part. ! * We want to resolve whether the double exception occurred ! * within a window exception handler. But *without* corrupting ! * any registers, or having to store registers to memory (which ! * would require the vector table to be in RAM so we could have ! * a save area next to it; and which isn't very safe in a double ! * exception handler in any case). ! * ! * Offset Size Vector Addr bits 8:6 ! * 0x000 64 Overflow4 000 ! * 0x040 64 Underflow4 001 ! * 0x080 64 Overflow8 010 ! * 0x0C0 64 Underflow8 011 ! * 0x100 64 Overflow12 100 ! * 0x140 64 Underflow12 101 ! * ! * So we use the following techniques: ! * - we assume the double exception occurred during ! * processing of a window exception if EPC_1 points ! * within one of the window vectors (see offsets above; ! * base of window vectors is configuration specific) ! * - double exceptions NOT occurring as part of ! * processing a window exception are not a normal ! * or expected occurrence, and are generally an ! * indication of faulty OS code, or of an unrecoverable ! * situation; EPC_1 and EXCCAUSE of the context in ! * which the double exception occurred are likely ! * irrecoverably lost (and it isn't easy to find ! * out whether they were saved, etc); ! * SO, such double exceptions are considered ! * critical exceptions, where some state has ! * already been corrupted, so corrupting a bit ! * more state is probably okay (ie. the handling ! * of a critical exception will typically do something ! * drastic like reset the system after perhaps ! * recording the event, in minimal steps, because ! * the system is considered unstable at that point) ! * - we resolve the type of window exception from ! * EPC_1 lower bits (which we can do without needing ! * temporary registers, thanks to XSR), assuming ! * the previous context was a window exception, ! * and process it enough to get a temporary ! * register, which we then use to verify whether ! * it really was a window exception; if not, and ! * we clobbered a register, that's pretty much ! * okay since what we have is a critical exception. ! */ /* The vector table must be preceded by a save area (which --- 109,114 ---- */ ! xsr a1, EXCSAVE_1 // save a1, get dispatch table ! xsr a0, DEPC // save a0, get return PC /* The vector table must be preceded by a save area (which *************** *** 229,249 **** s32i a2, a1, TABLE_SAVEA2 // save a2 ! movi a2, XCHAL_WINDOW_VECTORS_VADDR // start of window exception vectors s32i a0, a1, TABLE_SAVEA0 // save DEPC ! /* Determine whether the double exception occurred within a ! * window exception handler. */ ! _bltu a0, a2, 1f // if PC precedes window vectors, jump to next test ! addi a2, a2, XSHAL_WINDOW_VECTORS_SIZE // end of window exception vectors area ! _bltu a0, a2, find_handler // if PC follows window vectors, fall thru to next test ! /* Occasionally, the kernel expects double exception to occur. ! * This usually happens when accessing user-space memory with ! * the user's permissions (l32e/s32e instructions). The ! * kernel state, though, is not always suitable for immediate ! * transfer of control to handle_double, where "normal" ! * exception processing occurs. * * The variable at TABLE_FIXUP offset from the pointer in --- 118,142 ---- s32i a2, a1, TABLE_SAVEA2 // save a2 ! movi a2, XCHAL_WINDOW_VECTORS_VADDR // start of window exc vectors s32i a0, a1, TABLE_SAVEA0 // save DEPC ! /* If the PC falls within the window-exception vectors area, ! * the exception occured within a window exception handler. ! * In this case, we jump to find_handler to handle the ! * exception. Otherwise, the PC falls outside this area ! * (before or after), and we fall through to test for the ! * TABLE_FIXUP case. */ ! _bltu a0, a2, 1f ! addi a2, a2, XSHAL_WINDOW_VECTORS_SIZE ! _bltu a0, a2, find_handler ! /* Occasionally, the kernel expects a double exception to ! * occur. This usually happens when accessing user-space ! * memory with the user's permissions (l32e/s32e ! * instructions). The kernel state, though, is not always ! * suitable for immediate transfer of control to ! * handle_double, where "normal" exception processing occurs. * * The variable at TABLE_FIXUP offset from the pointer in *************** *** 266,270 **** * * See the handle_alloca_user and spill_registers routines ! * for examples. */ --- 159,163 ---- * * See the handle_alloca_user and spill_registers routines ! * for example clients of TABLE_FIXUP. */ *************** *** 274,279 **** /* The double exception did occur within a window exception ! * handler or the alloca handler. The registered handler expects ! * the following: * * a0 is undefined --- 167,171 ---- /* The double exception did occur within a window exception ! * handler. The registered handler expects the following: * * a0 is undefined *************** *** 294,298 **** ! /* XTFIXME, Temp logic until we complete the double exception vector code. */ recover_or_crit: j 2f --- 186,193 ---- ! /* XTFIXME: recover_or_crit and slowdeg are dead code now, but useful ! * as an alternate LED msg example. We still use CriticalExc as a ! * sort of panic indicator. */ ! recover_or_crit: j 2f *************** *** 373,377 **** --- 268,327 ---- /* XTFIXME: The following code is incomplete, but has many * ideas for optimizing this handler. + + XTFIXME: To-do List for double exception vector: + + 1. Provide the ability to place the vector table in ROM. Currently, + it must be located in RAM because we assume some temporary save area + immediately preceding the table itself. Here are some old comments + with some ideas: + + * Okay, now the slightly tricky part. + * We want to resolve whether the double exception occurred + * within a window exception handler. But *without* corrupting + * any registers, or having to store registers to memory (which + * would require the vector table to be in RAM so we could have + * a save area next to it; and which isn't very safe in a double + * exception handler in any case). + * + * Offset Size Vector Addr bits 8:6 + * 0x000 64 Overflow4 000 + * 0x040 64 Underflow4 001 + * 0x080 64 Overflow8 010 + * 0x0C0 64 Underflow8 011 + * 0x100 64 Overflow12 100 + * 0x140 64 Underflow12 101 + * + * So we use the following techniques: + * - we assume the double exception occurred during + * processing of a window exception if EPC_1 points + * within one of the window vectors (see offsets above; + * base of window vectors is configuration specific) + * - double exceptions NOT occurring as part of + * processing a window exception are not a normal + * or expected occurrence, and are generally an + * indication of faulty OS code, or of an unrecoverable + * situation; EPC_1 and EXCCAUSE of the context in + * which the double exception occurred are likely + * irrecoverably lost (and it isn't easy to find + * out whether they were saved, etc); + * SO, such double exceptions are considered + * critical exceptions, where some state has + * already been corrupted, so corrupting a bit + * more state is probably okay (ie. the handling + * of a critical exception will typically do something + * drastic like reset the system after perhaps + * recording the event, in minimal steps, because + * the system is considered unstable at that point) + * - we resolve the type of window exception from + * EPC_1 lower bits (which we can do without needing + * temporary registers, thanks to XSR), assuming + * the previous context was a window exception, + * and process it enough to get a temporary + * register, which we then use to verify whether + * it really was a window exception; if not, and + * we clobbered a register, that's pretty much + * okay since what we have is a critical exception. */ + /* Underflows can always be restarted; test this case: */ |