aboutsummaryrefslogtreecommitdiff
path: root/pk/vm.c
diff options
context:
space:
mode:
authorColin Schmidt <colins@berkeley.edu>2014-05-27 10:27:43 -0700
committerColin Schmidt <colins@berkeley.edu>2014-05-27 10:27:43 -0700
commit8fc3a35ba546209532c5ee79db52f4f706bf6beb (patch)
treeb7014666ae0f5c25e8666fc4c0384338e30f1219 /pk/vm.c
parent863e01b99095626a447d61f8f67fb4f1e6ba5355 (diff)
downloadpk-8fc3a35ba546209532c5ee79db52f4f706bf6beb.zip
pk-8fc3a35ba546209532c5ee79db52f4f706bf6beb.tar.gz
pk-8fc3a35ba546209532c5ee79db52f4f706bf6beb.tar.bz2
Allow mmap to map new segments larger than 1 page on top of existing mappings and add mprotect syscall
Diffstat (limited to 'pk/vm.c')
-rw-r--r--pk/vm.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/pk/vm.c b/pk/vm.c
index 8ab466e..783153c 100644
--- a/pk/vm.c
+++ b/pk/vm.c
@@ -242,7 +242,7 @@ uintptr_t __do_mmap(uintptr_t addr, size_t length, int prot, int flags, file_t*
kassert(pte);
if (*pte)
- __do_munmap(addr, RISCV_PGSIZE);
+ __do_munmap(a, RISCV_PGSIZE);
*pte = (pte_t)v;
}
@@ -346,6 +346,41 @@ uintptr_t do_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags)
return res;
}
+uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot)
+{
+ uintptr_t res = 0;
+ if ((addr) & (RISCV_PGSIZE-1))
+ return -EINVAL;
+
+ spinlock_lock(&vm_lock);
+ for (uintptr_t a = addr; a < addr + length; a += RISCV_PGSIZE)
+ {
+ pte_t* pte = __walk(a);
+ if (pte == 0 || *pte == 0)
+ return -ENOMEM;
+
+ if(!(*pte & PTE_V)){
+ vmr_t* v = (vmr_t*)*pte;
+ if((v->prot ^ prot) & ~v->prot){
+ //TODO:look at file to find perms
+ return -EACCES;
+ }
+ v->prot = prot;
+ }else{
+ pte_t perms = pte_create(0, 0, prot);
+ if ((*pte & perms) != perms){
+ //TODO:look at file to find perms
+ return -EACCES;
+ }
+ pte_t permset = (*pte & ~(PTE_UR | PTE_UW | PTE_UX)) | perms;
+ *pte = permset;
+ }
+ }
+ spinlock_unlock(&vm_lock);
+
+ return res;
+}
+
static void __map_kernel_range(uintptr_t paddr, size_t len, int prot)
{
pte_t perms = pte_create(0, prot, 0);