vm_remap_ro

- allows shared memory to be mapped in readonly

- ben@minix3.org & tom@minix3.org
This commit is contained in:
Ben Gras 2011-11-28 19:05:50 +01:00 committed by Tomas Hruby
parent 88f990e122
commit 4668b84158
11 changed files with 72 additions and 12 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@ service ipc
;
vm
REMAP
REMAP_RO
SHM_UNMAP
GETPHYS
GETREF

View file

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

View file

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

View file

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

View file

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

View file

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