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>
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 /*===========================================================================*
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 */
48 if ((s
=sys_getproc(&p
, proc_nr
)) != OK
)
51 memcpy(mem_map
, p
.p_memmap
, sizeof(p
.p_memmap
));
55 /*===========================================================================*
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
;
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
;
78 base
= (phys_bytes
) (CLICK_CEIL(base
));
79 limit
= (phys_bytes
) (CLICK_FLOOR(limit
));
81 memp
->base
= memp
->size
= 0;
83 memp
->base
= base
>> CLICK_SHIFT
;
84 memp
->size
= (limit
- base
) >> CLICK_SHIFT
;
89 /*===========================================================================*
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.
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
;
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 /*===========================================================================*
119 *===========================================================================*/
120 PUBLIC
int vm_isokendpt(endpoint_t endpoint
, int *proc
)
122 *proc
= _ENDPOINT_P(endpoint
);
123 if(*proc
< 0 || *proc
>= NR_PROCS
)
125 if(*proc
>= 0 && endpoint
!= vmproc
[*proc
].vm_endpoint
)
127 if(*proc
>= 0 && !(vmproc
[*proc
].vm_flags
& VMF_INUSE
))
133 struct proc mytmpproc
;
135 /*===========================================================================*
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 */
144 if ((s
=sys_getproc(&mytmpproc
, proc_nr_e
)) != OK
)
146 *sp
= mytmpproc
.p_reg
.sp
;
150 /*===========================================================================*
152 *===========================================================================*/
153 extern char *_brksize
;
154 PUBLIC
int brk(brk_addr
)
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");
167 /*===========================================================================*
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
];
176 vir_bytes addr
, size
, next
, ptr
;
177 int r
, pr
, dummy
, count
;
179 if (vm_isokendpt(m
->m_source
, &pr
) != OK
)
183 ptr
= (vir_bytes
) m
->VMI_PTR
;
185 switch(m
->VMI_WHAT
) {
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
;
197 if (vm_isokendpt(m
->VMI_EP
, &pr
) != OK
)
200 get_usage_info(&vmproc
[pr
], &vui
);
202 addr
= (vir_bytes
) &vui
;
208 if (vm_isokendpt(m
->VMI_EP
, &pr
) != OK
)
211 count
= MIN(m
->VMI_COUNT
, MAX_VRI_COUNT
);
214 count
= get_region_info(&vmproc
[pr
], vri
, count
, &next
);
216 m
->VMI_COUNT
= count
;
219 addr
= (vir_bytes
) vri
;
220 size
= sizeof(vri
[0]) * count
;
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
243 return sys_datacopy(SELF
, addr
,
244 (vir_bytes
) vmp
->vm_endpoint
, ptr
, size
);