Skip to content

Commit 03adecd

Browse files
committed
Handle U-mode ecall for syscall dispatch
Adds exception handler for U-mode ecall instructions to dispatch system calls. Extracts syscall number and arguments from the saved register context and returns results through the same mechanism. This design enables privilege separation by allowing user-mode tasks to request kernel services without direct access to privileged operations, addressing the security issue where tasks could bypass isolation by executing in M-mode.
1 parent f36e7c5 commit 03adecd

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

arch/riscv/hal.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,31 @@ uint32_t do_trap(uint32_t cause, uint32_t epc, uint32_t isr_sp)
321321
} else { /* Synchronous Exception */
322322
uint32_t code = MCAUSE_GET_CODE(cause);
323323

324+
/* Handle ecall from U-mode - system calls */
325+
if (code == MCAUSE_ECALL_UMODE) {
326+
/* Advance mepc past the ecall instruction (4 bytes) */
327+
uint32_t new_epc = epc + 4;
328+
write_csr(mepc, new_epc);
329+
330+
uint32_t *isr_frame = (uint32_t *) isr_sp;
331+
isr_frame[31] = new_epc;
332+
333+
/* Extract syscall arguments from ISR frame */
334+
int syscall_num = isr_frame[15];
335+
void *arg1 = (void *) isr_frame[8];
336+
void *arg2 = (void *) isr_frame[9];
337+
void *arg3 = (void *) isr_frame[10];
338+
339+
/* Dispatch to syscall handler */
340+
extern int syscall(int num, void *arg1, void *arg2, void *arg3);
341+
int retval = syscall(syscall_num, arg1, arg2, arg3);
342+
343+
/* Store return value */
344+
isr_frame[8] = retval;
345+
346+
return isr_sp;
347+
}
348+
324349
/* Handle ecall from M-mode - used for yielding in preemptive mode */
325350
if (code == MCAUSE_ECALL_MMODE) {
326351
/* Advance mepc past the ecall instruction (4 bytes) */

0 commit comments

Comments
 (0)