提交 723157a5 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

pass syscall args as function args, instead of fishing them out of trapframe

上级 233d2d46
......@@ -17,29 +17,31 @@ void swtch(struct context**, struct context*);
extern struct segdesc bootgdt[NSEGS];
// syscalls
long sys_chdir(void);
long sys_close(void);
long sys_dup(void);
long sys_exec(void);
struct stat;
long sys_chdir(const char*);
long sys_close(int);
long sys_dup(int);
long sys_exec(const char*, u64);
long sys_exit(void);
long sys_fork(void);
long sys_fstat(void);
long sys_fork(int);
long sys_fstat(int, struct stat*);
long sys_getpid(void);
long sys_kill(void);
long sys_link(void);
long sys_mkdir(void);
long sys_mknod(void);
long sys_open(void);
long sys_pipe(void);
long sys_read(void);
long sys_sbrk(void);
long sys_sleep(void);
long sys_unlink(void);
long sys_kill(int);
long sys_link(const char*, const char*);
long sys_mkdir(const char*);
long sys_mknod(const char*, int, int);
long sys_open(const char*, int);
long sys_pipe(int*);
long sys_read(int, char*, int);
long sys_sbrk(int);
long sys_sleep(int);
long sys_unlink(const char*);
long sys_wait(void);
long sys_write(void);
long sys_write(int, char*, int);
long sys_uptime(void);
long sys_map(void);
long sys_unmap(void);
long sys_map(uptr, u64);
long sys_unmap(uptr, u64);
long sys_halt(void);
long sys_socket(int, int, int);
long sys_bind(int, void*, int);
......@@ -48,7 +50,7 @@ long sys_accept(int, void*, void*);
long sys_pread(int fd, void *ubuf, size_t count, off_t offset);
long sys_async(int, size_t, off_t, u32, u32);
long sys_script(void *addr, u64 len, u64 chunk);
extern long (*syscalls[])(u64, u64, u64, u64, u64, u64);
extern long (*syscalls[])(u64, u64, u64, u64, u64);
// other exported/imported functions
void cmain(u64 mbmagic, u64 mbaddr);
......@@ -60,4 +62,4 @@ void threadhelper(void (*fn)(void *), void *arg);
struct trapframe;
void trap(struct trapframe *tf);
void sysentry(void);
void sysentry_c(void);
u64 sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num);
......@@ -84,7 +84,7 @@ int e1000tx(void *buf, u32 len);
void e1000hwaddr(u8 *hwaddr);
// exec.c
int exec(char*, char**);
int exec(const char*, char**);
// file.c
struct file* filealloc(void);
......@@ -110,7 +110,7 @@ int readi(struct inode*, char*, u32, u32);
void stati(struct inode*, struct stat*);
int writei(struct inode*, char*, u32, u32);
struct inode* idup(struct inode*);
struct inode* nameiparent(char*, char*);
struct inode* nameiparent(const char*, char*);
int dirlink(struct inode*, const char*, u32);
void dir_init(struct inode *dp);
void dir_flush(struct inode *dp);
......@@ -210,15 +210,12 @@ void destroylock(struct spinlock *lk);
void release(struct spinlock*);
// syscall.c
int argint64(int, u64*);
int argint32(int n, int *ip);
int argptr(int, char**, int);
int argstr(int, char**);
int argcheckptr(void *argval, int);
int argcheckstr(const char*);
int fetchint64(uptr, u64*);
int fetchstr(uptr, char**);
int umemcpy(void*, void*, u64);
int kmemcpy(void*, void*, u64);
void syscall(void);
u64 syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num);
// string.c
extern "C" int memcmp(const void*, const void*, u32);
......@@ -304,39 +301,6 @@ void initsched(void);
void initlockstat(void);
void initwq(void);
// syscalls
long sys_chdir(void);
long sys_close(void);
long sys_dup(void);
long sys_exec(void);
long sys_exit(void);
long sys_fork(void);
long sys_fstat(void);
long sys_getpid(void);
long sys_kill(void);
long sys_link(void);
long sys_mkdir(void);
long sys_mknod(void);
long sys_open(void);
long sys_pipe(void);
long sys_read(void);
long sys_sbrk(void);
long sys_sleep(void);
long sys_unlink(void);
long sys_wait(void);
long sys_write(void);
long sys_uptime(void);
long sys_map(void);
long sys_unmap(void);
long sys_halt(void);
long sys_socket(int, int, int);
long sys_bind(int, void*, int);
long sys_listen(int, int);
long sys_accept(int, void*, void*);
long sys_pread(int fd, void *ubuf, size_t count, off_t offset);
long sys_async(int, size_t, off_t, u32, u32);
extern long (*syscalls[])(u64, u64, u64, u64, u64, u64);
// other exported/imported functions
void cmain(u64 mbmagic, u64 mbaddr);
void mpboot(void);
......
......@@ -28,7 +28,7 @@ struct segdesc __attribute__((aligned(16))) bootgdt[NSEGS] = {
#define SYSCALL(name) [SYS_##name] = (void*)sys_##name
long (*syscalls[])(u64, u64, u64, u64, u64, u64) = {
long (*syscalls[])(u64, u64, u64, u64, u64) = {
SYSCALL(chdir),
SYSCALL(close),
SYSCALL(dup),
......
......@@ -24,7 +24,7 @@ struct eargs {
struct proc *proc;
struct inode *ip;
struct vmap *vmap;
char *path;
const char *path;
char **argv;
};
......@@ -76,7 +76,7 @@ static void dostack(uptr a0, u64 a1)
int argc;
uptr sp;
uptr ustack[1+MAXARG+1];
char *s, *last;
const char *s, *last;
prof_start(dostack_prof);
// Allocate a one-page stack at the top of the (user) address space
......@@ -143,7 +143,7 @@ bad:
}
int
exec(char *path, char **argv)
exec(const char *path, char **argv)
{
struct inode *ip = NULL;
struct vmap *vmp = NULL;
......
......@@ -795,7 +795,7 @@ namei(const char *path)
}
struct inode*
nameiparent(char *path, char *name)
nameiparent(const char *path, char *name)
{
return namex(path, 1, name);
}
......
......@@ -32,84 +32,33 @@ fetchint64(uptr addr, u64 *ip)
// Doesn't actually copy the string - just sets *pp to point at it.
// Returns length of string, not including nul.
int
fetchstr(uptr addr, char **pp)
argcheckstr(const char *addr)
{
char *s = (char *) addr;
const char *s = addr;
while(1){
if(pagefault(myproc()->vmap, (uptr) s, 0) < 0)
return -1;
if(*s == 0){
*pp = (char*)addr;
return s - *pp;
}
if(*s == 0)
return s - addr;
s++;
}
return -1;
}
// Fetch the nth 64-bit system call argument.
int
argint64(int n, u64 *ip)
{
switch(n) {
case 0: *ip = myproc()->tf->rdi; break;
case 1: *ip = myproc()->tf->rsi; break;
case 2: *ip = myproc()->tf->rdx; break;
case 3: *ip = myproc()->tf->rcx; break;
case 4: *ip = myproc()->tf->r8; break;
// r9 is corrupted by sysentry
// case 5: *ip = myproc()->tf->r9; break;
default:
cprintf("argint64: bad arg %d\n", n);
return -1;
}
return 0;
}
int
argint32(int n, int *ip)
{
int r;
u64 i;
r = argint64(n, &i);
if (r >= 0)
*ip = i;
return r;
}
// Fetch the nth word-sized system call argument as a pointer
// to a block of memory of size n bytes. Check that the pointer
// lies within the process address space.
int
argptr(int n, char **pp, int size)
argcheckptr(void *p, int size)
{
u64 i;
if(argint64(n, &i) < 0)
return -1;
u64 i = (u64) p;
for(uptr va = PGROUNDDOWN(i); va < i+size; va = va + PGSIZE)
if(pagefault(myproc()->vmap, va, 0) < 0)
return -1;
*pp = (char*)i;
return 0;
}
// Fetch the nth word-sized system call argument as a string pointer.
// Check that the pointer is valid and the string is nul-terminated.
// (There is no shared writable memory, so the string can't change
// between this check and being used by the kernel.)
int
argstr(int n, char **pp)
{
uptr addr;
if(argint64(n, &addr) < 0)
return -1;
return fetchstr(addr, pp);
}
static int
umemptr(void *umem, void **ret, u64 size)
{
......@@ -147,24 +96,22 @@ kmemcpy(void *umem, void *src, u64 size)
return 0;
}
void
syscall(void)
u64
syscall(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num)
{
struct trapframe *tf;
int num;
u64 r;
tf = myproc()->tf;
num = tf->rax;
if(num >= 0 && num < SYS_ncount && syscalls[num]) {
if(num < SYS_ncount && syscalls[num]) {
mtstart(syscalls[num], myproc());
mtrec();
tf->rax = syscalls[num](tf->rdi, tf->rsi, tf->rdx,
tf->rcx, tf->r8, tf->r9);
r = syscalls[num](a0, a1, a2, a3, a4);
mtstop(myproc());
mtign();
} else {
cprintf("%d %s: unknown sys call %d\n",
cprintf("%d %s: unknown sys call %ld\n",
myproc()->pid, myproc()->name, num);
tf->rax = -1;
r = -1;
}
return r;
}
......@@ -15,17 +15,12 @@
// Fetch the nth word-sized system call argument as a file descriptor
// and return both the descriptor and the corresponding struct file.
static int
argfd(int n, int *pfd, struct file **pf)
argfd(int fd, struct file **pf)
{
int fd;
struct file *f;
if(argint32(n, &fd) < 0)
return -1;
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
return -1;
if(pfd)
*pfd = fd;
if(pf)
*pf = f;
return 0;
......@@ -48,12 +43,12 @@ fdalloc(struct file *f)
}
long
sys_dup(void)
sys_dup(int ofd)
{
struct file *f;
int fd;
if(argfd(0, 0, &f) < 0)
if(argfd(ofd, &f) < 0)
return -1;
if((fd=fdalloc(f)) < 0)
return -1;
......@@ -62,13 +57,11 @@ sys_dup(void)
}
s64
sys_read(void)
sys_read(int fd, char *p, int n)
{
struct file *f;
int n;
char *p;
if(argfd(0, 0, &f) < 0 || argint32(2, &n) < 0 || argptr(1, &p, n) < 0)
if(argfd(fd, &f) < 0 || argcheckptr(p, n) < 0)
return -1;
return fileread(f, p, n);
}
......@@ -99,24 +92,21 @@ sys_pread(int fd, void *ubuf, size_t count, off_t offset)
}
long
sys_write(void)
sys_write(int fd, char *p, int n)
{
struct file *f;
int n;
char *p;
if(argfd(0, 0, &f) < 0 || argint32(2, &n) < 0 || argptr(1, &p, n) < 0)
if(argfd(fd, &f) < 0 || argcheckptr(p, n) < 0)
return -1;
return filewrite(f, p, n);
}
long
sys_close(void)
sys_close(int fd)
{
int fd;
struct file *f;
if(argfd(0, &fd, &f) < 0)
if(argfd(fd, &f) < 0)
return -1;
myproc()->ofile[fd] = 0;
fileclose(f);
......@@ -124,24 +114,23 @@ sys_close(void)
}
long
sys_fstat(void)
sys_fstat(int fd, struct stat *st)
{
struct file *f;
struct stat *st;
if(argfd(0, 0, &f) < 0 || argptr(1, (char**)&st, sizeof(*st)) < 0)
if(argfd(fd, &f) < 0 || argcheckptr(st, sizeof(*st)) < 0)
return -1;
return filestat(f, st);
}
// Create the path new as a link to the same inode as old.
long
sys_link(void)
sys_link(const char *old, const char *newn)
{
char name[DIRSIZ], *newn, *old;
char name[DIRSIZ];
struct inode *dp, *ip;
if(argstr(0, &old) < 0 || argstr(1, &newn) < 0)
if(argcheckstr(old) < 0 || argcheckstr(newn) < 0)
return -1;
if((ip = namei(old)) == 0)
return -1;
......@@ -189,12 +178,12 @@ isdirempty(struct inode *dp)
}
long
sys_unlink(void)
sys_unlink(const char *path)
{
struct inode *ip, *dp;
char name[DIRSIZ], *path;
char name[DIRSIZ];
if(argstr(0, &path) < 0)
if(argcheckstr(path) < 0)
return -1;
if((dp = nameiparent(path, name)) == 0)
return -1;
......@@ -245,7 +234,7 @@ sys_unlink(void)
}
static struct inode*
create(char *path, short type, short major, short minor)
create(const char *path, short type, short major, short minor)
{
struct inode *ip, *dp;
char name[DIRSIZ];
......@@ -295,14 +284,13 @@ create(char *path, short type, short major, short minor)
}
long
sys_open(void)
sys_open(const char *path, int omode)
{
char *path;
int fd, omode;
int fd;
struct file *f;
struct inode *ip;
if(argstr(0, &path) < 0 || argint32(1, &omode) < 0)
if(argcheckstr(path) < 0)
return -1;
if(omode & O_CREATE){
if((ip = create(path, T_FILE, 0, 0)) == 0)
......@@ -343,28 +331,23 @@ sys_open(void)
}
long
sys_mkdir(void)
sys_mkdir(const char *path)
{
char *path;
struct inode *ip;
if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0)
if(argcheckstr(path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0)
return -1;
iunlockput(ip);
return 0;
}
long
sys_mknod(void)
sys_mknod(const char *path, int major, int minor)
{
struct inode *ip;
char *path;
int len;
int major, minor;
if((len=argstr(0, &path)) < 0 ||
argint32(1, &major) < 0 ||
argint32(2, &minor) < 0 ||
if((len=argcheckstr(path)) < 0 ||
(ip = create(path, T_DEV, major, minor)) == 0)
return -1;
iunlockput(ip);
......@@ -372,12 +355,11 @@ sys_mknod(void)
}
long
sys_chdir(void)
sys_chdir(const char *path)
{
char *path;
struct inode *ip;
if(argstr(0, &path) < 0 || (ip = namei(path)) == 0)
if(argcheckstr(path) < 0 || (ip = namei(path)) == 0)
return -1;
ilock(ip, 0);
if(ip->type != T_DIR){
......@@ -391,14 +373,13 @@ sys_chdir(void)
}
long
sys_exec(void)
sys_exec(const char *path, u64 uargv)
{
char *path, *argv[MAXARG];
char *argv[MAXARG];
int i;
uptr uargv;
u64 uarg;
if(argstr(0, &path) < 0 || argint64(1, &uargv) < 0){
if(argcheckstr(path) < 0) {
return -1;
}
memset(argv, 0, sizeof(argv));
......@@ -411,20 +392,20 @@ sys_exec(void)
argv[i] = 0;
break;
}
if(fetchstr(uarg, &argv[i]) < 0)
argv[i] = (char*) uarg;
if(argcheckstr(argv[i]) < 0)
return -1;
}
return exec(path, argv);
}
long
sys_pipe(void)
sys_pipe(int *fd)
{
int *fd;
struct file *rf, *wf;
int fd0, fd1;
if(argptr(0, (char**)&fd, 2*sizeof(fd[0])) < 0)
if(argcheckptr(fd, 2*sizeof(fd[0])) < 0)
return -1;
if(pipealloc(&rf, &wf) < 0)
return -1;
......
......@@ -10,12 +10,8 @@
#include "vm.hh"
long
sys_fork(void)
sys_fork(int flags)
{
int flags;
if(argint32(0, &flags) < 0)
return -1;
return fork(flags);
}
......@@ -33,12 +29,8 @@ sys_wait(void)
}
long
sys_kill(void)
sys_kill(int pid)
{
int pid;
if(argint32(0, &pid) < 0)
return -1;
return kill(pid);
}
......@@ -49,13 +41,10 @@ sys_getpid(void)
}
long
sys_sbrk(void)
sys_sbrk(int n)
{
uptr addr;
int n;
if(argint32(0, &n) < 0)
return -1;
addr = myproc()->brk;
if(growproc(n) < 0)
return -1;
......@@ -63,13 +52,10 @@ sys_sbrk(void)
}
long
sys_sleep(void)
sys_sleep(int n)
{
int n;
u32 ticks0;
if(argint32(0, &n) < 0)
return -1;
acquire(&tickslock);
ticks0 = ticks;
while(ticks - ticks0 < n){
......@@ -97,16 +83,8 @@ sys_uptime(void)
}
long
sys_map(void)
sys_map(uptr addr, u64 len)
{
uptr addr;
u64 len;
if (argint64(0, &addr) < 0)
return -1;
if (argint64(1, &len) < 0)
return -1;
vmnode *vmn = new vmnode(PGROUNDUP(len) / PGSIZE);
if (vmn == 0)
return -1;
......@@ -120,16 +98,8 @@ sys_map(void)
}
long
sys_unmap(void)
sys_unmap(uptr addr, u64 len)
{
uptr addr;
uptr len;
if (argint64(0, &addr) < 0)
return -1;
if (argint64(1, &len) < 0)
return -1;
uptr align_addr = PGROUNDDOWN(addr);
uptr align_len = PGROUNDUP(addr + len) - align_addr;
if (myproc()->vmap->remove(align_addr, align_len) < 0)
......
......@@ -17,9 +17,11 @@ struct intdesc idt[256] __attribute__((aligned(16)));
// boot.S
extern u64 trapentry[];
void
sysentry_c()
u64
sysentry_c(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4, u64 num)
{
u64 r;
writegs(KDSEG);
writemsr(MSR_GS_BASE, (u64)&cpus[cpunum()].cpu);
......@@ -32,12 +34,14 @@ sysentry_c()
trapframe *tf = (trapframe*) (myproc()->kstack + KSTACKSIZE - sizeof(*tf));
myproc()->tf = tf;
syscall();
r = syscall(a0, a1, a2, a3, a4, num);
if(myproc()->killed) {
mtstart(trap, myproc());
exit();
}
return r;
}
void
......@@ -61,7 +65,7 @@ trap(struct trapframe *tf)
exit();
}
myproc()->tf = tf;
syscall();
tf->rax = syscall(tf->rdi, tf->rsi, tf->rdx, tf->rcx, tf->r8, tf->rax);
if(myproc()->killed) {
mtstart(trap, myproc());
exit();
......
......@@ -45,12 +45,12 @@ sysentry:
// skip r11 (0x40)
// skip r10 (0x48)
// skip r9 (0x50)
movq %r8, %ss:0x58(%r9)
movq %rax, %ss:0x60(%r9)
movq %r10, %ss:0x68(%r9) // rcx saved by usys.S
movq %rdx, %ss:0x70(%r9)
movq %rsi, %ss:0x78(%r9)
movq %rdi, %ss:0x80(%r9)
// skip r8 (0x58)
// skip rax (0x60)
// skip rcx (0x68)
// skip rdx (0x70)
// skip rsi (0x78)
// skip rdi (0x80)
// skip trapno (0x88)
// skip err, padding2 (0x90)
movq %rcx, %ss:0x98(%r9) // rip saved by syscall
......@@ -58,26 +58,28 @@ sysentry:
movq %r11, %ss:0xa8(%r9) // eflags saved by syscall
movq %rsp, %ss:0xb0(%r9)
movw $KDSEG, %ax
movw %ax, %ds
movw %ax, %es
movw $KDSEG, %cx
movw %cx, %ds
movw %cx, %es
movq %r9, %rsp
movq %r10, %rcx // saved by usys.S
movq %rax, %r9 // syscall# from usys.S
call sysentry_c
// return using SYSRET
cli
movq %rsp, %r11
movw $UDSEG, %ax
movw %ax, %ds
movw %ax, %es
movw $UDSEG, %cx
movw %cx, %ds
movw %cx, %es
movq %ss:0x10(%r11), %r15
movq %ss:0x18(%r11), %r14
movq %ss:0x20(%r11), %r13
movq %ss:0x28(%r11), %r12
movq %ss:0x30(%r11), %rbp
movq %ss:0x38(%r11), %rbx
movq %ss:0x60(%r11), %rax
movq %ss:0x98(%r11), %rcx // rip to be restored by sysret
movq %ss:0xb0(%r11), %rsp
movq %ss:0xa8(%r11), %r11 // eflags to be restored by sysret
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论