tactcomplabs / rev

RISC-V SST CPU Component
Other
17 stars 21 forks source link

[FEATURE REQUEST] Support signal and trap handling #309

Open leekillough opened 2 months ago

leekillough commented 2 months ago

Rev Feature Request

Support Unix-like signals through ECALLs and RISC-V instruction traps, and allow the setting of RISC-V signal handlers. A simple test case could be a RISC-V code which sets a signal handler, raises the signal, and expects the handler to be called and then it return correctly to the program after it raised the signal.

Version of SST

All

Additional context

When events such as illegal instructions, segmentation faults, bus errors, etc. occur, then instead of calling SST's fatal(), a signal of SIGILL, SIGSEGV, SIGBUS, etc. should be raised.

When a signal is raised in the simulation, either by a ECALL to kill() or an event such as SIGSEGV, SIGBUS, SIGILL, etc., signals should be raised by setting a flag in RevCPU, which is similar to the way ECALLs are raised today, but since signals are process-wide and not per-thread, the flag should be in RevCPU to be global to all threads and cores.

The signals raised should be queued in RevCPU, and checked at the beginning at every clock tick, and handled like an ECALL is handled today if there are pending signals which are not masked, by saving the PC, blocking the raised signal and any signals set by sa_mask in the sigaction() syscall, simulating a signal handler call, and if / when the signal handler returns, restoring the state. (As an unusual way of returning from signal handlers, longjmp() can be used to change the PC and SP to another frame, but we don't need to support this initially.)

Later, pthread_kill() could be supported (see https://github.com/tactcomplabs/rev/issues/191 ), and in that case, if a pending signal's disposition is not to be ignored or to abort the process, then the signal handler should not be called before the current thread's instruction unless the target thread (hart) is equal to the current one. If the signal disposition is to abort the process, then the currently executing thread should abort immediately regardless of whether it equals the target thread.

An initial implementation of signal support should not interrupt the adoption of Proxy Kernels or other methods of handling system calls in Rev. It is more normal behavior for signals to be raised for illegal instructions, bus errors, or segmentation faults, and for there to be optional signal handlers for them, than it is for the simulator to always abort immediately. A test for these cases can be written.