Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/riscv/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ LDFLAGS += --gc-sections
ARFLAGS = r
LDSCRIPT = $(ARCH_DIR)/riscv32-qemu.ld

HAL_OBJS := boot.o hal.o muldiv.o
HAL_OBJS := boot.o hal.o muldiv.o entry.o
HAL_OBJS := $(addprefix $(BUILD_KERNEL_DIR)/,$(HAL_OBJS))
deps += $(HAL_OBJS:%.o=%.o.d)

Expand Down
42 changes: 42 additions & 0 deletions arch/riscv/entry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* RISC-V Kernel Entry Points
*
* This file implements architecture-specific entry mechanisms into the kernel,
* primarily the system call trap interface using the RISC-V ecall instruction.
*
* System Call Calling Convention (RISC-V ABI):
* - a7 (x17): System call number
* - a0 (x10): Argument 1 / Return value
* - a1 (x11): Argument 2
* - a2 (x12): Argument 3
*
* The ecall instruction triggers an environment call exception that transfers
* control to the M-mode exception handler (hal.c), which then dispatches to
* the appropriate system call implementation via the syscall table.
*/

#include <sys/syscall.h>

/* Architecture-specific syscall implementation using ecall trap.
* This overrides the weak symbol defined in kernel/syscall.c.
*/
int syscall(int num, void *arg1, void *arg2, void *arg3)
{
register int a0 asm("a0") = (int) arg1;
register int a1 asm("a1") = (int) arg2;
register int a2 asm("a2") = (int) arg3;
register int a7 asm("a7") = num;

/* Execute ecall instruction to trap into M-mode.
* The M-mode exception handler will:
* 1. Save the current task context
* 2. Dispatch to the syscall handler based on a7
* 3. Place the return value in a0
* 4. Restore context and return to user mode via mret
*/
asm volatile("ecall"
: "+r"(a0) /* a0 is both input (arg1) and output (retval) */
: "r"(a1), "r"(a2), "r"(a7)
: "memory");

return a0;
}
29 changes: 27 additions & 2 deletions arch/riscv/hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,31 @@ uint32_t do_trap(uint32_t cause, uint32_t epc, uint32_t isr_sp)
} else { /* Synchronous Exception */
uint32_t code = MCAUSE_GET_CODE(cause);

/* Handle ecall from U-mode - system calls */
if (code == MCAUSE_ECALL_UMODE) {
/* Advance mepc past the ecall instruction (4 bytes) */
uint32_t new_epc = epc + 4;
write_csr(mepc, new_epc);

uint32_t *isr_frame = (uint32_t *) isr_sp;
isr_frame[31] = new_epc;

/* Extract syscall arguments from ISR frame */
int syscall_num = isr_frame[15];
void *arg1 = (void *) isr_frame[8];
void *arg2 = (void *) isr_frame[9];
void *arg3 = (void *) isr_frame[10];

/* Dispatch to syscall handler */
extern int syscall(int num, void *arg1, void *arg2, void *arg3);
int retval = syscall(syscall_num, arg1, arg2, arg3);

/* Store return value */
isr_frame[8] = retval;

return isr_sp;
}

/* Handle ecall from M-mode - used for yielding in preemptive mode */
if (code == MCAUSE_ECALL_MMODE) {
/* Advance mepc past the ecall instruction (4 bytes) */
Expand Down Expand Up @@ -759,12 +784,12 @@ void hal_context_init(jmp_buf *ctx, size_t sp, size_t ss, size_t ra)
/* Set the essential registers for a new task:
* - SP is set to the prepared top of the task's stack.
* - RA is set to the task's entry point.
* - mstatus is set to enable interrupts and ensure machine mode.
* - mstatus is set to enable interrupts and ensure user mode.
*
* When this context is first restored, the ret instruction will effectively
* jump to this entry point, starting the task.
*/
(*ctx)[CONTEXT_SP] = (uint32_t) stack_top;
(*ctx)[CONTEXT_RA] = (uint32_t) ra;
(*ctx)[CONTEXT_MSTATUS] = MSTATUS_MIE | MSTATUS_MPP_MACH;
(*ctx)[CONTEXT_MSTATUS] = MSTATUS_MIE | MSTATUS_MPP_USER;
}
2 changes: 1 addition & 1 deletion kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static const void *syscall_table[SYS_COUNT] = {SYSCALL_TABLE};
#undef _

/* Weak, generic dispatcher */
int syscall(int num, void *a1, void *a2, void *a3)
__attribute__((weak)) int syscall(int num, void *a1, void *a2, void *a3)
{
if (unlikely(num <= 0 || num >= SYS_COUNT))
return -ENOSYS;
Expand Down
Loading