You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
os-xv6/kernel/syscall.c

187 lines
4.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "spinlock.h"
#include "proc.h"
#include "syscall.h"
#include "defs.h"
// Fetch the uint64 at addr from the current process.
int
fetchaddr(uint64 addr, uint64 *ip)
{
struct proc *p = myproc();
if(addr >= p->sz || addr+sizeof(uint64) > p->sz) // both tests needed, in case of overflow
return -1;
if(copyin(p->pagetable, (char *)ip, addr, sizeof(*ip)) != 0)
return -1;
return 0;
}
// Fetch the nul-terminated string at addr from the current process.
// Returns length of string, not including nul, or -1 for error.
int
fetchstr(uint64 addr, char *buf, int max)
{
struct proc *p = myproc();
if(copyinstr(p->pagetable, buf, addr, max) < 0)
return -1;
return strlen(buf);
}
static uint64
argraw(int n)
{
struct proc *p = myproc();
switch (n) {
case 0:
return p->trapframe->a0;
case 1:
return p->trapframe->a1;
case 2:
return p->trapframe->a2;
case 3:
return p->trapframe->a3;
case 4:
return p->trapframe->a4;
case 5:
return p->trapframe->a5;
}
panic("argraw");
return -1;
}
// Fetch the nth 32-bit system call argument.
void
argint(int n, int *ip)
{
*ip = argraw(n);
}
// Retrieve an argument as a pointer.
// Doesn't check for legality, since
// copyin/copyout will do that.
void
argaddr(int n, uint64 *ip)
{
*ip = argraw(n);
}
// Fetch the nth word-sized system call argument as a null-terminated string.
// Copies into buf, at most max.
// Returns string length if OK (including nul), -1 if error.
int
argstr(int n, char *buf, int max)
{
uint64 addr;
argaddr(n, &addr);
return fetchstr(addr, buf, max);
}
// Prototypes for the functions that handle system calls.
extern uint64 sys_fork(void);
extern uint64 sys_exit(void);
extern uint64 sys_wait(void);
extern uint64 sys_pipe(void);
extern uint64 sys_read(void);
extern uint64 sys_kill(void);
extern uint64 sys_exec(void);
extern uint64 sys_fstat(void);
extern uint64 sys_chdir(void);
extern uint64 sys_dup(void);
extern uint64 sys_getpid(void);
extern uint64 sys_sbrk(void);
extern uint64 sys_sleep(void);
extern uint64 sys_uptime(void);
extern uint64 sys_open(void);
extern uint64 sys_write(void);
extern uint64 sys_mknod(void);
extern uint64 sys_unlink(void);
extern uint64 sys_link(void);
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_sysinfo(void); // 新增
extern uint64 sys_trace(void);
// An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
static uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
[SYS_exit] sys_exit,
[SYS_wait] sys_wait,
[SYS_pipe] sys_pipe,
[SYS_read] sys_read,
[SYS_kill] sys_kill,
[SYS_exec] sys_exec,
[SYS_fstat] sys_fstat,
[SYS_chdir] sys_chdir,
[SYS_dup] sys_dup,
[SYS_getpid] sys_getpid,
[SYS_sbrk] sys_sbrk,
[SYS_sleep] sys_sleep,
[SYS_uptime] sys_uptime,
[SYS_open] sys_open,
[SYS_write] sys_write,
[SYS_mknod] sys_mknod,
[SYS_unlink] sys_unlink,
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_sysinfo] sys_sysinfo,
[SYS_trace] sys_trace
};
// 在文件开头、syscalls数组前添加顺序需与syscall.h中的调用号一致
static char *syscall_names[] = {
"", // 0号未使用
"fork", // 1: SYS_fork
"exit", // 2: SYS_exit
"wait", // 3: SYS_wait
"pipe", // 4: SYS_pipe
"read", // 5: SYS_read
"kill", // 6: SYS_kill
"exec", // 7: SYS_exec
"fstat", // 8: SYS_fstat
"chdir", // 9: SYS_chdir
"dup", // 10: SYS_dup
"getpid", // 11: SYS_getpid
"sbrk", // 12: SYS_sbrk
"sleep", // 13: SYS_sleep
"uptime", // 14: SYS_uptime
"open", // 15: SYS_open
"write", // 16: SYS_write
"mknod", // 17: SYS_mknod
"unlink", // 18: SYS_unlink
"link", // 19: SYS_link
"mkdir", // 20: SYS_mkdir
"close", // 21: SYS_close
"trace", // 22: SYS_trace新增需与SYS_trace编号一致
"sysinfo" // 23: SYS_sysinfo
};
void
syscall(void)
{
int num;
struct proc *p = myproc();
num = p->trapframe->a7;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
// Use num to lookup the system call function for num, call it,
// and store its return value in p->trapframe->a0
p->trapframe->a0 = syscalls[num]();
if (strlen(p->mask) > 0 && p->mask[num] == '1'){
p->trace_counts[num]++;
printf("%d: syscall %s(trace counts: %d) -> %d\n", p->pid, syscall_names[num], p->trace_counts[num], p->trapframe->a0);
}
} else {
printf("%d %s: unknown sys call %d\n",
p->pid, p->name, num);
p->trapframe->a0 = -1;
}
}