6 #include <minix/callnr.h>
8 #include <minix/config.h>
9 #include <minix/const.h>
11 #include <minix/endpoint.h>
12 #include <minix/keymap.h>
13 #include <minix/minlib.h>
14 #include <minix/type.h>
15 #include <minix/ipc.h>
16 #include <minix/sysutil.h>
17 #include <minix/syslib.h>
18 #include <minix/safecopies.h>
19 #include <minix/bitmap.h>
35 /*===========================================================================*
37 *===========================================================================*/
38 PUBLIC
int do_mmap(message
*m
)
43 struct vir_region
*vr
= NULL
;
45 if((r
=vm_isokendpt(m
->m_source
, &n
)) != OK
) {
46 vm_panic("do_mmap: message from strange source", m
->m_source
);
51 if(!(vmp
->vm_flags
& VMF_HASPT
))
54 if(m
->VMM_FD
== -1 || (m
->VMM_FLAGS
& MAP_ANON
)) {
57 u32_t vrflags
= VR_ANON
| VR_WRITABLE
;
58 size_t len
= (vir_bytes
) m
->VMM_LEN
;
64 if(m
->VMM_FLAGS
& MAP_CONTIG
) mfflags
|= MF_CONTIG
;
65 if(m
->VMM_FLAGS
& MAP_PREALLOC
) mfflags
|= MF_PREALLOC
;
66 if(m
->VMM_FLAGS
& MAP_LOWER16M
) vrflags
|= VR_LOWER16MB
;
67 if(m
->VMM_FLAGS
& MAP_LOWER1M
) vrflags
|= VR_LOWER1MB
;
68 if(m
->VMM_FLAGS
& MAP_ALIGN64K
) vrflags
|= VR_PHYS64K
;
69 if(m
->VMM_FLAGS
& MAP_SHARED
) vrflags
|= VR_SHARED
;
71 if(len
% VM_PAGE_SIZE
)
72 len
+= VM_PAGE_SIZE
- (len
% VM_PAGE_SIZE
);
74 if(!(vr
= map_page_region(vmp
,
76 m
->VMM_ADDR
? m
->VMM_ADDR
: vmp
->vm_stacktop
),
77 VM_DATATOP
, len
, MAP_NONE
, vrflags
, mfflags
))) {
84 /* Return mapping, as seen from process. */
86 m
->VMM_RETADDR
= arch_map2vir(vmp
, vr
->vaddr
);
92 /*===========================================================================*
94 *===========================================================================*/
95 PUBLIC
int map_perm_check(endpoint_t caller
, endpoint_t target
,
96 phys_bytes physaddr
, phys_bytes len
)
100 /* TTY and memory are allowed to do anything.
101 * They have to be special cases as they have to be able to do
102 * anything; TTY even on behalf of anyone for the TIOCMAPMEM
103 * ioctl. MEM just for itself.
105 if(caller
== TTY_PROC_NR
)
109 if(caller
== MEM_PROC_NR
)
112 /* Anyone else needs explicit permission from the kernel (ultimately
115 r
= sys_privquery_mem(caller
, physaddr
, len
);
120 /*===========================================================================*
122 *===========================================================================*/
123 PUBLIC
int do_map_phys(message
*m
)
128 struct vir_region
*vr
;
130 phys_bytes startaddr
;
136 target
= m
->m_source
;
138 if((r
=vm_isokendpt(target
, &n
)) != OK
)
141 startaddr
= (vir_bytes
)m
->VMMP_PHADDR
;
143 /* First check permission, then round range down/up. Caller can't
144 * help it if we can't map in lower than page granularity.
146 if(map_perm_check(m
->m_source
, target
, startaddr
, len
) != OK
) {
147 printf("VM: unauthorized mapping of 0x%lx by %d\n",
148 startaddr
, m
->m_source
);
154 if(!(vmp
->vm_flags
& VMF_HASPT
))
157 if(len
% VM_PAGE_SIZE
)
158 len
+= VM_PAGE_SIZE
- (len
% VM_PAGE_SIZE
);
160 if(!(vr
= map_page_region(vmp
, arch_vir2map(vmp
, vmp
->vm_stacktop
),
161 VM_DATATOP
, len
, startaddr
,
162 VR_DIRECT
| VR_NOPF
| VR_WRITABLE
, 0))) {
166 m
->VMMP_VADDR_REPLY
= (void *) arch_map2vir(vmp
, vr
->vaddr
);
171 /*===========================================================================*
173 *===========================================================================*/
174 PUBLIC
int do_unmap_phys(message
*m
)
179 struct vir_region
*region
;
183 target
= m
->m_source
;
185 if((r
=vm_isokendpt(target
, &n
)) != OK
)
190 if(!(region
= map_lookup(vmp
,
191 arch_vir2map(vmp
, (vir_bytes
) m
->VMUM_ADDR
)))) {
195 if(!(region
->flags
& VR_DIRECT
)) {
199 if(map_unmap_region(vmp
, region
, region
->length
) != OK
) {
206 /*===========================================================================*
208 *===========================================================================*/
209 PUBLIC
int do_remap(message
*m
)
212 vir_bytes da
, sa
, startv
;
214 struct vir_region
*vr
, *region
;
215 struct vmproc
*dvmp
, *svmp
;
220 da
= (vir_bytes
) m
->VMRE_DA
;
221 sa
= (vir_bytes
) m
->VMRE_SA
;
224 if ((r
= vm_isokendpt(d
, &dn
)) != OK
)
226 if ((r
= vm_isokendpt(s
, &sn
)) != OK
)
232 /* da is not translated by arch_vir2map(),
233 * it's handled a little differently,
234 * since in map_remap(), we have to know
235 * about whether the user needs to bind to
236 * THAT address or be chosen by the system.
238 sa
= arch_vir2map(svmp
, sa
);
240 if (!(region
= map_lookup(svmp
, sa
)))
243 if ((r
= map_remap(dvmp
, da
, size
, region
, &startv
)) != OK
)
246 m
->VMRE_RETA
= (char *) arch_map2vir(dvmp
, startv
);
250 /*===========================================================================*
252 *===========================================================================*/
253 PUBLIC
int do_shared_unmap(message
*m
)
258 struct vir_region
*vr
;
261 target
= m
->VMUN_ENDPT
;
263 if ((r
= vm_isokendpt(target
, &n
)) != OK
)
268 addr
= arch_vir2map(vmp
, m
->VMUN_ADDR
);
270 if(!(vr
= map_lookup(vmp
, addr
))) {
271 printf("VM: addr 0x%lx not found.\n", m
->VMUN_ADDR
);
275 if(vr
->vaddr
!= addr
) {
276 printf("VM: wrong address for shared_unmap.\n");
280 if(!(vr
->flags
& VR_SHARED
)) {
281 printf("VM: address does not point to shared region.\n");
285 if(map_unmap_region(vmp
, vr
, vr
->length
) != OK
)
286 vm_panic("do_shared_unmap: map_unmap_region failed", NO_NUM
);
291 /*===========================================================================*
293 *===========================================================================*/
294 PUBLIC
int do_get_phys(message
*m
)
302 target
= m
->VMPHYS_ENDPT
;
303 addr
= m
->VMPHYS_ADDR
;
305 if ((r
= vm_isokendpt(target
, &n
)) != OK
)
309 addr
= arch_vir2map(vmp
, addr
);
311 r
= map_get_phys(vmp
, addr
, &ret
);
313 m
->VMPHYS_RETA
= ret
;
317 /*===========================================================================*
319 *===========================================================================*/
320 PUBLIC
int do_get_refcount(message
*m
)
328 target
= m
->VMREFCNT_ENDPT
;
329 addr
= m
->VMREFCNT_ADDR
;
331 if ((r
= vm_isokendpt(target
, &n
)) != OK
)
335 addr
= arch_vir2map(vmp
, addr
);
337 r
= map_get_ref(vmp
, addr
, &cnt
);
339 m
->VMREFCNT_RETC
= cnt
;
343 /*===========================================================================*
345 *===========================================================================*/
346 PUBLIC
int do_munmap(message
*m
)
351 struct vir_region
*vr
;
353 if((r
=vm_isokendpt(m
->m_source
, &n
)) != OK
) {
354 vm_panic("do_mmap: message from strange source", m
->m_source
);
359 if(!(vmp
->vm_flags
& VMF_HASPT
))
362 if(m
->m_type
== VM_MUNMAP
) {
363 addr
= (vir_bytes
) arch_vir2map(vmp
, (vir_bytes
) m
->VMUM_ADDR
);
364 } else if(m
->m_type
== VM_MUNMAP_TEXT
) {
365 addr
= (vir_bytes
) arch_vir2map_text(vmp
, (vir_bytes
) m
->VMUM_ADDR
);
367 vm_panic("do_munmap: strange type", NO_NUM
);
370 if(!(vr
= map_lookup(vmp
, addr
))) {
371 printf("VM: unmap: virtual address 0x%lx not found in %d\n",
372 m
->VMUM_ADDR
, vmp
->vm_endpoint
);
377 len
-= len
% VM_PAGE_SIZE
;
379 if(addr
!= vr
->vaddr
|| len
> vr
->length
|| len
< VM_PAGE_SIZE
) {
383 if(map_unmap_region(vmp
, vr
, len
) != OK
)
384 vm_panic("do_munmap: map_unmap_region failed", NO_NUM
);
391 /*===========================================================================*
392 * munmap_lin (used for overrides for VM) *
393 *===========================================================================*/
394 PRIVATE
int munmap_lin(vir_bytes addr
, size_t len
)
396 if(addr
% VM_PAGE_SIZE
) {
397 printf("munmap_lin: offset not page aligned\n");
401 if(len
% VM_PAGE_SIZE
) {
402 printf("munmap_lin: len not page aligned\n");
406 if(pt_writemap(&vmproc
[VM_PROC_NR
].vm_pt
, addr
, MAP_NONE
, len
, 0,
407 WMF_OVERWRITE
| WMF_FREE
) != OK
) {
408 printf("munmap_lin: pt_writemap failed\n");
415 /*===========================================================================*
416 * munmap (override for VM) *
417 *===========================================================================*/
418 PUBLIC
int munmap(void *addr
, size_t len
)
423 laddr
= (vir_bytes
) arch_vir2map(&vmproc
[VM_PROC_NR
], (vir_bytes
) addr
);
424 return munmap_lin(laddr
, len
);
427 /*===========================================================================*
428 * munmap_text (override for VM) *
429 *===========================================================================*/
430 PUBLIC
int munmap_text(void *addr
, size_t len
)
435 laddr
= (vir_bytes
) arch_vir2map_text(&vmproc
[VM_PROC_NR
],
437 return munmap_lin(laddr
, len
);