System call | System call number |
fork | 1 |
exit | 2 |
wait | 3 |
pipe | 4 |
read | 5 |
kill | 6 |
exec | 7 |
fstat | 8 |
chdir | 9 |
dup | 10 |
getpid | 11 |
sbrk | 12 |
sleep | 13 |
uptime | 14 |
open | 15 |
write | 16 |
mknod | 17 |
unlink | 18 |
link | 19 |
mkdir | 20 |
close | 21 |
// Prototypes for the functions that handle system calls.
extern uint64 sys_func(void);
...
static uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
...
};
void syscall(void) {
int num;
struct proc *p = myproc();
num = p->trapframe->a7;
...
}
- usertrapret (trap.c): Sets up the RISC-V control registers to prepare for a future trap from user space. (ecall 的逆操作)
- 关中断
intr_off();
- 更新
stvec
指向用户空间的 trap 处理代码, 设置了 stvec
指向 trampoline, 在那里执行 sret
返回到 user address space
- 填入 trapframe 内容 (恢复现场)
- 存储 kernel page table pointer (
kernel_satp
)
- 存储当前用户进程的 kernel stack (
kernel_sp
, stack pointer)
- 存储 usertrap 函数指针, 使得 trampoline 代码能够跳转到 (
kernel_trap = usertrap
)
- 从
tp
中读取当前的CPU核编号 (kernel_hartid
), 存储在 trapframe 中, 使得 trampoline 代码能够恢复这个数字, 因为用户代码可能会修改它
- userret (trampoline.S): Switches satp to the process’s user page table. kernel 中最后一条指令
- 程序切换回 user mode
$sepc
的数值会被 copy 到 pc
- sret 重新打开中断