xref: /minix3/minix/servers/vm/utility.c (revision d196e2c33387eb64e579688b8649f271be970f1f)
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>
25*d196e2c3SCristiano 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 
222433d6423SLionel Sambuc /*===========================================================================*
223433d6423SLionel Sambuc  *			      swap_proc_dyn_data	     		     *
224433d6423SLionel Sambuc  *===========================================================================*/
22563483e02SCristiano Giuffrida int swap_proc_dyn_data(struct vmproc *src_vmp, struct vmproc *dst_vmp,
22663483e02SCristiano Giuffrida 	int sys_upd_flags)
227433d6423SLionel Sambuc {
228433d6423SLionel Sambuc 	int is_vm;
229433d6423SLionel Sambuc 	int r;
23063483e02SCristiano Giuffrida 	struct vir_region *start_vr, *end_vr;
231433d6423SLionel Sambuc 
232433d6423SLionel Sambuc 	is_vm = (dst_vmp->vm_endpoint == VM_PROC_NR);
233433d6423SLionel Sambuc 
23463483e02SCristiano Giuffrida         /* For VM, transfer memory mapped regions first. */
235433d6423SLionel Sambuc         if(is_vm) {
236433d6423SLionel Sambuc #if LU_DEBUG
23763483e02SCristiano Giuffrida 		printf("VM: swap_proc_dyn_data: tranferring memory mapped regions from old (%d) to new VM (%d)\n",
238433d6423SLionel Sambuc 			src_vmp->vm_endpoint, dst_vmp->vm_endpoint);
239433d6423SLionel Sambuc #endif
24063483e02SCristiano Giuffrida 		r = pt_map_in_range(src_vmp, dst_vmp, VM_OWN_HEAPBASE, VM_OWN_MMAPTOP);
241433d6423SLionel Sambuc 		if(r != OK) {
242433d6423SLionel Sambuc 			printf("swap_proc_dyn_data: pt_map_in_range failed\n");
243433d6423SLionel Sambuc 			return r;
244433d6423SLionel Sambuc 		}
245433d6423SLionel Sambuc         }
246433d6423SLionel Sambuc 
247433d6423SLionel Sambuc #if LU_DEBUG
248433d6423SLionel Sambuc 	printf("VM: swap_proc_dyn_data: swapping regions' parents for %d (%d) and %d (%d)\n",
249433d6423SLionel Sambuc 	    src_vmp->vm_endpoint, src_vmp->vm_slot,
250433d6423SLionel Sambuc 	    dst_vmp->vm_endpoint, dst_vmp->vm_slot);
251433d6423SLionel Sambuc #endif
252433d6423SLionel Sambuc 
253433d6423SLionel Sambuc 	/* Swap vir_regions' parents. */
254433d6423SLionel Sambuc 	map_setparent(src_vmp);
255433d6423SLionel Sambuc 	map_setparent(dst_vmp);
256433d6423SLionel Sambuc 
25763483e02SCristiano Giuffrida 	/* Don't transfer mmapped regions if not required. */
25863483e02SCristiano Giuffrida 	if(is_vm || (sys_upd_flags & (SF_VM_ROLLBACK|SF_VM_NOMMAP))) {
25963483e02SCristiano Giuffrida 		return OK;
26063483e02SCristiano Giuffrida 	}
26163483e02SCristiano Giuffrida 
26263483e02SCristiano Giuffrida 	/* Make sure regions are consistent. */
26363483e02SCristiano Giuffrida 	assert(region_search_root(&src_vmp->vm_regions_avl) && region_search_root(&dst_vmp->vm_regions_avl));
26463483e02SCristiano Giuffrida 
26563483e02SCristiano Giuffrida 	/* Transfer memory mapped regions now. To sandbox the new instance and
26663483e02SCristiano Giuffrida 	 * prevent state corruption on rollback, we share all the regions
26763483e02SCristiano Giuffrida 	 * between the two instances as COW.
268433d6423SLionel Sambuc 	 */
26963483e02SCristiano Giuffrida 	start_vr = region_search(&dst_vmp->vm_regions_avl, VM_MMAPBASE, AVL_GREATER_EQUAL);
27063483e02SCristiano Giuffrida 	end_vr = region_search(&dst_vmp->vm_regions_avl, VM_MMAPTOP, AVL_LESS);
27163483e02SCristiano Giuffrida 	if(start_vr) {
272433d6423SLionel Sambuc #if LU_DEBUG
27363483e02SCristiano Giuffrida 		printf("VM: swap_proc_dyn_data: tranferring memory mapped regions from %d to %d\n",
27463483e02SCristiano Giuffrida 			dst_vmp->vm_endpoint, src_vmp->vm_endpoint);
275433d6423SLionel Sambuc #endif
27663483e02SCristiano Giuffrida 		assert(end_vr);
27763483e02SCristiano Giuffrida 		r = map_proc_copy_range(src_vmp, dst_vmp, start_vr, end_vr);
278433d6423SLionel Sambuc 		if(r != OK) {
279433d6423SLionel Sambuc 			return r;
280433d6423SLionel Sambuc 		}
281433d6423SLionel Sambuc 	}
282433d6423SLionel Sambuc 
283433d6423SLionel Sambuc 	return OK;
284433d6423SLionel Sambuc }
285433d6423SLionel Sambuc 
286433d6423SLionel Sambuc void *mmap(void *addr, size_t len, int f, int f2, int f3, off_t o)
287433d6423SLionel Sambuc {
288433d6423SLionel Sambuc 	void *ret;
289433d6423SLionel Sambuc 	phys_bytes p;
290433d6423SLionel Sambuc 
291433d6423SLionel Sambuc 	assert(!addr);
292433d6423SLionel Sambuc 	assert(!(len % VM_PAGE_SIZE));
293433d6423SLionel Sambuc 
294433d6423SLionel Sambuc 	ret = vm_allocpages(&p, VMP_SLAB, len/VM_PAGE_SIZE);
295433d6423SLionel Sambuc 
296433d6423SLionel Sambuc 	if(!ret) return MAP_FAILED;
297433d6423SLionel Sambuc 	memset(ret, 0, len);
298433d6423SLionel Sambuc 	return ret;
299433d6423SLionel Sambuc }
300433d6423SLionel Sambuc 
301433d6423SLionel Sambuc int munmap(void * addr, size_t len)
302433d6423SLionel Sambuc {
303433d6423SLionel Sambuc 	vm_freepages((vir_bytes) addr, roundup(len, VM_PAGE_SIZE)/VM_PAGE_SIZE);
304433d6423SLionel Sambuc 	return 0;
305433d6423SLionel Sambuc }
306433d6423SLionel Sambuc 
307*d196e2c3SCristiano Giuffrida #ifdef __weak_alias
308*d196e2c3SCristiano Giuffrida __weak_alias(brk, _brk)
309*d196e2c3SCristiano Giuffrida #endif
310*d196e2c3SCristiano Giuffrida int _brk(void *addr)
311433d6423SLionel Sambuc {
312433d6423SLionel Sambuc 	/* brk is a special case function to allow vm itself to
313433d6423SLionel Sambuc 	   allocate memory in it's own (cacheable) HEAP */
314433d6423SLionel Sambuc 	vir_bytes target = roundup((vir_bytes)addr, VM_PAGE_SIZE), v;
315433d6423SLionel Sambuc 	extern char _end;
316433d6423SLionel Sambuc 	extern char *_brksize;
317433d6423SLionel Sambuc 	static vir_bytes prevbrk = (vir_bytes) &_end;
318433d6423SLionel Sambuc 	struct vmproc *vmprocess = &vmproc[VM_PROC_NR];
319433d6423SLionel Sambuc 
320433d6423SLionel Sambuc 	for(v = roundup(prevbrk, VM_PAGE_SIZE); v < target;
321433d6423SLionel Sambuc 		v += VM_PAGE_SIZE) {
322433d6423SLionel Sambuc 		phys_bytes mem, newpage = alloc_mem(1, 0);
323433d6423SLionel Sambuc 		if(newpage == NO_MEM) return -1;
324433d6423SLionel Sambuc 		mem = CLICK2ABS(newpage);
325433d6423SLionel Sambuc 		if(pt_writemap(vmprocess, &vmprocess->vm_pt,
326433d6423SLionel Sambuc 			v, mem, VM_PAGE_SIZE,
327433d6423SLionel Sambuc 			  ARCH_VM_PTE_PRESENT
328433d6423SLionel Sambuc 			| ARCH_VM_PTE_USER
329433d6423SLionel Sambuc 			| ARCH_VM_PTE_RW
330433d6423SLionel Sambuc #if defined(__arm__)
331433d6423SLionel Sambuc 			| ARM_VM_PTE_CACHED
332433d6423SLionel Sambuc #endif
333433d6423SLionel Sambuc 			, 0) != OK) {
334433d6423SLionel Sambuc 			free_mem(newpage, 1);
335433d6423SLionel Sambuc 			return -1;
336433d6423SLionel Sambuc 		}
337433d6423SLionel Sambuc 		prevbrk = v + VM_PAGE_SIZE;
338433d6423SLionel Sambuc 	}
339433d6423SLionel Sambuc 
340433d6423SLionel Sambuc         _brksize = (char *) addr;
341433d6423SLionel Sambuc 
342433d6423SLionel Sambuc         if(sys_vmctl(SELF, VMCTL_FLUSHTLB, 0) != OK)
343433d6423SLionel Sambuc         	panic("flushtlb failed");
344433d6423SLionel Sambuc 
345433d6423SLionel Sambuc 	return 0;
346433d6423SLionel Sambuc }
347433d6423SLionel Sambuc 
348433d6423SLionel Sambuc /*===========================================================================*
349433d6423SLionel Sambuc  *				do_getrusage		     		     *
350433d6423SLionel Sambuc  *===========================================================================*/
351433d6423SLionel Sambuc int do_getrusage(message *m)
352433d6423SLionel Sambuc {
353433d6423SLionel Sambuc 	int res, slot;
354433d6423SLionel Sambuc 	struct vmproc *vmp;
355433d6423SLionel Sambuc 	struct rusage r_usage;
356433d6423SLionel Sambuc 	if ((res = vm_isokendpt(m->m_source, &slot)) != OK)
357433d6423SLionel Sambuc 		return ESRCH;
358433d6423SLionel Sambuc 
359433d6423SLionel Sambuc 	vmp = &vmproc[slot];
360433d6423SLionel Sambuc 
361433d6423SLionel Sambuc 	if ((res = sys_datacopy(m->m_source, m->m_lc_vm_rusage.addr,
362433d6423SLionel Sambuc 		SELF, (vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0)
363433d6423SLionel Sambuc 		return res;
364433d6423SLionel Sambuc 
365433d6423SLionel Sambuc 	r_usage.ru_maxrss = vmp->vm_total_max;
366433d6423SLionel Sambuc 	r_usage.ru_minflt = vmp->vm_minor_page_fault;
367433d6423SLionel Sambuc 	r_usage.ru_majflt = vmp->vm_major_page_fault;
368433d6423SLionel Sambuc 
369433d6423SLionel Sambuc 	return sys_datacopy(SELF, (vir_bytes) &r_usage, m->m_source,
370433d6423SLionel Sambuc 		m->m_lc_vm_rusage.addr, (vir_bytes) sizeof(r_usage));
371433d6423SLionel Sambuc }
37263483e02SCristiano Giuffrida 
37363483e02SCristiano Giuffrida /*===========================================================================*
37463483e02SCristiano Giuffrida  *                            adjust_proc_refs                              *
37563483e02SCristiano Giuffrida  *===========================================================================*/
37663483e02SCristiano Giuffrida void adjust_proc_refs()
37763483e02SCristiano Giuffrida {
37863483e02SCristiano Giuffrida        struct vmproc *vmp;
37963483e02SCristiano Giuffrida        region_iter iter;
38063483e02SCristiano Giuffrida 
38163483e02SCristiano Giuffrida        /* Fix up region parents. */
38263483e02SCristiano Giuffrida        for(vmp = vmproc; vmp < &vmproc[VMP_NR]; vmp++) {
38363483e02SCristiano Giuffrida                struct vir_region *vr;
38463483e02SCristiano Giuffrida                if(!(vmp->vm_flags & VMF_INUSE))
38563483e02SCristiano Giuffrida                        continue;
38663483e02SCristiano Giuffrida                region_start_iter_least(&vmp->vm_regions_avl, &iter);
38763483e02SCristiano Giuffrida                while((vr = region_get_iter(&iter))) {
38863483e02SCristiano Giuffrida                        USE(vr, vr->parent = vmp;);
38963483e02SCristiano Giuffrida                        region_incr_iter(&iter);
39063483e02SCristiano Giuffrida                }
39163483e02SCristiano Giuffrida        }
39263483e02SCristiano Giuffrida }
39363483e02SCristiano Giuffrida 
394