Browse Source

Add some syscalls

pull/2/head
Andrew Waterman 13 years ago
parent
commit
00f7299824
  1. 1
      pk/pk.h
  2. 57
      pk/syscall.c
  3. 62
      pk/vm.c
  4. 3
      pk/vm.h

1
pk/pk.h

@ -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;

57
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])

62
pk/vm.c

@ -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);

3
pk/vm.h

@ -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

Loading…
Cancel
Save