1 2 /* This file implements the methods of anonymous memory. 3 * 4 * Anonymous memory is memory that is for private use to a process 5 * and can not be related to a file (hence anonymous). 6 */ 7 8 #include <assert.h> 9 10 #include "proto.h" 11 #include "vm.h" 12 #include "region.h" 13 #include "glo.h" 14 15 /* These functions are static so as to not pollute the 16 * global namespace, and are accessed through their function 17 * pointers. 18 */ 19 20 static void anon_split(struct vmproc *vmp, struct vir_region *vr, 21 struct vir_region *r1, struct vir_region *r2); 22 static int anon_lowshrink(struct vir_region *vr, vir_bytes len); 23 static int anon_unreference(struct phys_region *pr); 24 static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, 25 struct phys_region *ph, int write, vfs_callback_t cb, void *state, 26 int len, int *io); 27 static int anon_sanitycheck(struct phys_region *pr, const char *file, int line); 28 static int anon_writable(struct phys_region *pr); 29 static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); 30 static u32_t anon_regionid(struct vir_region *region); 31 static int anon_refcount(struct vir_region *vr); 32 static int anon_pt_flags(struct vir_region *vr); 33 34 struct mem_type mem_type_anon = { 35 .name = "anonymous memory", 36 .ev_unreference = anon_unreference, 37 .ev_pagefault = anon_pagefault, 38 .ev_resize = anon_resize, 39 .ev_sanitycheck = anon_sanitycheck, 40 .ev_lowshrink = anon_lowshrink, 41 .ev_split = anon_split, 42 .regionid = anon_regionid, 43 .writable = anon_writable, 44 .refcount = anon_refcount, 45 .pt_flags = anon_pt_flags, 46 }; 47 48 static int anon_pt_flags(struct vir_region *vr){ 49 #if defined(__arm__) 50 return ARM_VM_PTE_CACHED; 51 #else 52 return 0; 53 #endif 54 } 55 56 static int anon_unreference(struct phys_region *pr) 57 { 58 assert(pr->ph->refcount == 0); 59 if(pr->ph->phys != MAP_NONE) 60 free_mem(ABS2CLICK(pr->ph->phys), 1); 61 return OK; 62 } 63 64 static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, 65 struct phys_region *ph, int write, vfs_callback_t cb, void *state, 66 int len, int *io) 67 { 68 phys_bytes new_page, new_page_cl; 69 u32_t allocflags; 70 71 allocflags = vrallocflags(region->flags); 72 73 assert(ph->ph->refcount > 0); 74 75 if((new_page_cl = alloc_mem(1, allocflags)) == NO_MEM) { 76 printf("anon_pagefault: out of memory\n"); 77 return ENOMEM; 78 } 79 new_page = CLICK2ABS(new_page_cl); 80 81 /* Totally new block? Create it. */ 82 if(ph->ph->phys == MAP_NONE) { 83 ph->ph->phys = new_page; 84 assert(ph->ph->phys != MAP_NONE); 85 86 return OK; 87 } 88 89 if(ph->ph->refcount < 2 || !write) { 90 /* memory is ready already */ 91 return OK; 92 } 93 94 assert(region->flags & VR_WRITABLE); 95 96 return mem_cow(region, ph, new_page_cl, new_page); 97 } 98 99 static int anon_sanitycheck(struct phys_region *pr, const char *file, int line) 100 { 101 MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK); 102 return OK; 103 } 104 105 static int anon_writable(struct phys_region *pr) 106 { 107 assert(pr->ph->refcount > 0); 108 if(pr->ph->phys == MAP_NONE) 109 return 0; 110 if(pr->parent->remaps > 0) 111 return 1; 112 return pr->ph->refcount == 1; 113 } 114 115 static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l) 116 { 117 /* Shrinking not implemented; silently ignored. 118 * (Which is ok for brk().) 119 */ 120 if(l <= vr->length) 121 return OK; 122 123 assert(vr); 124 assert(vr->flags & VR_ANON); 125 assert(!(l % VM_PAGE_SIZE)); 126 127 USE(vr, vr->length = l;); 128 129 return OK; 130 } 131 132 static u32_t anon_regionid(struct vir_region *region) 133 { 134 return region->id; 135 } 136 137 static int anon_lowshrink(struct vir_region *vr, vir_bytes len) 138 { 139 return OK; 140 } 141 142 static int anon_refcount(struct vir_region *vr) 143 { 144 return 1 + vr->remaps; 145 } 146 147 static void anon_split(struct vmproc *vmp, struct vir_region *vr, 148 struct vir_region *r1, struct vir_region *r2) 149 { 150 return; 151 } 152