xref: /minix3/minix/servers/vm/utility.c (revision 95cb93971a479dc5508602cf0acebc5573e19f6d)
1433d6423SLionel Sambuc 
2433d6423SLionel Sambuc /* This file contains some utility routines for VM.  */
3433d6423SLionel Sambuc 
4433d6423SLionel Sambuc #define _SYSTEM		1
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc #include <minix/callnr.h>
7433d6423SLionel Sambuc #include <minix/com.h>
8433d6423SLionel Sambuc #include <minix/config.h>
9433d6423SLionel Sambuc #include <minix/const.h>
10433d6423SLionel Sambuc #include <minix/ds.h>
11433d6423SLionel Sambuc #include <minix/endpoint.h>
12433d6423SLionel Sambuc #include <minix/minlib.h>
13433d6423SLionel Sambuc #include <minix/type.h>
14433d6423SLionel Sambuc #include <minix/ipc.h>
15433d6423SLionel Sambuc #include <minix/sysutil.h>
16433d6423SLionel Sambuc #include <minix/syslib.h>
17433d6423SLionel Sambuc #include <minix/type.h>
18433d6423SLionel Sambuc #include <minix/bitmap.h>
1963483e02SCristiano Giuffrida #include <minix/rs.h>
20433d6423SLionel Sambuc #include <string.h>
21433d6423SLionel Sambuc #include <errno.h>
22433d6423SLionel Sambuc #include <env.h>
23433d6423SLionel Sambuc #include <unistd.h>
24433d6423SLionel Sambuc #include <assert.h>
25d196e2c3SCristiano Giuffrida #include <sys/cdefs.h>
26433d6423SLionel Sambuc #include <sys/param.h>
27433d6423SLionel Sambuc #include <sys/mman.h>
28433d6423SLionel Sambuc #include <sys/resource.h>
29433d6423SLionel Sambuc 
30433d6423SLionel Sambuc #include "proto.h"
31433d6423SLionel Sambuc #include "glo.h"
32433d6423SLionel Sambuc #include "util.h"
33433d6423SLionel Sambuc #include "region.h"
34433d6423SLionel Sambuc #include "sanitycheck.h"
35433d6423SLionel Sambuc 
36433d6423SLionel Sambuc #include <machine/archtypes.h>
37433d6423SLionel Sambuc #include "kernel/const.h"
38433d6423SLionel Sambuc #include "kernel/config.h"
39433d6423SLionel Sambuc #include "kernel/type.h"
40433d6423SLionel Sambuc #include "kernel/proc.h"
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc /*===========================================================================*
43433d6423SLionel Sambuc  *                              get_mem_chunks                               *
44433d6423SLionel Sambuc  *===========================================================================*/
45433d6423SLionel Sambuc void get_mem_chunks(
46433d6423SLionel Sambuc struct memory *mem_chunks)                      /* store mem chunks here */
47433d6423SLionel Sambuc {
48433d6423SLionel Sambuc /* Initialize the free memory list from the kernel-provided memory map.  Translate
49433d6423SLionel Sambuc  * the byte offsets and sizes in this list to clicks, properly truncated.
50433d6423SLionel Sambuc  */
51433d6423SLionel Sambuc   phys_bytes base, size, limit;
52433d6423SLionel Sambuc   int i;
53433d6423SLionel Sambuc   struct memory *memp;
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc   /* Initialize everything to zero. */
56433d6423SLionel Sambuc   memset(mem_chunks, 0, NR_MEMS*sizeof(*mem_chunks));
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc   /* Obtain and parse memory from kernel environment. */
59433d6423SLionel Sambuc   /* XXX Any memory chunk in excess of NR_MEMS is silently ignored. */
60433d6423SLionel Sambuc   for(i = 0; i < MIN(MAXMEMMAP, NR_MEMS); i++) {
61433d6423SLionel Sambuc   	mem_chunks[i].base = kernel_boot_info.memmap[i].mm_base_addr;
62433d6423SLionel Sambuc   	mem_chunks[i].size = kernel_boot_info.memmap[i].mm_length;
63433d6423SLionel Sambuc   }
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc   /* Round physical memory to clicks. Round start up, round end down. */
66433d6423SLionel Sambuc   for (i = 0; i < NR_MEMS; i++) {
67433d6423SLionel Sambuc         memp = &mem_chunks[i];          /* next mem chunk is stored here */
68433d6423SLionel Sambuc         base = mem_chunks[i].base;
69433d6423SLionel Sambuc         size = mem_chunks[i].size;
70433d6423SLionel Sambuc         limit = base + size;
71433d6423SLionel Sambuc         base = (phys_bytes) (CLICK_CEIL(base));
72433d6423SLionel Sambuc         limit = (phys_bytes) (CLICK_FLOOR(limit));
73433d6423SLionel Sambuc         if (limit <= base) {
74433d6423SLionel Sambuc                 memp->base = memp->size = 0;
75433d6423SLionel Sambuc         } else {
76433d6423SLionel Sambuc                 memp->base = base >> CLICK_SHIFT;
77433d6423SLionel Sambuc                 memp->size = (limit - base) >> CLICK_SHIFT;
78433d6423SLionel Sambuc         }
79433d6423SLionel Sambuc   }
80433d6423SLionel Sambuc }
81433d6423SLionel Sambuc 
82433d6423SLionel Sambuc /*===========================================================================*
83433d6423SLionel Sambuc  *                              vm_isokendpt                           	     *
84433d6423SLionel Sambuc  *===========================================================================*/
85433d6423SLionel Sambuc int vm_isokendpt(endpoint_t endpoint, int *procn)
86433d6423SLionel Sambuc {
87433d6423SLionel Sambuc         *procn = _ENDPOINT_P(endpoint);
88433d6423SLionel Sambuc         if(*procn < 0 || *procn >= NR_PROCS)
89433d6423SLionel Sambuc 		return EINVAL;
90433d6423SLionel Sambuc         if(*procn >= 0 && endpoint != vmproc[*procn].vm_endpoint)
91433d6423SLionel Sambuc                 return EDEADEPT;
92433d6423SLionel Sambuc         if(*procn >= 0 && !(vmproc[*procn].vm_flags & VMF_INUSE))
93433d6423SLionel Sambuc                 return EDEADEPT;
94433d6423SLionel Sambuc         return OK;
95433d6423SLionel Sambuc }
96433d6423SLionel Sambuc 
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc /*===========================================================================*
99433d6423SLionel Sambuc  *                              do_info                                      *
100433d6423SLionel Sambuc  *===========================================================================*/
101433d6423SLionel Sambuc int do_info(message *m)
102433d6423SLionel Sambuc {
103433d6423SLionel Sambuc 	struct vm_stats_info vsi;
104433d6423SLionel Sambuc 	struct vm_usage_info vui;
105433d6423SLionel Sambuc 	static struct vm_region_info vri[MAX_VRI_COUNT];
106433d6423SLionel Sambuc 	struct vmproc *vmp;
107433d6423SLionel Sambuc 	vir_bytes addr, size, next, ptr;
108433d6423SLionel Sambuc 	int r, pr, dummy, count, free_pages, largest_contig;
109433d6423SLionel Sambuc 
110433d6423SLionel Sambuc 	if (vm_isokendpt(m->m_source, &pr) != OK)
111433d6423SLionel Sambuc 		return EINVAL;
112433d6423SLionel Sambuc 	vmp = &vmproc[pr];
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc 	ptr = (vir_bytes) m->m_lsys_vm_info.ptr;
115433d6423SLionel Sambuc 
116433d6423SLionel Sambuc 	switch(m->m_lsys_vm_info.what) {
117433d6423SLionel Sambuc 	case VMIW_STATS:
118433d6423SLionel Sambuc 		vsi.vsi_pagesize = VM_PAGE_SIZE;
119433d6423SLionel Sambuc 		vsi.vsi_total = total_pages;
120433d6423SLionel Sambuc 		memstats(&dummy, &free_pages, &largest_contig);
121433d6423SLionel Sambuc 		vsi.vsi_free = free_pages;
122433d6423SLionel Sambuc 		vsi.vsi_largest = largest_contig;
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc 		get_stats_info(&vsi);
125433d6423SLionel Sambuc 
126433d6423SLionel Sambuc 		addr = (vir_bytes) &vsi;
127433d6423SLionel Sambuc 		size = sizeof(vsi);
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc 		break;
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc 	case VMIW_USAGE:
132433d6423SLionel Sambuc 		if(m->m_lsys_vm_info.ep < 0)
133433d6423SLionel Sambuc 			get_usage_info_kernel(&vui);
134433d6423SLionel Sambuc 		else if (vm_isokendpt(m->m_lsys_vm_info.ep, &pr) != OK)
135433d6423SLionel Sambuc 			return EINVAL;
136433d6423SLionel Sambuc 		else get_usage_info(&vmproc[pr], &vui);
137433d6423SLionel Sambuc 
138433d6423SLionel Sambuc 		addr = (vir_bytes) &vui;
139433d6423SLionel Sambuc 		size = sizeof(vui);
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc 		break;
142433d6423SLionel Sambuc 
143433d6423SLionel Sambuc 	case VMIW_REGION:
14465b4b952SCristiano Giuffrida 		if(m->m_lsys_vm_info.ep == SELF) {
14565b4b952SCristiano Giuffrida 			m->m_lsys_vm_info.ep = m->m_source;
14665b4b952SCristiano Giuffrida 		}
147433d6423SLionel Sambuc 		if (vm_isokendpt(m->m_lsys_vm_info.ep, &pr) != OK)
148433d6423SLionel Sambuc 			return EINVAL;
149433d6423SLionel Sambuc 
150433d6423SLionel Sambuc 		count = MIN(m->m_lsys_vm_info.count, MAX_VRI_COUNT);
151433d6423SLionel Sambuc 		next = m->m_lsys_vm_info.next;
152433d6423SLionel Sambuc 
153433d6423SLionel Sambuc 		count = get_region_info(&vmproc[pr], vri, count, &next);
154433d6423SLionel Sambuc 
155433d6423SLionel Sambuc 		m->m_lsys_vm_info.count = count;
156433d6423SLionel Sambuc 		m->m_lsys_vm_info.next = next;
157433d6423SLionel Sambuc 
158433d6423SLionel Sambuc 		addr = (vir_bytes) vri;
159433d6423SLionel Sambuc 		size = sizeof(vri[0]) * count;
160433d6423SLionel Sambuc 
161433d6423SLionel Sambuc 		break;
162433d6423SLionel Sambuc 
163433d6423SLionel Sambuc 	default:
164433d6423SLionel Sambuc 		return EINVAL;
165433d6423SLionel Sambuc 	}
166433d6423SLionel Sambuc 
167433d6423SLionel Sambuc 	if (size == 0)
168433d6423SLionel Sambuc 		return OK;
169433d6423SLionel Sambuc 
170433d6423SLionel Sambuc 	/* Make sure that no page faults can occur while copying out. A page
171433d6423SLionel Sambuc 	 * fault would cause the kernel to send a notify to us, while we would
172433d6423SLionel Sambuc 	 * be waiting for the result of the copy system call, resulting in a
173433d6423SLionel Sambuc 	 * deadlock. Note that no memory mapping can be undone without the
174433d6423SLionel Sambuc 	 * involvement of VM, so we are safe until we're done.
175433d6423SLionel Sambuc 	 */
176433d6423SLionel Sambuc 	r = handle_memory_once(vmp, ptr, size, 1 /*wrflag*/);
177433d6423SLionel Sambuc 	if (r != OK) return r;
178433d6423SLionel Sambuc 
179433d6423SLionel Sambuc 	/* Now that we know the copy out will succeed, perform the actual copy
180433d6423SLionel Sambuc 	 * operation.
181433d6423SLionel Sambuc 	 */
182433d6423SLionel Sambuc 	return sys_datacopy(SELF, addr,
183433d6423SLionel Sambuc 		(vir_bytes) vmp->vm_endpoint, ptr, size);
184433d6423SLionel Sambuc }
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc /*===========================================================================*
187433d6423SLionel Sambuc  *				swap_proc_slot	     			     *
188433d6423SLionel Sambuc  *===========================================================================*/
189433d6423SLionel Sambuc int swap_proc_slot(struct vmproc *src_vmp, struct vmproc *dst_vmp)
190433d6423SLionel Sambuc {
191433d6423SLionel Sambuc 	struct vmproc orig_src_vmproc, orig_dst_vmproc;
192433d6423SLionel Sambuc 
193433d6423SLionel Sambuc #if LU_DEBUG
194433d6423SLionel Sambuc 	printf("VM: swap_proc: swapping %d (%d) and %d (%d)\n",
195433d6423SLionel Sambuc 	    src_vmp->vm_endpoint, src_vmp->vm_slot,
196433d6423SLionel Sambuc 	    dst_vmp->vm_endpoint, dst_vmp->vm_slot);
197433d6423SLionel Sambuc #endif
198433d6423SLionel Sambuc 
199433d6423SLionel Sambuc 	/* Save existing data. */
200433d6423SLionel Sambuc 	orig_src_vmproc = *src_vmp;
201433d6423SLionel Sambuc 	orig_dst_vmproc = *dst_vmp;
202433d6423SLionel Sambuc 
203433d6423SLionel Sambuc 	/* Swap slots. */
204433d6423SLionel Sambuc 	*src_vmp = orig_dst_vmproc;
205433d6423SLionel Sambuc 	*dst_vmp = orig_src_vmproc;
206433d6423SLionel Sambuc 
207433d6423SLionel Sambuc 	/* Preserve endpoints and slot numbers. */
208433d6423SLionel Sambuc 	src_vmp->vm_endpoint = orig_src_vmproc.vm_endpoint;
209433d6423SLionel Sambuc 	src_vmp->vm_slot = orig_src_vmproc.vm_slot;
210433d6423SLionel Sambuc 	dst_vmp->vm_endpoint = orig_dst_vmproc.vm_endpoint;
211433d6423SLionel Sambuc 	dst_vmp->vm_slot = orig_dst_vmproc.vm_slot;
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc #if LU_DEBUG
214433d6423SLionel Sambuc 	printf("VM: swap_proc: swapped %d (%d) and %d (%d)\n",
215433d6423SLionel Sambuc 	    src_vmp->vm_endpoint, src_vmp->vm_slot,
216433d6423SLionel Sambuc 	    dst_vmp->vm_endpoint, dst_vmp->vm_slot);
217433d6423SLionel Sambuc #endif
218433d6423SLionel Sambuc 
219433d6423SLionel Sambuc 	return OK;
220433d6423SLionel Sambuc }
221433d6423SLionel Sambuc 
222*95cb9397SDavid van Moolenbroek /*
223*95cb9397SDavid van Moolenbroek  * Transfer memory mapped regions, using CoW sharing, from 'src_vmp' to
224*95cb9397SDavid van Moolenbroek  * 'dst_vmp', for the source process's address range of 'start_addr'
225*95cb9397SDavid van Moolenbroek  * (inclusive) to 'end_addr' (exclusive).  Return OK or an error code.
226*95cb9397SDavid van Moolenbroek  */
227*95cb9397SDavid van Moolenbroek static int
228*95cb9397SDavid van Moolenbroek transfer_mmap_regions(struct vmproc *dst_vmp, struct vmproc *src_vmp,
229*95cb9397SDavid van Moolenbroek 	vir_bytes start_addr, vir_bytes end_addr)
230*95cb9397SDavid van Moolenbroek {
231*95cb9397SDavid van Moolenbroek 	struct vir_region *start_vr, *end_vr;
232*95cb9397SDavid van Moolenbroek 
233*95cb9397SDavid van Moolenbroek 	start_vr = region_search(&src_vmp->vm_regions_avl, start_addr,
234*95cb9397SDavid van Moolenbroek 	    AVL_GREATER_EQUAL);
235*95cb9397SDavid van Moolenbroek 
236*95cb9397SDavid van Moolenbroek 	if (start_vr == NULL || start_vr->vaddr >= end_addr)
237*95cb9397SDavid van Moolenbroek 		return OK; /* nothing to do */
238*95cb9397SDavid van Moolenbroek 
239*95cb9397SDavid van Moolenbroek 	end_vr = region_search(&src_vmp->vm_regions_avl, end_addr, AVL_LESS);
240*95cb9397SDavid van Moolenbroek 	assert(end_vr != NULL);
241*95cb9397SDavid van Moolenbroek 	assert(start_vr->vaddr <= end_vr->vaddr);
242*95cb9397SDavid van Moolenbroek 
243*95cb9397SDavid van Moolenbroek #if LU_DEBUG
244*95cb9397SDavid van Moolenbroek 	printf("VM: transfer_mmap_regions: transferring memory mapped regions "
245*95cb9397SDavid van Moolenbroek 	    "from %d to %d (0x%lx to 0x%lx)\n", src_vmp->vm_endpoint,
246*95cb9397SDavid van Moolenbroek 	    dst_vmp->vm_endpoint, start_vr->vaddr, end_vr->vaddr);
247*95cb9397SDavid van Moolenbroek #endif
248*95cb9397SDavid van Moolenbroek 
249*95cb9397SDavid van Moolenbroek 	return map_proc_copy_range(dst_vmp, src_vmp, start_vr, end_vr);
250*95cb9397SDavid van Moolenbroek }
251*95cb9397SDavid van Moolenbroek 
252433d6423SLionel Sambuc /*===========================================================================*
253433d6423SLionel Sambuc  *			      swap_proc_dyn_data	     		     *
254433d6423SLionel Sambuc  *===========================================================================*/
25563483e02SCristiano Giuffrida int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp,
25663483e02SCristiano Giuffrida 	int sys_upd_flags)
257433d6423SLionel Sambuc {
258433d6423SLionel Sambuc 	int is_vm;
259433d6423SLionel Sambuc 	int r;
260433d6423SLionel Sambuc 
261433d6423SLionel Sambuc 	is_vm = (dst_vmp->vm_endpoint == VM_PROC_NR);
262433d6423SLionel Sambuc 
26363483e02SCristiano Giuffrida         /* For VM, transfer memory mapped regions first. */
264433d6423SLionel Sambuc         if(is_vm) {
265433d6423SLionel Sambuc #if LU_DEBUG
26663483e02SCristiano Giuffrida 		printf("VM: swap_proc_dyn_data: tranferring memory mapped regions from old (%d) to new VM (%d)\n",
267433d6423SLionel Sambuc 			src_vmp->vm_endpoint, dst_vmp->vm_endpoint);
268433d6423SLionel Sambuc #endif
26963483e02SCristiano Giuffrida 		r = pt_map_in_range(src_vmp, dst_vmp, VM_OWN_HEAPBASE, VM_OWN_MMAPTOP);
270433d6423SLionel Sambuc 		if(r != OK) {
271433d6423SLionel Sambuc 			printf("swap_proc_dyn_data: pt_map_in_range failed\n");
272433d6423SLionel Sambuc 			return r;
273433d6423SLionel Sambuc 		}
274a6db4d0aSDirk Vogt 		r = pt_map_in_range(src_vmp, dst_vmp, VM_STACKTOP, VM_DATATOP);
275a6db4d0aSDirk Vogt 		if(r != OK) {
276a6db4d0aSDirk Vogt 			printf("swap_proc_dyn_data: pt_map_in_range failed\n");
277a6db4d0aSDirk Vogt 			return r;
278a6db4d0aSDirk Vogt 		}
279a6db4d0aSDirk Vogt 
280433d6423SLionel Sambuc         }
281433d6423SLionel Sambuc 
282433d6423SLionel Sambuc #if LU_DEBUG
283433d6423SLionel Sambuc 	printf("VM: swap_proc_dyn_data: swapping regions' parents for %d (%d) and %d (%d)\n",
284433d6423SLionel Sambuc 	    src_vmp->vm_endpoint, src_vmp->vm_slot,
285433d6423SLionel Sambuc 	    dst_vmp->vm_endpoint, dst_vmp->vm_slot);
286433d6423SLionel Sambuc #endif
287433d6423SLionel Sambuc 
288433d6423SLionel Sambuc 	/* Swap vir_regions' parents. */
289433d6423SLionel Sambuc 	map_setparent(src_vmp);
290433d6423SLionel Sambuc 	map_setparent(dst_vmp);
291433d6423SLionel Sambuc 
29263483e02SCristiano Giuffrida 	/* Don't transfer mmapped regions if not required. */
29363483e02SCristiano Giuffrida 	if(is_vm || (sys_upd_flags & (SF_VM_ROLLBACK|SF_VM_NOMMAP))) {
29463483e02SCristiano Giuffrida 		return OK;
29563483e02SCristiano Giuffrida 	}
29663483e02SCristiano Giuffrida 
29763483e02SCristiano Giuffrida 	/* Make sure regions are consistent. */
29863483e02SCristiano Giuffrida 	assert(region_search_root(&src_vmp->vm_regions_avl) && region_search_root(&dst_vmp->vm_regions_avl));
29963483e02SCristiano Giuffrida 
30063483e02SCristiano Giuffrida 	/* Transfer memory mapped regions now. To sandbox the new instance and
30163483e02SCristiano Giuffrida 	 * prevent state corruption on rollback, we share all the regions
302*95cb9397SDavid van Moolenbroek 	 * between the two instances as COW. Source and destination are
303*95cb9397SDavid van Moolenbroek 	 * intentionally swapped in these calls!
304433d6423SLionel Sambuc 	 */
305*95cb9397SDavid van Moolenbroek 	r = transfer_mmap_regions(src_vmp, dst_vmp, VM_MMAPBASE, VM_MMAPTOP);
306433d6423SLionel Sambuc 
307a6db4d0aSDirk Vogt 	/* If the stack is not mapped at the VM_DATATOP, there might be some
308a6db4d0aSDirk Vogt 	 * more regions hiding above the stack.  We also have to transfer
309a6db4d0aSDirk Vogt 	 * those.
310a6db4d0aSDirk Vogt 	 */
311*95cb9397SDavid van Moolenbroek 	if (r == OK && VM_STACKTOP < VM_DATATOP)
312*95cb9397SDavid van Moolenbroek 		r = transfer_mmap_regions(src_vmp, dst_vmp, VM_STACKTOP,
313*95cb9397SDavid van Moolenbroek 		    VM_DATATOP);
314a6db4d0aSDirk Vogt 
315a6db4d0aSDirk Vogt 	return r;
316a6db4d0aSDirk Vogt }
317433d6423SLionel Sambuc 
318433d6423SLionel Sambuc void *mmap(void *addr, size_t len, int f, int f2, int f3, off_t o)
319433d6423SLionel Sambuc {
320433d6423SLionel Sambuc 	void *ret;
321433d6423SLionel Sambuc 	phys_bytes p;
322433d6423SLionel Sambuc 
323433d6423SLionel Sambuc 	assert(!addr);
324433d6423SLionel Sambuc 	assert(!(len % VM_PAGE_SIZE));
325433d6423SLionel Sambuc 
326433d6423SLionel Sambuc 	ret = vm_allocpages(&p, VMP_SLAB, len/VM_PAGE_SIZE);
327433d6423SLionel Sambuc 
328433d6423SLionel Sambuc 	if(!ret) return MAP_FAILED;
329433d6423SLionel Sambuc 	memset(ret, 0, len);
330433d6423SLionel Sambuc 	return ret;
331433d6423SLionel Sambuc }
332433d6423SLionel Sambuc 
333433d6423SLionel Sambuc int munmap(void * addr, size_t len)
334433d6423SLionel Sambuc {
335433d6423SLionel Sambuc 	vm_freepages((vir_bytes) addr, roundup(len, VM_PAGE_SIZE)/VM_PAGE_SIZE);
336433d6423SLionel Sambuc 	return 0;
337433d6423SLionel Sambuc }
338433d6423SLionel Sambuc 
339d196e2c3SCristiano Giuffrida #ifdef __weak_alias
340d196e2c3SCristiano Giuffrida __weak_alias(brk, _brk)
341d196e2c3SCristiano Giuffrida #endif
342d196e2c3SCristiano Giuffrida int _brk(void *addr)
343433d6423SLionel Sambuc {
344433d6423SLionel Sambuc 	/* brk is a special case function to allow vm itself to
345433d6423SLionel Sambuc 	   allocate memory in it's own (cacheable) HEAP */
346433d6423SLionel Sambuc 	vir_bytes target = roundup((vir_bytes)addr, VM_PAGE_SIZE), v;
347433d6423SLionel Sambuc 	extern char _end;
348433d6423SLionel Sambuc 	extern char *_brksize;
349433d6423SLionel Sambuc 	static vir_bytes prevbrk = (vir_bytes) &_end;
350433d6423SLionel Sambuc 	struct vmproc *vmprocess = &vmproc[VM_PROC_NR];
351433d6423SLionel Sambuc 
352433d6423SLionel Sambuc 	for(v = roundup(prevbrk, VM_PAGE_SIZE); v < target;
353433d6423SLionel Sambuc 		v += VM_PAGE_SIZE) {
354433d6423SLionel Sambuc 		phys_bytes mem, newpage = alloc_mem(1, 0);
355433d6423SLionel Sambuc 		if(newpage == NO_MEM) return -1;
356433d6423SLionel Sambuc 		mem = CLICK2ABS(newpage);
357433d6423SLionel Sambuc 		if(pt_writemap(vmprocess, &vmprocess->vm_pt,
358433d6423SLionel Sambuc 			v, mem, VM_PAGE_SIZE,
359433d6423SLionel Sambuc 			  ARCH_VM_PTE_PRESENT
360433d6423SLionel Sambuc 			| ARCH_VM_PTE_USER
361433d6423SLionel Sambuc 			| ARCH_VM_PTE_RW
362433d6423SLionel Sambuc #if defined(__arm__)
363433d6423SLionel Sambuc 			| ARM_VM_PTE_CACHED
364433d6423SLionel Sambuc #endif
365433d6423SLionel Sambuc 			, 0) != OK) {
366433d6423SLionel Sambuc 			free_mem(newpage, 1);
367433d6423SLionel Sambuc 			return -1;
368433d6423SLionel Sambuc 		}
369433d6423SLionel Sambuc 		prevbrk = v + VM_PAGE_SIZE;
370433d6423SLionel Sambuc 	}
371433d6423SLionel Sambuc 
372433d6423SLionel Sambuc         _brksize = (char *) addr;
373433d6423SLionel Sambuc 
374433d6423SLionel Sambuc         if(sys_vmctl(SELF, VMCTL_FLUSHTLB, 0) != OK)
375433d6423SLionel Sambuc         	panic("flushtlb failed");
376433d6423SLionel Sambuc 
377433d6423SLionel Sambuc 	return 0;
378433d6423SLionel Sambuc }
379433d6423SLionel Sambuc 
380433d6423SLionel Sambuc /*===========================================================================*
381433d6423SLionel Sambuc  *				do_getrusage		     		     *
382433d6423SLionel Sambuc  *===========================================================================*/
383433d6423SLionel Sambuc int do_getrusage(message *m)
384433d6423SLionel Sambuc {
385433d6423SLionel Sambuc 	int res, slot;
386433d6423SLionel Sambuc 	struct vmproc *vmp;
387433d6423SLionel Sambuc 	struct rusage r_usage;
388433d6423SLionel Sambuc 	if ((res = vm_isokendpt(m->m_source, &slot)) != OK)
389433d6423SLionel Sambuc 		return ESRCH;
390433d6423SLionel Sambuc 
391433d6423SLionel Sambuc 	vmp = &vmproc[slot];
392433d6423SLionel Sambuc 
393433d6423SLionel Sambuc 	if ((res = sys_datacopy(m->m_source, m->m_lc_vm_rusage.addr,
394433d6423SLionel Sambuc 		SELF, (vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0)
395433d6423SLionel Sambuc 		return res;
396433d6423SLionel Sambuc 
397433d6423SLionel Sambuc 	r_usage.ru_maxrss = vmp->vm_total_max;
398433d6423SLionel Sambuc 	r_usage.ru_minflt = vmp->vm_minor_page_fault;
399433d6423SLionel Sambuc 	r_usage.ru_majflt = vmp->vm_major_page_fault;
400433d6423SLionel Sambuc 
401433d6423SLionel Sambuc 	return sys_datacopy(SELF, (vir_bytes) &r_usage, m->m_source,
402433d6423SLionel Sambuc 		m->m_lc_vm_rusage.addr, (vir_bytes) sizeof(r_usage));
403433d6423SLionel Sambuc }
40463483e02SCristiano Giuffrida 
40563483e02SCristiano Giuffrida /*===========================================================================*
40663483e02SCristiano Giuffrida  *                            adjust_proc_refs                              *
40763483e02SCristiano Giuffrida  *===========================================================================*/
40863483e02SCristiano Giuffrida void adjust_proc_refs()
40963483e02SCristiano Giuffrida {
41063483e02SCristiano Giuffrida        struct vmproc *vmp;
41163483e02SCristiano Giuffrida        region_iter iter;
41263483e02SCristiano Giuffrida 
41363483e02SCristiano Giuffrida        /* Fix up region parents. */
41463483e02SCristiano Giuffrida        for(vmp = vmproc; vmp < &vmproc[VMP_NR]; vmp++) {
41563483e02SCristiano Giuffrida                struct vir_region *vr;
41663483e02SCristiano Giuffrida                if(!(vmp->vm_flags & VMF_INUSE))
41763483e02SCristiano Giuffrida                        continue;
41863483e02SCristiano Giuffrida                region_start_iter_least(&vmp->vm_regions_avl, &iter);
41963483e02SCristiano Giuffrida                while((vr = region_get_iter(&iter))) {
42063483e02SCristiano Giuffrida                        USE(vr, vr->parent = vmp;);
42163483e02SCristiano Giuffrida                        region_incr_iter(&iter);
42263483e02SCristiano Giuffrida                }
42363483e02SCristiano Giuffrida        }
42463483e02SCristiano Giuffrida }
42563483e02SCristiano Giuffrida 
426