Mercurial > hg > Members > anatofuz > CbC_xv6
diff src/syscall.cbc @ 52:214d21c891c7
rename to cbc
__ncode is not handled as interfaces
author | kono |
---|---|
date | Mon, 03 Jun 2019 18:12:44 +0900 |
parents | src/syscall.c@a7144583914c |
children | b5ddf6fb0a6d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/syscall.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,192 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "arm.h" +#include "syscall.h" + +#define __ncode __code +# +// User code makes a system call with INT T_SYSCALL. System call number +// in r0. Arguments on the stack, from the user call to the C library +// system call function. The saved user sp points to the first argument. + +// Fetch the int at addr from the current process. +int fetchint(uint addr, int *ip) +{ + if(addr >= proc->sz || addr+4 > proc->sz) { + return -1; + } + + *ip = *(int*)(addr); + return 0; +} + +// Fetch the nul-terminated string at addr from the current process. +// Doesn't actually copy the string - just sets *pp to point at it. +// Returns length of string, not including nul. +int fetchstr(uint addr, char **pp) +{ + char *s, *ep; + + if(addr >= proc->sz) { + return -1; + } + + *pp = (char*)addr; + ep = (char*)proc->sz; + + for(s = *pp; s < ep; s++) { + if(*s == 0) { + return s - *pp; + } + } + + return -1; +} + +// Fetch the nth (starting from 0) 32-bit system call argument. +// In our ABI, r0 contains system call index, r1-r4 contain parameters. +// now we support system calls with at most 4 parameters. +int argint(int n, int *ip) +{ + if (n > 3) { + panic ("too many system call parameters\n"); + } + + *ip = *(&proc->tf->r1 + n); + + return 0; +} + +// 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) +{ + int i; + + if(argint(n, &i) < 0) { + return -1; + } + + if((uint)i >= proc->sz || (uint)i+size > proc->sz) { + 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) +{ + int addr; + + if(argint(n, &addr) < 0) { + return -1; + } + + return fetchstr(addr, pp); +} + +extern int sys_chdir(void); +extern int sys_close(void); +extern int sys_dup(void); +extern int sys_exec(void); +extern int sys_exit(void); +extern int sys_fork(void); +extern int sys_fstat(void); +extern int sys_getpid(void); +extern int sys_kill(void); +extern int sys_link(void); +extern int sys_mkdir(void); +extern int sys_mknod(void); +extern int sys_open(void); +extern int sys_pipe(void); +extern int sys_read(void); +extern int sys_sbrk(void); +extern int sys_sleep(void); +extern int sys_unlink(void); +extern int sys_wait(void); +extern int sys_write(void); +extern int sys_uptime(void); + +extern __code cbc_read(__code(*)(int)); + +static int (*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, +}; + +static __code (*cbccodes[])(__code (*)(int)) = { + [SYS_cbc_read] = cbc_read, +}; + +__ncode cbc_trap_return(){ + return; +} + +__ncode cbc_ret(int ret){ + int num = proc->cbc_arg.cbc_console_arg.num; + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + goto cbc_trap_return(); +} + +void syscall(void) +{ + int num; + int ret; + + num = proc->tf->r0; + + if (num == 5) + num = 22; + //cprintf ("syscall(%d) from %s(%d)\n", num, proc->name, proc->pid); + + if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) { + proc->cbc_arg.cbc_console_arg.num = num; + goto (cbccodes[num])(cbc_ret); + } + + + if((num > 0) && (num < NELEM(syscalls)) && syscalls[num]) { + ret = syscalls[num](); + + // in ARM, parameters to main (argc, argv) are passed in r0 and r1 + // do not set the return value if it is SYS_exec (the user program + // anyway does not expect us to return anything). + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + } else { + cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); + proc->tf->r0 = -1; + } +}