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