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