2 /* This file contains some utility routines for VM. */
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>
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>
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 #define SWAP_PROC_DEBUG 0
42 /*===========================================================================*
44 *===========================================================================*/
45 PUBLIC
int get_mem_map(proc_nr
, mem_map
)
46 int proc_nr
; /* process to get map of */
47 struct mem_map
*mem_map
; /* put memory map here */
52 if ((s
=sys_getproc(&p
, proc_nr
)) != OK
)
55 memcpy(mem_map
, p
.p_memmap
, sizeof(p
.p_memmap
));
59 /*===========================================================================*
61 *===========================================================================*/
62 PUBLIC
void get_mem_chunks(mem_chunks
)
63 struct memory
*mem_chunks
; /* store mem chunks here */
65 /* Initialize the free memory list from the 'memory' boot variable. Translate
66 * the byte offsets and sizes in this list to clicks, properly truncated.
68 phys_bytes base
, size
, limit
;
72 /* Obtain and parse memory from system environment. */
73 if(env_memory_parse(mem_chunks
, NR_MEMS
) != OK
)
74 panic("couldn't obtain memory chunks");
76 /* Round physical memory to clicks. Round start up, round end down. */
77 for (i
= 0; i
< NR_MEMS
; i
++) {
78 memp
= &mem_chunks
[i
]; /* next mem chunk is stored here */
79 base
= mem_chunks
[i
].base
;
80 size
= mem_chunks
[i
].size
;
82 base
= (phys_bytes
) (CLICK_CEIL(base
));
83 limit
= (phys_bytes
) (CLICK_FLOOR(limit
));
85 memp
->base
= memp
->size
= 0;
87 memp
->base
= base
>> CLICK_SHIFT
;
88 memp
->size
= (limit
- base
) >> CLICK_SHIFT
;
93 /*===========================================================================*
95 *===========================================================================*/
96 PUBLIC
void reserve_proc_mem(mem_chunks
, map_ptr
)
97 struct memory
*mem_chunks
; /* store mem chunks here */
98 struct mem_map
*map_ptr
; /* memory to remove */
100 /* Remove server memory from the free memory list. The boot monitor
101 * promises to put processes at the start of memory chunks. The
102 * tasks all use same base address, so only the first task changes
103 * the memory lists. The servers and init have their own memory
104 * spaces and their memory will be removed from the list.
107 for (memp
= mem_chunks
; memp
< &mem_chunks
[NR_MEMS
]; memp
++) {
108 if (memp
->base
== map_ptr
[T
].mem_phys
) {
109 memp
->base
+= map_ptr
[T
].mem_len
+ map_ptr
[S
].mem_vir
;
110 memp
->size
-= map_ptr
[T
].mem_len
+ map_ptr
[S
].mem_vir
;
114 if (memp
>= &mem_chunks
[NR_MEMS
])
116 panic("reserve_proc_mem: can't find map in mem_chunks: 0x%lx",
117 map_ptr
[T
].mem_phys
);
121 /*===========================================================================*
123 *===========================================================================*/
124 PUBLIC
int vm_isokendpt(endpoint_t endpoint
, int *proc
)
126 *proc
= _ENDPOINT_P(endpoint
);
127 if(*proc
< 0 || *proc
>= NR_PROCS
)
129 if(*proc
>= 0 && endpoint
!= vmproc
[*proc
].vm_endpoint
)
131 if(*proc
>= 0 && !(vmproc
[*proc
].vm_flags
& VMF_INUSE
))
137 struct proc mytmpproc
;
139 /*===========================================================================*
141 *===========================================================================*/
142 PUBLIC
int get_stack_ptr(proc_nr_e
, sp
)
143 int proc_nr_e
; /* process to get sp of */
144 vir_bytes
*sp
; /* put stack pointer here */
148 if ((s
=sys_getproc(&mytmpproc
, proc_nr_e
)) != OK
)
150 *sp
= mytmpproc
.p_reg
.sp
;
154 /*===========================================================================*
156 *===========================================================================*/
157 extern char *_brksize
;
158 PUBLIC
int brk(brk_addr
)
162 struct vmproc
*vmm
= &vmproc
[VM_PROC_NR
];
164 /* VM wants to call brk() itself. */
165 if((r
=real_brk(vmm
, (vir_bytes
) brk_addr
)) != OK
)
166 panic("VM: brk() on myself failed");
171 /*===========================================================================*
173 *===========================================================================*/
174 PUBLIC
int do_info(message
*m
)
176 struct vm_stats_info vsi
;
177 struct vm_usage_info vui
;
178 static struct vm_region_info vri
[MAX_VRI_COUNT
];
180 vir_bytes addr
, size
, next
, ptr
;
181 int r
, pr
, dummy
, count
;
183 if (vm_isokendpt(m
->m_source
, &pr
) != OK
)
187 ptr
= (vir_bytes
) m
->VMI_PTR
;
189 switch(m
->VMI_WHAT
) {
191 vsi
.vsi_pagesize
= VM_PAGE_SIZE
;
192 vsi
.vsi_total
= total_pages
;
193 memstats(&dummy
, &vsi
.vsi_free
, &vsi
.vsi_largest
);
195 addr
= (vir_bytes
) &vsi
;
201 if (vm_isokendpt(m
->VMI_EP
, &pr
) != OK
)
204 get_usage_info(&vmproc
[pr
], &vui
);
206 addr
= (vir_bytes
) &vui
;
212 if (vm_isokendpt(m
->VMI_EP
, &pr
) != OK
)
215 count
= MIN(m
->VMI_COUNT
, MAX_VRI_COUNT
);
218 count
= get_region_info(&vmproc
[pr
], vri
, count
, &next
);
220 m
->VMI_COUNT
= count
;
223 addr
= (vir_bytes
) vri
;
224 size
= sizeof(vri
[0]) * count
;
235 /* Make sure that no page faults can occur while copying out. A page
236 * fault would cause the kernel to send a notify to us, while we would
237 * be waiting for the result of the copy system call, resulting in a
238 * deadlock. Note that no memory mapping can be undone without the
239 * involvement of VM, so we are safe until we're done.
241 r
= handle_memory(vmp
, arch_vir2map(vmp
, ptr
), size
, 1 /*wrflag*/);
242 if (r
!= OK
) return r
;
244 /* Now that we know the copy out will succeed, perform the actual copy
247 return sys_datacopy(SELF
, addr
,
248 (vir_bytes
) vmp
->vm_endpoint
, ptr
, size
);
251 /*===========================================================================*
253 *===========================================================================*/
254 PUBLIC
int swap_proc(endpoint_t src_e
, endpoint_t dst_e
)
256 struct vmproc
*src_vmp
, *dst_vmp
;
257 struct vmproc orig_src_vmproc
, orig_dst_vmproc
;
259 struct vir_region
*vr
;
261 /* Lookup slots for source and destination process. */
262 if(vm_isokendpt(src_e
, &src_p
) != OK
) {
263 printf("swap_proc: bad src endpoint %d\n", src_e
);
266 src_vmp
= &vmproc
[src_p
];
267 if(vm_isokendpt(dst_e
, &dst_p
) != OK
) {
268 printf("swap_proc: bad dst endpoint %d\n", dst_e
);
271 dst_vmp
= &vmproc
[dst_p
];
274 printf("swap_proc: swapping %d (%d, %d) and %d (%d, %d)\n",
275 src_vmp
->vm_endpoint
, src_p
, src_vmp
->vm_slot
,
276 dst_vmp
->vm_endpoint
, dst_p
, dst_vmp
->vm_slot
);
278 printf("swap_proc: map_printmap for source before swapping:\n");
279 map_printmap(src_vmp
);
280 printf("swap_proc: map_printmap for destination before swapping:\n");
281 map_printmap(dst_vmp
);
284 /* Save existing data. */
285 orig_src_vmproc
= *src_vmp
;
286 orig_dst_vmproc
= *dst_vmp
;
289 *src_vmp
= orig_dst_vmproc
;
290 *dst_vmp
= orig_src_vmproc
;
292 /* Preserve endpoints and slot numbers. */
293 src_vmp
->vm_endpoint
= orig_src_vmproc
.vm_endpoint
;
294 src_vmp
->vm_slot
= orig_src_vmproc
.vm_slot
;
295 dst_vmp
->vm_endpoint
= orig_dst_vmproc
.vm_endpoint
;
296 dst_vmp
->vm_slot
= orig_dst_vmproc
.vm_slot
;
298 /* Preserve vir_region's parents. */
299 for(vr
= src_vmp
->vm_regions
; vr
; vr
= vr
->next
) {
300 vr
->parent
= src_vmp
;
302 for(vr
= dst_vmp
->vm_regions
; vr
; vr
= vr
->next
) {
303 vr
->parent
= dst_vmp
;
306 /* Adjust page tables. */
307 assert(src_vmp
->vm_flags
& VMF_HASPT
);
308 assert(dst_vmp
->vm_flags
& VMF_HASPT
);
309 pt_bind(&src_vmp
->vm_pt
, src_vmp
);
310 pt_bind(&dst_vmp
->vm_pt
, dst_vmp
);
311 if((r
=sys_vmctl(SELF
, VMCTL_FLUSHTLB
, 0)) != OK
) {
312 panic("swap_proc: VMCTL_FLUSHTLB failed: %d", r
);
316 printf("swap_proc: swapped %d (%d, %d) and %d (%d, %d)\n",
317 src_vmp
->vm_endpoint
, src_p
, src_vmp
->vm_slot
,
318 dst_vmp
->vm_endpoint
, dst_p
, dst_vmp
->vm_slot
);
320 printf("swap_proc: map_printmap for source after swapping:\n");
321 map_printmap(src_vmp
);
322 printf("swap_proc: map_printmap for destination after swapping:\n");
323 map_printmap(dst_vmp
);