2 /* This file contains some utility routines for VM. */
6 #define _MINIX 1 /* To get the brk() prototype (as _brk()). */
8 #include <minix/callnr.h>
10 #include <minix/config.h>
11 #include <minix/const.h>
13 #include <minix/endpoint.h>
14 #include <minix/minlib.h>
15 #include <minix/type.h>
16 #include <minix/ipc.h>
17 #include <minix/sysutil.h>
18 #include <minix/syslib.h>
19 #include <minix/type.h>
20 #include <minix/bitmap.h>
26 #include <sys/param.h>
32 #include "sanitycheck.h"
34 #include <machine/archtypes.h>
35 #include "kernel/const.h"
36 #include "kernel/config.h"
37 #include "kernel/type.h"
38 #include "kernel/proc.h"
40 /*===========================================================================*
42 *===========================================================================*/
43 void get_mem_chunks(mem_chunks
)
44 struct memory
*mem_chunks
; /* store mem chunks here */
46 /* Initialize the free memory list from the 'memory' boot variable. Translate
47 * the byte offsets and sizes in this list to clicks, properly truncated.
49 phys_bytes base
, size
, limit
;
53 /* Obtain and parse memory from system environment. */
54 if(env_memory_parse(mem_chunks
, NR_MEMS
) != OK
)
55 panic("couldn't obtain memory chunks");
57 /* Round physical memory to clicks. Round start up, round end down. */
58 for (i
= 0; i
< NR_MEMS
; i
++) {
59 memp
= &mem_chunks
[i
]; /* next mem chunk is stored here */
60 base
= mem_chunks
[i
].base
;
61 size
= mem_chunks
[i
].size
;
63 base
= (phys_bytes
) (CLICK_CEIL(base
));
64 limit
= (phys_bytes
) (CLICK_FLOOR(limit
));
66 memp
->base
= memp
->size
= 0;
68 memp
->base
= base
>> CLICK_SHIFT
;
69 memp
->size
= (limit
- base
) >> CLICK_SHIFT
;
74 /*===========================================================================*
76 *===========================================================================*/
77 int vm_isokendpt(endpoint_t endpoint
, int *proc
)
79 *proc
= _ENDPOINT_P(endpoint
);
80 if(*proc
< 0 || *proc
>= NR_PROCS
)
82 if(*proc
>= 0 && endpoint
!= vmproc
[*proc
].vm_endpoint
)
84 if(*proc
>= 0 && !(vmproc
[*proc
].vm_flags
& VMF_INUSE
))
90 /*===========================================================================*
92 *===========================================================================*/
93 int do_info(message
*m
)
95 struct vm_stats_info vsi
;
96 struct vm_usage_info vui
;
97 static struct vm_region_info vri
[MAX_VRI_COUNT
];
99 vir_bytes addr
, size
, next
, ptr
;
100 int r
, pr
, dummy
, count
, free_pages
, largest_contig
;
102 if (vm_isokendpt(m
->m_source
, &pr
) != OK
)
106 ptr
= (vir_bytes
) m
->VMI_PTR
;
108 switch(m
->VMI_WHAT
) {
110 vsi
.vsi_pagesize
= VM_PAGE_SIZE
;
111 vsi
.vsi_total
= total_pages
;
112 memstats(&dummy
, &free_pages
, &largest_contig
);
113 vsi
.vsi_free
= free_pages
;
114 vsi
.vsi_largest
= largest_contig
;
116 get_stats_info(&vsi
);
118 addr
= (vir_bytes
) &vsi
;
125 get_usage_info_kernel(&vui
);
126 else if (vm_isokendpt(m
->VMI_EP
, &pr
) != OK
)
128 else get_usage_info(&vmproc
[pr
], &vui
);
130 addr
= (vir_bytes
) &vui
;
136 if (vm_isokendpt(m
->VMI_EP
, &pr
) != OK
)
139 count
= MIN(m
->VMI_COUNT
, MAX_VRI_COUNT
);
142 count
= get_region_info(&vmproc
[pr
], vri
, count
, &next
);
144 m
->VMI_COUNT
= count
;
147 addr
= (vir_bytes
) vri
;
148 size
= sizeof(vri
[0]) * count
;
159 /* Make sure that no page faults can occur while copying out. A page
160 * fault would cause the kernel to send a notify to us, while we would
161 * be waiting for the result of the copy system call, resulting in a
162 * deadlock. Note that no memory mapping can be undone without the
163 * involvement of VM, so we are safe until we're done.
165 r
= handle_memory(vmp
, ptr
, size
, 1 /*wrflag*/);
166 if (r
!= OK
) return r
;
168 /* Now that we know the copy out will succeed, perform the actual copy
171 return sys_datacopy(SELF
, addr
,
172 (vir_bytes
) vmp
->vm_endpoint
, ptr
, size
);
175 /*===========================================================================*
177 *===========================================================================*/
178 int swap_proc_slot(struct vmproc
*src_vmp
, struct vmproc
*dst_vmp
)
180 struct vmproc orig_src_vmproc
, orig_dst_vmproc
;
183 printf("VM: swap_proc: swapping %d (%d) and %d (%d)\n",
184 src_vmp
->vm_endpoint
, src_vmp
->vm_slot
,
185 dst_vmp
->vm_endpoint
, dst_vmp
->vm_slot
);
188 /* Save existing data. */
189 orig_src_vmproc
= *src_vmp
;
190 orig_dst_vmproc
= *dst_vmp
;
193 *src_vmp
= orig_dst_vmproc
;
194 *dst_vmp
= orig_src_vmproc
;
196 /* Preserve endpoints and slot numbers. */
197 src_vmp
->vm_endpoint
= orig_src_vmproc
.vm_endpoint
;
198 src_vmp
->vm_slot
= orig_src_vmproc
.vm_slot
;
199 dst_vmp
->vm_endpoint
= orig_dst_vmproc
.vm_endpoint
;
200 dst_vmp
->vm_slot
= orig_dst_vmproc
.vm_slot
;
203 printf("VM: swap_proc: swapped %d (%d) and %d (%d)\n",
204 src_vmp
->vm_endpoint
, src_vmp
->vm_slot
,
205 dst_vmp
->vm_endpoint
, dst_vmp
->vm_slot
);
211 /*===========================================================================*
212 * swap_proc_dyn_data *
213 *===========================================================================*/
214 int swap_proc_dyn_data(struct vmproc
*src_vmp
, struct vmproc
*dst_vmp
)
219 is_vm
= (dst_vmp
->vm_endpoint
== VM_PROC_NR
);
221 /* For VM, transfer memory regions above the stack first. */
224 printf("VM: swap_proc_dyn_data: tranferring regions above the stack from old VM (%d) to new VM (%d)\n",
225 src_vmp
->vm_endpoint
, dst_vmp
->vm_endpoint
);
227 r
= pt_map_in_range(src_vmp
, dst_vmp
, VM_STACKTOP
, 0);
229 printf("swap_proc_dyn_data: pt_map_in_range failed\n");
235 printf("VM: swap_proc_dyn_data: swapping regions' parents for %d (%d) and %d (%d)\n",
236 src_vmp
->vm_endpoint
, src_vmp
->vm_slot
,
237 dst_vmp
->vm_endpoint
, dst_vmp
->vm_slot
);
240 /* Swap vir_regions' parents. */
241 map_setparent(src_vmp
);
242 map_setparent(dst_vmp
);
244 /* For regular processes, transfer regions above the stack now.
245 * In case of rollback, we need to skip this step. To sandbox the
246 * new instance and prevent state corruption on rollback, we share all
247 * the regions between the two instances as COW.
250 struct vir_region
*vr
;
251 vr
= map_lookup(dst_vmp
, VM_STACKTOP
, NULL
);
252 if(vr
&& !map_lookup(src_vmp
, VM_STACKTOP
, NULL
)) {
254 printf("VM: swap_proc_dyn_data: tranferring regions above the stack from %d to %d\n",
255 src_vmp
->vm_endpoint
, dst_vmp
->vm_endpoint
);
257 r
= map_proc_copy_from(src_vmp
, dst_vmp
, vr
);