From 4668b8415838e542e623a9ad572f010d27b05ddd Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 28 Nov 2011 19:05:50 +0100 Subject: [PATCH] vm_remap_ro - allows shared memory to be mapped in readonly - ben@minix3.org & tom@minix3.org --- commands/service/parse.c | 1 + common/include/minix/com.h | 6 +++++- include/sys/mman.h | 2 ++ lib/libc/posix/_mmap.c | 22 ++++++++++++++++++++++ lib/nbsd_libc/sys-minix/mmap.c | 21 +++++++++++++++++++++ servers/ipc/ipc.conf | 1 + servers/vm/main.c | 1 + servers/vm/mmap.c | 9 ++++++++- servers/vm/pagefaults.c | 5 ----- servers/vm/proto.h | 2 +- servers/vm/region.c | 14 ++++++++++---- 11 files changed, 72 insertions(+), 12 deletions(-) diff --git a/commands/service/parse.c b/commands/service/parse.c index 20096e0e0..ed675d4f0 100644 --- a/commands/service/parse.c +++ b/commands/service/parse.c @@ -716,6 +716,7 @@ struct { "DELDMA", VM_DELDMA }, { "GETDMA", VM_GETDMA }, { "REMAP", VM_REMAP }, + { "REMAP_RO", VM_REMAP_RO }, { "SHM_UNMAP", VM_SHM_UNMAP }, { "GETPHYS", VM_GETPHYS }, { "GETREF", VM_GETREF }, diff --git a/common/include/minix/com.h b/common/include/minix/com.h index 678637673..7047ff6d0 100644 --- a/common/include/minix/com.h +++ b/common/include/minix/com.h @@ -999,6 +999,7 @@ # define VMRE_SA m1_p2 # define VMRE_RETA m1_p3 # define VMRE_SIZE m1_i3 +# define VMRE_FLAGS m1_i3 #define VM_SHM_UNMAP (VM_RQ_BASE+34) # define VMUN_ENDPT m2_i1 @@ -1051,8 +1052,11 @@ #define VM_WATCH_EXIT (VM_RQ_BASE+43) # define VM_WE_EP m1_i1 +#define VM_REMAP_RO (VM_RQ_BASE+44) +/* same args as VM_REMAP */ + /* Total. */ -#define NR_VM_CALLS 44 +#define NR_VM_CALLS 45 #define VM_CALL_MASK_SIZE BITMAP_CHUNKS(NR_VM_CALLS) /* not handled as a normal VM call, thus at the end of the reserved rage */ diff --git a/include/sys/mman.h b/include/sys/mman.h index 7317ea606..b08c912bc 100644 --- a/include/sys/mman.h +++ b/include/sys/mman.h @@ -30,6 +30,8 @@ _PROTOTYPE( int minix_munmap, (void *, size_t)); _PROTOTYPE( int minix_munmap_text, (void *, size_t)); _PROTOTYPE( void *vm_remap, (endpoint_t d, endpoint_t s, void *da, void *sa, size_t si)); +_PROTOTYPE( void *vm_remap_ro, (endpoint_t d, endpoint_t s, void *da, + void *sa, size_t si)); _PROTOTYPE( int vm_unmap, (endpoint_t endpt, void *addr)); _PROTOTYPE( unsigned long vm_getphys, (endpoint_t endpt, void *addr)); _PROTOTYPE( u8_t vm_getrefcount, (endpoint_t endpt, void *addr)); diff --git a/lib/libc/posix/_mmap.c b/lib/libc/posix/_mmap.c index 8497fddc4..42605beb6 100644 --- a/lib/libc/posix/_mmap.c +++ b/lib/libc/posix/_mmap.c @@ -76,6 +76,28 @@ PUBLIC void *vm_remap(endpoint_t d, return (void *) m.VMRE_RETA; } +PUBLIC void *vm_remap_ro(endpoint_t d, + endpoint_t s, + void *da, + void *sa, + size_t size) +{ + message m; + int r; + + m.VMRE_D = d; + m.VMRE_S = s; + m.VMRE_DA = (char *) da; + m.VMRE_SA = (char *) sa; + m.VMRE_SIZE = size; + + r = _syscall(VM_PROC_NR, VM_REMAP_RO, &m); + if (r != OK) + return MAP_FAILED; + return (void *) m.VMRE_RETA; +} + + PUBLIC int vm_unmap(endpoint_t endpt, void *addr) { message m; diff --git a/lib/nbsd_libc/sys-minix/mmap.c b/lib/nbsd_libc/sys-minix/mmap.c index 1a0ea36d0..d49d495fd 100644 --- a/lib/nbsd_libc/sys-minix/mmap.c +++ b/lib/nbsd_libc/sys-minix/mmap.c @@ -85,6 +85,27 @@ PUBLIC void *vm_remap(endpoint_t d, return (void *) m.VMRE_RETA; } +PUBLIC void *vm_remap_ro(endpoint_t d, + endpoint_t s, + void *da, + void *sa, + size_t size) +{ + message m; + int r; + + m.VMRE_D = d; + m.VMRE_S = s; + m.VMRE_DA = (char *) da; + m.VMRE_SA = (char *) sa; + m.VMRE_SIZE = size; + + r = _syscall(VM_PROC_NR, VM_REMAP_RO, &m); + if (r != OK) + return MAP_FAILED; + return (void *) m.VMRE_RETA; +} + PUBLIC int vm_unmap(endpoint_t endpt, void *addr) { message m; diff --git a/servers/ipc/ipc.conf b/servers/ipc/ipc.conf index a4cc015fc..e2300e6bb 100644 --- a/servers/ipc/ipc.conf +++ b/servers/ipc/ipc.conf @@ -10,6 +10,7 @@ service ipc ; vm REMAP + REMAP_RO SHM_UNMAP GETPHYS GETREF diff --git a/servers/vm/main.c b/servers/vm/main.c index 43a07b78d..9a32356fa 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -361,6 +361,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) /* Generic calls. */ CALLMAP(VM_REMAP, do_remap); + CALLMAP(VM_REMAP_RO, do_remap); CALLMAP(VM_GETPHYS, do_get_phys); CALLMAP(VM_SHM_UNMAP, do_shared_unmap); CALLMAP(VM_GETREF, do_get_refcount); diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index 2659b6e45..8e1c3abc4 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -231,6 +231,13 @@ PUBLIC int do_remap(message *m) struct vir_region *region; struct vmproc *dvmp, *svmp; int r; + int readonly; + + if(m->m_type == VM_REMAP) + readonly = 0; + else if(m->m_type == VM_REMAP_RO) + readonly = 1; + else panic("do_remap: can't be"); da = (vir_bytes) m->VMRE_DA; sa = (vir_bytes) m->VMRE_SA; @@ -275,7 +282,7 @@ PUBLIC int do_remap(message *m) return EFAULT; } - if ((r = map_remap(dvmp, da, size, region, &startv)) != OK) + if ((r = map_remap(dvmp, da, size, region, &startv, readonly)) != OK) return r; m->VMRE_RETA = (char *) arch_map2vir(dvmp, startv); diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c index fae6373a9..6b6575c63 100644 --- a/servers/vm/pagefaults.c +++ b/servers/vm/pagefaults.c @@ -86,11 +86,6 @@ PUBLIC void do_pagefaults(message *m) */ assert(!(region->flags & VR_NOPF)); - /* We do not allow shared memory to cause pagefaults. - * These pages have to be pre-allocated. - */ - assert(!(region->flags & VR_SHARED)); - /* If process was writing, see if it's writable. */ if(!(region->flags & VR_WRITABLE) && wr) { printf("VM: pagefault: SIGSEGV %d ro map 0x%lx %s\n", diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 506e59d78..8b861d3ad 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -169,7 +169,7 @@ _PROTOTYPE(struct vir_region * map_region_lookup_tag, (struct vmproc *vmp, u32_t _PROTOTYPE(void map_region_set_tag, (struct vir_region *vr, u32_t tag)); _PROTOTYPE(u32_t map_region_get_tag, (struct vir_region *vr)); _PROTOTYPE(int map_remap, (struct vmproc *dvmp, vir_bytes da, size_t size, - struct vir_region *region, vir_bytes *r)); + struct vir_region *region, vir_bytes *r, int ro)); _PROTOTYPE(int map_get_phys, (struct vmproc *vmp, vir_bytes addr, phys_bytes *r)); _PROTOTYPE(int map_get_ref, (struct vmproc *vmp, vir_bytes addr, u8_t *cnt)); diff --git a/servers/vm/region.c b/servers/vm/region.c index 2d63e1954..ad375e54b 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -36,8 +36,9 @@ PRIVATE yielded_t *lru_youngest = NULL, *lru_oldest = NULL; /* Should a physblock be mapped writable? */ #define WRITABLE(r, pb) \ - (((r)->flags & (VR_DIRECT | VR_SHARED)) || \ - (((r)->flags & VR_WRITABLE) && (pb)->refcount == 1)) + (((r)->flags & VR_WRITABLE) && \ + (((r)->flags & (VR_DIRECT | VR_SHARED)) || \ + (pb)->refcount == 1)) FORWARD _PROTOTYPE(int map_new_physblock, (struct vmproc *vmp, struct vir_region *region, vir_bytes offset, vir_bytes length, @@ -1426,6 +1427,7 @@ PRIVATE struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region newvr->lower = newvr->higher = NULL; newvr->phys = phavl; ); + physr_init(newvr->phys); physr_start_iter_least(vr->phys, &iter); @@ -1806,7 +1808,7 @@ PUBLIC int map_unmap_region(struct vmproc *vmp, struct vir_region *r, * map_remap * *========================================================================*/ PUBLIC int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size, - struct vir_region *region, vir_bytes *r) + struct vir_region *region, vir_bytes *r, int readonly) { struct vir_region *vr; struct phys_region *ph; @@ -1843,7 +1845,11 @@ PUBLIC int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size, vr->length = size; vr->flags = region->flags; vr->tag = VRT_NONE; - vr->parent = dvmp;); + vr->parent = dvmp; + if(readonly) { + vr->flags &= ~VR_WRITABLE; + } + ); assert(vr->flags & VR_SHARED); region_insert(&dvmp->vm_regions_avl, vr); -- 2.44.0