Open jmgomez-IAA opened 4 years ago
m.rosenfelder 10 years ago Permalink Hey there, ... If I may give you one advice: Don't write your trap handler in C code!
The compiler is intended for code generation for applications and not for trap handlers. This implies that it uses many conventions from the SPARC V8 ABI, especially concerning the register usage. For example, the SPARC ABI says that the register %g1 is not expected to retain its content during a procedure call. The called procedure is allowed to overwrite the content. But a trap handler should preserve any registers visible to an application, so it should also preserve %g1! Thus, if you let the compiler choose in which register to put your local variables in your C trap procedure, you cannot guarantee that %g1 is being preserved.
Other problems are the output registers %o0 to %o7. The SPARC register window is circular yielding that the window that is being rotated to by the hardware when the trap occurs may be the last window that is free. Its output registers overlap with the input registers of the last window. "Last" in this contexts means the window that is the oldest one in the register window of the processor that has not yet been saved onto the stack. Thus, you may only use the outs if you are sure that there is at least one additional free register window available. That means that your trap code should either avoid using the outs at all or you should check the current window pointer (CWP) and the window invalid mask (WIM) if there is another free window available. Only then you are sure that you may use the output registers in your trap code!
Again, the compiler assumes that it can use all outs as it usually can do for application code. This may overwrite other register data and this kind of error is very hard to spot. It is only visible if a trap occurs after your procedure call chain has reached a certain depth (i.e. no more additional register windows free for the application, i.e. any SAVE instruction will cause an overflow trap). It may work for most cases but will sporadically produre strange behaviour. I experienced this kind of bug in my current project some time ago and after long debugging sessions it turned out that it was not my code that was erronous but the trap handler that was written by someone else who was unable to write trap handler code properly.
And - of course - don't use any input registers. These are the output registers of the application where the trap occurs and must be reserved by the trap handler. As the HW is putting the PC and the nPC of the trap in registers %l1 and %l2 of the new window when a trap occurs, the only six registers that your trap handling code may safely use at the beginning are %l0, %l3-%l7. You may then check if there is another register window free and if it is may use additionally the eight output registers as mentioned above.
A third issue with trap handlers are traps itself. If a trap occurs, the processor automatically disables traps, i.e. ET (enable traps) in the PSR (processor status register) is set to zero. That is because the handling of the current trap shall not be interrupted by other traps (especially interrupts) before it didn't finish the current one. Generating another trap while ET is zero will cause the processor to enter error mode (as defined in the SPARC V8 instruction set architecture). This is very dangerous because what follows then is undefined behaviour! The SPARC V8 ISA even mentions that the hardware may typically trigger an external reset for the processor which means that all information of the system is lost! Thus, causing traps itself while being in a trap handler must absolutely b e avoided!
Therefore, you cannot use the normal register over- or underflow handlers. So don't blindly execute SAVE or RESTORE instructions without checking the WIM before. Don't execute any memory load- or store-instructions if you have an MMU and it is enabled before not checking the page tables (use the LDA instruction with ASI bypass for physical memory addresses to walk the page tables in software before doing ANY normal memory access).
In summary, traps are evil on the SPARC. Write them yourself in assembler and not in C. Or even better: Don't write your own trap handlers if you are unsure of your capabilities and use tested and proven code from someone else (e.g. the Linux kernel). Or try to solve your problems in other ways and avoid writing your own trap handlers if possible. You will shoot youself in the foot if your are not very careful!
regards, matthias
Reed Solomon
https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders C: http://www.eccpage.com/
Python: https://github.com/tomerfiliba/reedsolomon
Matlab: https://es.mathworks.com/help/comm/ug/error-detection-and-correction.html#bsxtjo1
Java: https://github.com/Backblaze/JavaReedSolomon/
Cpp: https://github.com/ArashPartow/schifra