riscv_syscall.S: Fix a massive bug in syscall dispatch logic

There is an enormous error in the system call dispatch logic; if a task
is inside a critical section (local interrupts disabled) there is a chance
that during a context switch when the task resumes, local interrupts are
erroneously ENABLED. This obviously leads to unexpected crashes and such.

This happens when the CPU status has Previous Interrupt Enable (PIE) set
to 1, even though Interrupt Enable (IE) is set to 0.

When the system call returns via ERET, the CPU sets PIE->IE and if PIE=1
interrupts get enabled.

This is fixed easily by explicitly CLEARING PIE from the register save
area, if IE=0 when the system call was started.
This commit is contained in:
Ville Juven 2024-11-08 10:58:20 +02:00 committed by Alan C. Assis
parent db31e56957
commit 65cfd8a6ca

View file

@ -96,8 +96,13 @@ sys_call6:
and s0, s0, s1
li s1, STATUS_PIE /* set PIE */
or s0, s0, s1
j 2f
1:
1:
li s1, ~STATUS_PIE /* else: clear PIE */
and s0, s0, s1
2:
/* Set previous privilege, we are in privileged mode now */
li s1, STATUS_PPP /* set previous privilege */