vm: use assert() instead of vm_assert(); remove vm_assert().
[minix.git] / servers / vm / utility.c
blobdfe77c264fa0fece9259f449c85a4fa65553e3dc
2 /* This file contains some utility routines for VM. */
4 #define _SYSTEM 1
6 #define _MINIX 1 /* To get the brk() prototype (as _brk()). */
7 #define brk _brk /* Our brk() must redefine _brk(). */
9 #include <minix/callnr.h>
10 #include <minix/com.h>
11 #include <minix/config.h>
12 #include <minix/const.h>
13 #include <minix/ds.h>
14 #include <minix/endpoint.h>
15 #include <minix/minlib.h>
16 #include <minix/type.h>
17 #include <minix/ipc.h>
18 #include <minix/sysutil.h>
19 #include <minix/syslib.h>
20 #include <minix/type.h>
21 #include <minix/bitmap.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <env.h>
25 #include <unistd.h>
26 #include <memory.h>
28 #include "proto.h"
29 #include "glo.h"
30 #include "util.h"
32 #include <machine/archtypes.h>
33 #include "kernel/const.h"
34 #include "kernel/config.h"
35 #include "kernel/type.h"
36 #include "kernel/proc.h"
38 /*===========================================================================*
39 * get_mem_map *
40 *===========================================================================*/
41 PUBLIC int get_mem_map(proc_nr, mem_map)
42 int proc_nr; /* process to get map of */
43 struct mem_map *mem_map; /* put memory map here */
45 struct proc p;
46 int s;
48 if ((s=sys_getproc(&p, proc_nr)) != OK)
49 return(s);
51 memcpy(mem_map, p.p_memmap, sizeof(p.p_memmap));
52 return(OK);
55 /*===========================================================================*
56 * get_mem_chunks *
57 *===========================================================================*/
58 PUBLIC void get_mem_chunks(mem_chunks)
59 struct memory *mem_chunks; /* store mem chunks here */
61 /* Initialize the free memory list from the 'memory' boot variable. Translate
62 * the byte offsets and sizes in this list to clicks, properly truncated.
64 phys_bytes base, size, limit;
65 int i;
66 struct memory *memp;
68 /* Obtain and parse memory from system environment. */
69 if(env_memory_parse(mem_chunks, NR_MEMS) != OK)
70 panic("couldn't obtain memory chunks");
72 /* Round physical memory to clicks. Round start up, round end down. */
73 for (i = 0; i < NR_MEMS; i++) {
74 memp = &mem_chunks[i]; /* next mem chunk is stored here */
75 base = mem_chunks[i].base;
76 size = mem_chunks[i].size;
77 limit = base + size;
78 base = (phys_bytes) (CLICK_CEIL(base));
79 limit = (phys_bytes) (CLICK_FLOOR(limit));
80 if (limit <= base) {
81 memp->base = memp->size = 0;
82 } else {
83 memp->base = base >> CLICK_SHIFT;
84 memp->size = (limit - base) >> CLICK_SHIFT;
89 /*===========================================================================*
90 * reserve_proc_mem *
91 *===========================================================================*/
92 PUBLIC void reserve_proc_mem(mem_chunks, map_ptr)
93 struct memory *mem_chunks; /* store mem chunks here */
94 struct mem_map *map_ptr; /* memory to remove */
96 /* Remove server memory from the free memory list. The boot monitor
97 * promises to put processes at the start of memory chunks. The
98 * tasks all use same base address, so only the first task changes
99 * the memory lists. The servers and init have their own memory
100 * spaces and their memory will be removed from the list.
102 struct memory *memp;
103 for (memp = mem_chunks; memp < &mem_chunks[NR_MEMS]; memp++) {
104 if (memp->base == map_ptr[T].mem_phys) {
105 memp->base += map_ptr[T].mem_len + map_ptr[S].mem_vir;
106 memp->size -= map_ptr[T].mem_len + map_ptr[S].mem_vir;
107 break;
110 if (memp >= &mem_chunks[NR_MEMS])
112 panic("reserve_proc_mem: can't find map in mem_chunks: 0x%lx",
113 map_ptr[T].mem_phys);
117 /*===========================================================================*
118 * vm_isokendpt *
119 *===========================================================================*/
120 PUBLIC int vm_isokendpt(endpoint_t endpoint, int *proc)
122 *proc = _ENDPOINT_P(endpoint);
123 if(*proc < 0 || *proc >= NR_PROCS)
124 return EINVAL;
125 if(*proc >= 0 && endpoint != vmproc[*proc].vm_endpoint)
126 return EDEADSRCDST;
127 if(*proc >= 0 && !(vmproc[*proc].vm_flags & VMF_INUSE))
128 return EDEADSRCDST;
129 return OK;
133 struct proc mytmpproc;
135 /*===========================================================================*
136 * get_stack_ptr *
137 *===========================================================================*/
138 PUBLIC int get_stack_ptr(proc_nr_e, sp)
139 int proc_nr_e; /* process to get sp of */
140 vir_bytes *sp; /* put stack pointer here */
142 int s;
144 if ((s=sys_getproc(&mytmpproc, proc_nr_e)) != OK)
145 return(s);
146 *sp = mytmpproc.p_reg.sp;
147 return(OK);
150 /*===========================================================================*
151 * _brk *
152 *===========================================================================*/
153 extern char *_brksize;
154 PUBLIC int brk(brk_addr)
155 char *brk_addr;
157 int r;
158 struct vmproc *vmm = &vmproc[VM_PROC_NR];
160 /* VM wants to call brk() itself. */
161 if((r=real_brk(vmm, (vir_bytes) brk_addr)) != OK)
162 panic("VM: brk() on myself failed");
163 _brksize = brk_addr;
164 return 0;
167 /*===========================================================================*
168 * do_info *
169 *===========================================================================*/
170 PUBLIC int do_info(message *m)
172 struct vm_stats_info vsi;
173 struct vm_usage_info vui;
174 static struct vm_region_info vri[MAX_VRI_COUNT];
175 struct vmproc *vmp;
176 vir_bytes addr, size, next, ptr;
177 int r, pr, dummy, count;
179 if (vm_isokendpt(m->m_source, &pr) != OK)
180 return EINVAL;
181 vmp = &vmproc[pr];
183 ptr = (vir_bytes) m->VMI_PTR;
185 switch(m->VMI_WHAT) {
186 case VMIW_STATS:
187 vsi.vsi_pagesize = VM_PAGE_SIZE;
188 vsi.vsi_total = total_pages;
189 memstats(&dummy, &vsi.vsi_free, &vsi.vsi_largest);
191 addr = (vir_bytes) &vsi;
192 size = sizeof(vsi);
194 break;
196 case VMIW_USAGE:
197 if (vm_isokendpt(m->VMI_EP, &pr) != OK)
198 return EINVAL;
200 get_usage_info(&vmproc[pr], &vui);
202 addr = (vir_bytes) &vui;
203 size = sizeof(vui);
205 break;
207 case VMIW_REGION:
208 if (vm_isokendpt(m->VMI_EP, &pr) != OK)
209 return EINVAL;
211 count = MIN(m->VMI_COUNT, MAX_VRI_COUNT);
212 next = m->VMI_NEXT;
214 count = get_region_info(&vmproc[pr], vri, count, &next);
216 m->VMI_COUNT = count;
217 m->VMI_NEXT = next;
219 addr = (vir_bytes) vri;
220 size = sizeof(vri[0]) * count;
222 break;
224 default:
225 return EINVAL;
228 if (size == 0)
229 return OK;
231 /* Make sure that no page faults can occur while copying out. A page
232 * fault would cause the kernel to send a notify to us, while we would
233 * be waiting for the result of the copy system call, resulting in a
234 * deadlock. Note that no memory mapping can be undone without the
235 * involvement of VM, so we are safe until we're done.
237 r = handle_memory(vmp, arch_vir2map(vmp, ptr), size, 1 /*wrflag*/);
238 if (r != OK) return r;
240 /* Now that we know the copy out will succeed, perform the actual copy
241 * operation.
243 return sys_datacopy(SELF, addr,
244 (vir_bytes) vmp->vm_endpoint, ptr, size);