diff options
author | Andrew Waterman <waterman@cs.berkeley.edu> | 2013-09-11 04:16:51 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@cs.berkeley.edu> | 2013-09-11 04:16:51 -0700 |
commit | 00f72998242a588c2bbd050d0929d852664d97e4 (patch) | |
tree | 4019534da5c68f5a12f112cc606c005d231ce05c /pk | |
parent | 2a0bfcd3da1a9f76cd2d0b05f59afb6533faa318 (diff) | |
download | pk-00f72998242a588c2bbd050d0929d852664d97e4.zip pk-00f72998242a588c2bbd050d0929d852664d97e4.tar.gz pk-00f72998242a588c2bbd050d0929d852664d97e4.tar.bz2 |
Add some syscalls
Diffstat (limited to 'pk')
-rw-r--r-- | pk/pk.h | 1 | ||||
-rw-r--r-- | pk/syscall.c | 57 | ||||
-rw-r--r-- | pk/vm.c | 62 | ||||
-rw-r--r-- | pk/vm.h | 3 |
4 files changed, 121 insertions, 2 deletions
@@ -66,6 +66,7 @@ typedef struct { size_t phdr; size_t phdr_top; size_t stack_top; + size_t t0; } elf_info; extern elf_info current; diff --git a/pk/syscall.c b/pk/syscall.c index 39baa79..1297ffa 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -13,6 +13,9 @@ typedef sysret_t (*syscall_t)(long, long, long, long, long, long, long); void sys_exit(int code) { + if (current.t0) + printk("%ld cycles\n", rdcycle() - current.t0); + frontend_syscall(SYS_exit, code, 0, 0, 0); while (1); } @@ -146,6 +149,55 @@ sysret_t sys_mmap(uintptr_t addr, size_t length, int prot, int flags, int fd, of return do_mmap(addr, length, prot, flags, fd, offset); } +sysret_t sys_munmap(uintptr_t addr, size_t length) +{ + return do_munmap(addr, length); +} + +sysret_t sys_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags) +{ + return do_mremap(addr, old_size, new_size, flags); +} + +sysret_t sys_rt_sigaction(int sig, const void* act, void* oact, size_t sssz) +{ + if (oact) + { + size_t sz = current.elf64 ? 6*sizeof(uint64_t) : 8*sizeof(uint32_t); + populate_mapping(oact, sz, PROT_WRITE); + memset(oact, 0, sz); + } + + return (sysret_t){0, 0}; +} + +sysret_t sys_time(long* loc) +{ + uintptr_t t = rdcycle(), hz = 1000000000; + if (loc) + { + populate_mapping(loc, sizeof(long), PROT_WRITE); + loc[0] = t/hz; + } + return (sysret_t){t, 0}; +} + +sysret_t sys_writev(int fd, const void* iov, int cnt) +{ + long get(int i) { return current.elf64 ? ((long*)iov)[i] : ((int*)iov)[i]; } + populate_mapping(iov, cnt*2*(current.elf64 ? 8 : 4), PROT_READ); + + ssize_t ret = 0; + for (int i = 0; i < cnt; i++) + { + sysret_t r = sys_write(fd, (void*)get(2*i), get(2*i+1)); + if (r.result < 0) + return r; + ret += r.result; + } + return (sysret_t){ret, 0}; +} + sysret_t syscall(long a0, long a1, long a2, long a3, long a4, long a5, long n) { const static void* syscall_table[] = { @@ -168,6 +220,11 @@ sysret_t syscall(long a0, long a1, long a2, long a3, long a4, long a5, long n) [SYS_getgid] = sys_getuid, [SYS_getegid] = sys_getuid, [SYS_mmap] = sys_mmap, + [SYS_munmap] = sys_munmap, + [SYS_mremap] = sys_mremap, + [SYS_rt_sigaction] = sys_rt_sigaction, + [SYS_time] = sys_time, + [SYS_writev] = sys_writev, }; if(n >= ARRAY_SIZE(syscall_table) || !syscall_table[n]) @@ -175,6 +175,7 @@ static int __handle_page_fault(uintptr_t vaddr, int prot) vmr_t* v = (vmr_t*)*pte; *pte = pte_create(ppn, PROT_READ|PROT_WRITE, 0); + flush_tlb(); if (v->file) { size_t flen = MIN(RISCV_PGSIZE, v->length - (vaddr - v->addr)); @@ -203,6 +204,22 @@ int handle_page_fault(uintptr_t vaddr, int prot) return ret; } +static void __do_munmap(uintptr_t addr, size_t len) +{ + for (uintptr_t a = addr; a < addr + len; a += RISCV_PGSIZE) + { + pte_t* pte = __walk(a); + if (pte == 0 || *pte == 0) + continue; + + if (!(*pte & PTE_V)) + __vmr_decref((vmr_t*)*pte, 1); + + *pte = 0; + } + flush_tlb(); // TODO: shootdown +} + uintptr_t __do_mmap(uintptr_t addr, size_t length, int prot, int flags, file_t* f, off_t offset) { size_t npage = (length-1)/RISCV_PGSIZE+1; @@ -225,7 +242,7 @@ uintptr_t __do_mmap(uintptr_t addr, size_t length, int prot, int flags, file_t* kassert(pte); if (*pte) - kassert(*pte == 0); // TODO __do_munmap + __do_munmap(addr, RISCV_PGSIZE); *pte = (pte_t)v; } @@ -244,6 +261,19 @@ fail_vmr: return (uintptr_t)-1; } +sysret_t do_munmap(uintptr_t addr, size_t length) +{ + if ((addr & (RISCV_PGSIZE-1)) || addr < current.user_min || + addr + length > current.stack_top || addr + length < addr) + return (sysret_t){-1, EINVAL}; + + spinlock_lock(&vm_lock); + __do_munmap(addr, length); + spinlock_unlock(&vm_lock); + + return (sysret_t){0, 0}; +} + sysret_t do_mmap(uintptr_t addr, size_t length, int prot, int flags, int fd, off_t offset) { if (!(flags & MAP_PRIVATE) || length == 0 || (offset & (RISCV_PGSIZE-1))) @@ -276,7 +306,7 @@ size_t __do_brk(size_t addr) size_t newbrk_page = ROUNDUP(newbrk, RISCV_PGSIZE); if (current.brk > newbrk_page) - kassert(0); // TODO __do_munmap + __do_munmap(newbrk_page, current.brk - newbrk_page); else if (current.brk < newbrk_page) kassert(__do_mmap(current.brk, newbrk_page - current.brk, -1, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) == current.brk); current.brk = newbrk_page; @@ -293,6 +323,34 @@ sysret_t do_brk(size_t addr) return (sysret_t){addr, 0}; } +sysret_t do_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags) +{ + uintptr_t res = -1; + if (((addr | old_size | new_size) & (RISCV_PGSIZE-1)) || + (flags & MREMAP_FIXED)) + return (sysret_t){-1, EINVAL}; + + spinlock_lock(&vm_lock); + for (size_t i = 0; i < MAX_VMR; i++) + { + if (vmrs[i].refcnt && addr == vmrs[i].addr && old_size == vmrs[i].length) + { + size_t old_npage = (vmrs[i].length-1)/RISCV_PGSIZE+1; + size_t new_npage = (new_size-1)/RISCV_PGSIZE+1; + if (new_size < old_size) + __do_munmap(addr + new_size, old_size - new_size); + else if (new_size > old_size) + __do_mmap(addr + old_size, new_size - old_size, vmrs[i].prot, 0, + vmrs[i].file, vmrs[i].offset + new_size - old_size); + __vmr_decref(&vmrs[i], old_npage - new_npage); + res = addr; + } + } + spinlock_unlock(&vm_lock); + + return (sysret_t){res, 0}; +} + static void __map_kernel_range(uintptr_t paddr, size_t len, int prot) { pte_t perms = pte_create(0, prot, 0); @@ -15,12 +15,15 @@ #define MAP_FIXED 0x10 #define MAP_ANONYMOUS 0x20 #define MAP_POPULATE 0x8000 +#define MREMAP_FIXED 0x2 void vm_init(); int handle_page_fault(uintptr_t vaddr, int prot); void populate_mapping(const void* start, size_t size, int prot); uintptr_t __do_mmap(uintptr_t addr, size_t length, int prot, int flags, file_t* file, off_t offset); sysret_t do_mmap(uintptr_t addr, size_t length, int prot, int flags, int fd, off_t offset); +sysret_t do_munmap(uintptr_t addr, size_t length); +sysret_t do_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags); sysret_t do_brk(uintptr_t addr); #endif |