VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c@ 57276

Last change on this file since 57276 was 55095, checked in by vboxsync, 10 years ago

Assorted fixes for FreeBSD hosts, VBox compiles and runs again without further patches (tested on 10.1 amd64 )

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.0 KB
Line 
1/* $Id: memobj-r0drv-freebsd.c 55095 2015-04-02 16:52:46Z vboxsync $ */
2/** @file
3 * IPRT - Ring-0 Memory Objects, FreeBSD.
4 */
5
6/*
7 * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
8 * Copyright (c) 2011 Andriy Gapon <avg@FreeBSD.org>
9 *
10 * Permission is hereby granted, free of charge, to any person
11 * obtaining a copy of this software and associated documentation
12 * files (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use,
14 * copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following
17 * conditions:
18 *
19 * The above copyright notice and this permission notice shall be
20 * included in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
24 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 * OTHER DEALINGS IN THE SOFTWARE.
30 */
31
32
33/*******************************************************************************
34* Header Files *
35*******************************************************************************/
36#include "the-freebsd-kernel.h"
37
38#include <iprt/memobj.h>
39#include <iprt/mem.h>
40#include <iprt/err.h>
41#include <iprt/assert.h>
42#include <iprt/log.h>
43#include <iprt/param.h>
44#include <iprt/process.h>
45#include "internal/memobj.h"
46
47
48/*******************************************************************************
49* Structures and Typedefs *
50*******************************************************************************/
51/**
52 * The FreeBSD version of the memory object structure.
53 */
54typedef struct RTR0MEMOBJFREEBSD
55{
56 /** The core structure. */
57 RTR0MEMOBJINTERNAL Core;
58 /** The VM object associated with the allocation. */
59 vm_object_t pObject;
60} RTR0MEMOBJFREEBSD, *PRTR0MEMOBJFREEBSD;
61
62
63MALLOC_DEFINE(M_IPRTMOBJ, "iprtmobj", "IPRT - R0MemObj");
64
65
66/**
67 * Gets the virtual memory map the specified object is mapped into.
68 *
69 * @returns VM map handle on success, NULL if no map.
70 * @param pMem The memory object.
71 */
72static vm_map_t rtR0MemObjFreeBSDGetMap(PRTR0MEMOBJINTERNAL pMem)
73{
74 switch (pMem->enmType)
75 {
76 case RTR0MEMOBJTYPE_PAGE:
77 case RTR0MEMOBJTYPE_LOW:
78 case RTR0MEMOBJTYPE_CONT:
79 return kernel_map;
80
81 case RTR0MEMOBJTYPE_PHYS:
82 case RTR0MEMOBJTYPE_PHYS_NC:
83 return NULL; /* pretend these have no mapping atm. */
84
85 case RTR0MEMOBJTYPE_LOCK:
86 return pMem->u.Lock.R0Process == NIL_RTR0PROCESS
87 ? kernel_map
88 : &((struct proc *)pMem->u.Lock.R0Process)->p_vmspace->vm_map;
89
90 case RTR0MEMOBJTYPE_RES_VIRT:
91 return pMem->u.ResVirt.R0Process == NIL_RTR0PROCESS
92 ? kernel_map
93 : &((struct proc *)pMem->u.ResVirt.R0Process)->p_vmspace->vm_map;
94
95 case RTR0MEMOBJTYPE_MAPPING:
96 return pMem->u.Mapping.R0Process == NIL_RTR0PROCESS
97 ? kernel_map
98 : &((struct proc *)pMem->u.Mapping.R0Process)->p_vmspace->vm_map;
99
100 default:
101 return NULL;
102 }
103}
104
105
106DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
107{
108 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)pMem;
109 int rc;
110
111 switch (pMemFreeBSD->Core.enmType)
112 {
113 case RTR0MEMOBJTYPE_PAGE:
114 case RTR0MEMOBJTYPE_LOW:
115 case RTR0MEMOBJTYPE_CONT:
116 rc = vm_map_remove(kernel_map,
117 (vm_offset_t)pMemFreeBSD->Core.pv,
118 (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeBSD->Core.cb);
119 AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
120 break;
121
122 case RTR0MEMOBJTYPE_LOCK:
123 {
124 vm_map_t pMap = kernel_map;
125
126 if (pMemFreeBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
127 pMap = &((struct proc *)pMemFreeBSD->Core.u.Lock.R0Process)->p_vmspace->vm_map;
128
129 rc = vm_map_unwire(pMap,
130 (vm_offset_t)pMemFreeBSD->Core.pv,
131 (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeBSD->Core.cb,
132 VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);
133 AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
134 break;
135 }
136
137 case RTR0MEMOBJTYPE_RES_VIRT:
138 {
139 vm_map_t pMap = kernel_map;
140 if (pMemFreeBSD->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
141 pMap = &((struct proc *)pMemFreeBSD->Core.u.ResVirt.R0Process)->p_vmspace->vm_map;
142 rc = vm_map_remove(pMap,
143 (vm_offset_t)pMemFreeBSD->Core.pv,
144 (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeBSD->Core.cb);
145 AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
146 break;
147 }
148
149 case RTR0MEMOBJTYPE_MAPPING:
150 {
151 vm_map_t pMap = kernel_map;
152
153 if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
154 pMap = &((struct proc *)pMemFreeBSD->Core.u.Mapping.R0Process)->p_vmspace->vm_map;
155 rc = vm_map_remove(pMap,
156 (vm_offset_t)pMemFreeBSD->Core.pv,
157 (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeBSD->Core.cb);
158 AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
159 break;
160 }
161
162 case RTR0MEMOBJTYPE_PHYS:
163 case RTR0MEMOBJTYPE_PHYS_NC:
164 {
165#if __FreeBSD_version >= 1000030
166 VM_OBJECT_WLOCK(pMemFreeBSD->pObject);
167#else
168 VM_OBJECT_LOCK(pMemFreeBSD->pObject);
169#endif
170 vm_page_t pPage = vm_page_find_least(pMemFreeBSD->pObject, 0);
171#if __FreeBSD_version < 1000000
172 vm_page_lock_queues();
173#endif
174 for (vm_page_t pPage = vm_page_find_least(pMemFreeBSD->pObject, 0);
175 pPage != NULL;
176 pPage = vm_page_next(pPage))
177 {
178 vm_page_unwire(pPage, 0);
179 }
180#if __FreeBSD_version < 1000000
181 vm_page_unlock_queues();
182#endif
183#if __FreeBSD_version >= 1000030
184 VM_OBJECT_WUNLOCK(pMemFreeBSD->pObject);
185#else
186 VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
187#endif
188 vm_object_deallocate(pMemFreeBSD->pObject);
189 break;
190 }
191
192 default:
193 AssertMsgFailed(("enmType=%d\n", pMemFreeBSD->Core.enmType));
194 return VERR_INTERNAL_ERROR;
195 }
196
197 return VINF_SUCCESS;
198}
199
200
201static vm_page_t rtR0MemObjFreeBSDContigPhysAllocHelper(vm_object_t pObject, vm_pindex_t iPIndex,
202 u_long cPages, vm_paddr_t VmPhysAddrHigh,
203 u_long uAlignment, bool fWire)
204{
205 vm_page_t pPages;
206 int cTries = 0;
207
208#if __FreeBSD_version > 1000000
209 int fFlags = VM_ALLOC_INTERRUPT | VM_ALLOC_NOBUSY;
210 if (fWire)
211 fFlags |= VM_ALLOC_WIRED;
212
213 while (cTries <= 1)
214 {
215#if __FreeBSD_version >= 1000030
216 VM_OBJECT_WLOCK(pObject);
217#else
218 VM_OBJECT_LOCK(pObject);
219#endif
220 pPages = vm_page_alloc_contig(pObject, iPIndex, fFlags, cPages, 0,
221 VmPhysAddrHigh, uAlignment, 0, VM_MEMATTR_DEFAULT);
222#if __FreeBSD_version >= 1000030
223 VM_OBJECT_WUNLOCK(pObject);
224#else
225 VM_OBJECT_UNLOCK(pObject);
226#endif
227 if (pPages)
228 break;
229 vm_pageout_grow_cache(cTries, 0, VmPhysAddrHigh);
230 cTries++;
231 }
232
233 return pPages;
234#else
235 while (cTries <= 1)
236 {
237 pPages = vm_phys_alloc_contig(cPages, 0, VmPhysAddrHigh, uAlignment, 0);
238 if (pPages)
239 break;
240 vm_contig_grow_cache(cTries, 0, VmPhysAddrHigh);
241 cTries++;
242 }
243
244 if (!pPages)
245 return pPages;
246#if __FreeBSD_version >= 1000030
247 VM_OBJECT_WLOCK(pObject);
248#else
249 VM_OBJECT_LOCK(pObject);
250#endif
251 for (vm_pindex_t iPage = 0; iPage < cPages; iPage++)
252 {
253 vm_page_t pPage = pPages + iPage;
254 vm_page_insert(pPage, pObject, iPIndex + iPage);
255 pPage->valid = VM_PAGE_BITS_ALL;
256 if (fWire)
257 {
258 pPage->wire_count = 1;
259 atomic_add_int(&cnt.v_wire_count, 1);
260 }
261 }
262#if __FreeBSD_version >= 1000030
263 VM_OBJECT_WUNLOCK(pObject);
264#else
265 VM_OBJECT_UNLOCK(pObject);
266#endif
267 return pPages;
268#endif
269}
270
271static int rtR0MemObjFreeBSDPhysAllocHelper(vm_object_t pObject, u_long cPages,
272 vm_paddr_t VmPhysAddrHigh, u_long uAlignment,
273 bool fContiguous, bool fWire, int rcNoMem)
274{
275 if (fContiguous)
276 {
277 if (rtR0MemObjFreeBSDContigPhysAllocHelper(pObject, 0, cPages, VmPhysAddrHigh,
278 uAlignment, fWire) != NULL)
279 return VINF_SUCCESS;
280 return rcNoMem;
281 }
282
283 for (vm_pindex_t iPage = 0; iPage < cPages; iPage++)
284 {
285 vm_page_t pPage = rtR0MemObjFreeBSDContigPhysAllocHelper(pObject, iPage, 1, VmPhysAddrHigh,
286 uAlignment, fWire);
287 if (!pPage)
288 {
289 /* Free all allocated pages */
290#if __FreeBSD_version >= 1000030
291 VM_OBJECT_WLOCK(pObject);
292#else
293 VM_OBJECT_LOCK(pObject);
294#endif
295 while (iPage-- > 0)
296 {
297 pPage = vm_page_lookup(pObject, iPage);
298#if __FreeBSD_version < 1000000
299 vm_page_lock_queues();
300#endif
301 if (fWire)
302 vm_page_unwire(pPage, 0);
303 vm_page_free(pPage);
304#if __FreeBSD_version < 1000000
305 vm_page_unlock_queues();
306#endif
307 }
308#if __FreeBSD_version >= 1000030
309 VM_OBJECT_WUNLOCK(pObject);
310#else
311 VM_OBJECT_UNLOCK(pObject);
312#endif
313 return rcNoMem;
314 }
315 }
316 return VINF_SUCCESS;
317}
318
319static int rtR0MemObjFreeBSDAllocHelper(PRTR0MEMOBJFREEBSD pMemFreeBSD, bool fExecutable,
320 vm_paddr_t VmPhysAddrHigh, bool fContiguous, int rcNoMem)
321{
322 vm_offset_t MapAddress = vm_map_min(kernel_map);
323 size_t cPages = atop(pMemFreeBSD->Core.cb);
324 int rc;
325
326 pMemFreeBSD->pObject = vm_object_allocate(OBJT_PHYS, cPages);
327
328 /* No additional object reference for auto-deallocation upon unmapping. */
329#if __FreeBSD_version >= 1000055
330 rc = vm_map_find(kernel_map, pMemFreeBSD->pObject, 0,
331 &MapAddress, pMemFreeBSD->Core.cb, 0, VMFS_ANY_SPACE,
332 fExecutable ? VM_PROT_ALL : VM_PROT_RW, VM_PROT_ALL, 0);
333#else
334 rc = vm_map_find(kernel_map, pMemFreeBSD->pObject, 0,
335 &MapAddress, pMemFreeBSD->Core.cb, VMFS_ANY_SPACE,
336 fExecutable ? VM_PROT_ALL : VM_PROT_RW, VM_PROT_ALL, 0);
337#endif
338
339 if (rc == KERN_SUCCESS)
340 {
341 rc = rtR0MemObjFreeBSDPhysAllocHelper(pMemFreeBSD->pObject, cPages,
342 VmPhysAddrHigh, PAGE_SIZE, fContiguous,
343 false, rcNoMem);
344 if (RT_SUCCESS(rc))
345 {
346 vm_map_wire(kernel_map, MapAddress, MapAddress + pMemFreeBSD->Core.cb,
347 VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);
348
349 /* Store start address */
350 pMemFreeBSD->Core.pv = (void *)MapAddress;
351 return VINF_SUCCESS;
352 }
353
354 vm_map_remove(kernel_map, MapAddress, MapAddress + pMemFreeBSD->Core.cb);
355 }
356 else
357 {
358 rc = rcNoMem; /** @todo fix translation (borrow from darwin) */
359 vm_object_deallocate(pMemFreeBSD->pObject);
360 }
361
362 rtR0MemObjDelete(&pMemFreeBSD->Core);
363 return rc;
364}
365DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
366{
367 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
368 RTR0MEMOBJTYPE_PAGE, NULL, cb);
369 if (!pMemFreeBSD)
370 return VERR_NO_MEMORY;
371
372 int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, ~(vm_paddr_t)0, false, VERR_NO_MEMORY);
373 if (RT_FAILURE(rc))
374 {
375 rtR0MemObjDelete(&pMemFreeBSD->Core);
376 return rc;
377 }
378
379 *ppMem = &pMemFreeBSD->Core;
380 return rc;
381}
382
383
384DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
385{
386 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
387 RTR0MEMOBJTYPE_LOW, NULL, cb);
388 if (!pMemFreeBSD)
389 return VERR_NO_MEMORY;
390
391 int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G - 1, false, VERR_NO_LOW_MEMORY);
392 if (RT_FAILURE(rc))
393 {
394 rtR0MemObjDelete(&pMemFreeBSD->Core);
395 return rc;
396 }
397
398 *ppMem = &pMemFreeBSD->Core;
399 return rc;
400}
401
402
403DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
404{
405 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
406 RTR0MEMOBJTYPE_CONT, NULL, cb);
407 if (!pMemFreeBSD)
408 return VERR_NO_MEMORY;
409
410 int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G - 1, true, VERR_NO_CONT_MEMORY);
411 if (RT_FAILURE(rc))
412 {
413 rtR0MemObjDelete(&pMemFreeBSD->Core);
414 return rc;
415 }
416
417 pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
418 *ppMem = &pMemFreeBSD->Core;
419 return rc;
420}
421
422
423static int rtR0MemObjFreeBSDAllocPhysPages(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJTYPE enmType,
424 size_t cb,
425 RTHCPHYS PhysHighest, size_t uAlignment,
426 bool fContiguous, int rcNoMem)
427{
428 uint32_t cPages = atop(cb);
429 vm_paddr_t VmPhysAddrHigh;
430
431 /* create the object. */
432 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
433 enmType, NULL, cb);
434 if (!pMemFreeBSD)
435 return VERR_NO_MEMORY;
436
437 pMemFreeBSD->pObject = vm_object_allocate(OBJT_PHYS, atop(cb));
438
439 if (PhysHighest != NIL_RTHCPHYS)
440 VmPhysAddrHigh = PhysHighest;
441 else
442 VmPhysAddrHigh = ~(vm_paddr_t)0;
443
444 int rc = rtR0MemObjFreeBSDPhysAllocHelper(pMemFreeBSD->pObject, cPages, VmPhysAddrHigh,
445 uAlignment, fContiguous, true, rcNoMem);
446 if (RT_SUCCESS(rc))
447 {
448 if (fContiguous)
449 {
450 Assert(enmType == RTR0MEMOBJTYPE_PHYS);
451#if __FreeBSD_version >= 1000030
452 VM_OBJECT_WLOCK(pMemFreeBSD->pObject);
453#else
454 VM_OBJECT_LOCK(pMemFreeBSD->pObject);
455#endif
456 pMemFreeBSD->Core.u.Phys.PhysBase = VM_PAGE_TO_PHYS(vm_page_find_least(pMemFreeBSD->pObject, 0));
457#if __FreeBSD_version >= 1000030
458 VM_OBJECT_WUNLOCK(pMemFreeBSD->pObject);
459#else
460 VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
461#endif
462 pMemFreeBSD->Core.u.Phys.fAllocated = true;
463 }
464
465 *ppMem = &pMemFreeBSD->Core;
466 }
467 else
468 {
469 vm_object_deallocate(pMemFreeBSD->pObject);
470 rtR0MemObjDelete(&pMemFreeBSD->Core);
471 }
472
473 return rc;
474}
475
476
477DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
478{
479 return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS, cb, PhysHighest, uAlignment, true, VERR_NO_MEMORY);
480}
481
482
483DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
484{
485 return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS_NC, cb, PhysHighest, PAGE_SIZE, false, VERR_NO_PHYS_MEMORY);
486}
487
488
489DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
490{
491 AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED);
492
493 /* create the object. */
494 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_PHYS, NULL, cb);
495 if (!pMemFreeBSD)
496 return VERR_NO_MEMORY;
497
498 /* there is no allocation here, it needs to be mapped somewhere first. */
499 pMemFreeBSD->Core.u.Phys.fAllocated = false;
500 pMemFreeBSD->Core.u.Phys.PhysBase = Phys;
501 pMemFreeBSD->Core.u.Phys.uCachePolicy = uCachePolicy;
502 *ppMem = &pMemFreeBSD->Core;
503 return VINF_SUCCESS;
504}
505
506
507/**
508 * Worker locking the memory in either kernel or user maps.
509 */
510static int rtR0MemObjNativeLockInMap(PPRTR0MEMOBJINTERNAL ppMem, vm_map_t pVmMap,
511 vm_offset_t AddrStart, size_t cb, uint32_t fAccess,
512 RTR0PROCESS R0Process, int fFlags)
513{
514 int rc;
515 NOREF(fAccess);
516
517 /* create the object. */
518 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_LOCK, (void *)AddrStart, cb);
519 if (!pMemFreeBSD)
520 return VERR_NO_MEMORY;
521
522 /*
523 * We could've used vslock here, but we don't wish to be subject to
524 * resource usage restrictions, so we'll call vm_map_wire directly.
525 */
526 rc = vm_map_wire(pVmMap, /* the map */
527 AddrStart, /* start */
528 AddrStart + cb, /* end */
529 fFlags); /* flags */
530 if (rc == KERN_SUCCESS)
531 {
532 pMemFreeBSD->Core.u.Lock.R0Process = R0Process;
533 *ppMem = &pMemFreeBSD->Core;
534 return VINF_SUCCESS;
535 }
536 rtR0MemObjDelete(&pMemFreeBSD->Core);
537 return VERR_NO_MEMORY;/** @todo fix mach -> vbox error conversion for freebsd. */
538}
539
540
541DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
542{
543 return rtR0MemObjNativeLockInMap(ppMem,
544 &((struct proc *)R0Process)->p_vmspace->vm_map,
545 (vm_offset_t)R3Ptr,
546 cb,
547 fAccess,
548 R0Process,
549 VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
550}
551
552
553DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
554{
555 return rtR0MemObjNativeLockInMap(ppMem,
556 kernel_map,
557 (vm_offset_t)pv,
558 cb,
559 fAccess,
560 NIL_RTR0PROCESS,
561 VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);
562}
563
564
565/**
566 * Worker for the two virtual address space reservers.
567 *
568 * We're leaning on the examples provided by mmap and vm_mmap in vm_mmap.c here.
569 */
570static int rtR0MemObjNativeReserveInMap(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process, vm_map_t pMap)
571{
572 int rc;
573
574 /*
575 * The pvFixed address range must be within the VM space when specified.
576 */
577 if ( pvFixed != (void *)-1
578 && ( (vm_offset_t)pvFixed < vm_map_min(pMap)
579 || (vm_offset_t)pvFixed + cb > vm_map_max(pMap)))
580 return VERR_INVALID_PARAMETER;
581
582 /*
583 * Check that the specified alignment is supported.
584 */
585 if (uAlignment > PAGE_SIZE)
586 return VERR_NOT_SUPPORTED;
587
588 /*
589 * Create the object.
590 */
591 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_RES_VIRT, NULL, cb);
592 if (!pMemFreeBSD)
593 return VERR_NO_MEMORY;
594
595 vm_offset_t MapAddress = pvFixed != (void *)-1
596 ? (vm_offset_t)pvFixed
597 : vm_map_min(pMap);
598 if (pvFixed != (void *)-1)
599 vm_map_remove(pMap,
600 MapAddress,
601 MapAddress + cb);
602
603 rc = vm_map_find(pMap, /* map */
604 NULL, /* object */
605 0, /* offset */
606 &MapAddress, /* addr (IN/OUT) */
607 cb, /* length */
608#if __FreeBSD_version >= 1000055
609 0, /* max addr */
610#endif
611 pvFixed == (void *)-1 ? VMFS_ANY_SPACE : VMFS_NO_SPACE,
612 /* find_space */
613 VM_PROT_NONE, /* protection */
614 VM_PROT_ALL, /* max(_prot) ?? */
615 0); /* cow (copy-on-write) */
616 if (rc == KERN_SUCCESS)
617 {
618 if (R0Process != NIL_RTR0PROCESS)
619 {
620 rc = vm_map_inherit(pMap,
621 MapAddress,
622 MapAddress + cb,
623 VM_INHERIT_SHARE);
624 AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
625 }
626 pMemFreeBSD->Core.pv = (void *)MapAddress;
627 pMemFreeBSD->Core.u.ResVirt.R0Process = R0Process;
628 *ppMem = &pMemFreeBSD->Core;
629 return VINF_SUCCESS;
630 }
631
632 rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
633 rtR0MemObjDelete(&pMemFreeBSD->Core);
634 return rc;
635
636}
637
638
639DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
640{
641 return rtR0MemObjNativeReserveInMap(ppMem, pvFixed, cb, uAlignment, NIL_RTR0PROCESS, kernel_map);
642}
643
644
645DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
646{
647 return rtR0MemObjNativeReserveInMap(ppMem, (void *)R3PtrFixed, cb, uAlignment, R0Process,
648 &((struct proc *)R0Process)->p_vmspace->vm_map);
649}
650
651
652DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
653 unsigned fProt, size_t offSub, size_t cbSub)
654{
655// AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
656 AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED);
657
658 /*
659 * Check that the specified alignment is supported.
660 */
661 if (uAlignment > PAGE_SIZE)
662 return VERR_NOT_SUPPORTED;
663
664 int rc;
665 PRTR0MEMOBJFREEBSD pMemToMapFreeBSD = (PRTR0MEMOBJFREEBSD)pMemToMap;
666
667 /* calc protection */
668 vm_prot_t ProtectionFlags = 0;
669 if ((fProt & RTMEM_PROT_NONE) == RTMEM_PROT_NONE)
670 ProtectionFlags = VM_PROT_NONE;
671 if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ)
672 ProtectionFlags |= VM_PROT_READ;
673 if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE)
674 ProtectionFlags |= VM_PROT_WRITE;
675 if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC)
676 ProtectionFlags |= VM_PROT_EXECUTE;
677
678 vm_offset_t Addr = vm_map_min(kernel_map);
679 if (cbSub == 0)
680 cbSub = pMemToMap->cb - offSub;
681
682 vm_object_reference(pMemToMapFreeBSD->pObject);
683 rc = vm_map_find(kernel_map, /* Map to insert the object in */
684 pMemToMapFreeBSD->pObject, /* Object to map */
685 offSub, /* Start offset in the object */
686 &Addr, /* Start address IN/OUT */
687 cbSub, /* Size of the mapping */
688#if __FreeBSD_version >= 1000055
689 0, /* Upper bound of mapping */
690#endif
691 VMFS_ANY_SPACE, /* Whether a suitable address should be searched for first */
692 ProtectionFlags, /* protection flags */
693 VM_PROT_ALL, /* Maximum protection flags */
694 0); /* copy-on-write and similar flags */
695
696 if (rc == KERN_SUCCESS)
697 {
698 rc = vm_map_wire(kernel_map, Addr, Addr + cbSub, VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
699 AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
700
701 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(RTR0MEMOBJFREEBSD),
702 RTR0MEMOBJTYPE_MAPPING,
703 (void *)Addr,
704 cbSub);
705 if (pMemFreeBSD)
706 {
707 Assert((vm_offset_t)pMemFreeBSD->Core.pv == Addr);
708 pMemFreeBSD->Core.u.Mapping.R0Process = NIL_RTR0PROCESS;
709 *ppMem = &pMemFreeBSD->Core;
710 return VINF_SUCCESS;
711 }
712 rc = vm_map_remove(kernel_map, Addr, Addr + cbSub);
713 AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
714 }
715 else
716 vm_object_deallocate(pMemToMapFreeBSD->pObject);
717
718 return VERR_NO_MEMORY;
719}
720
721
722DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
723 unsigned fProt, RTR0PROCESS R0Process)
724{
725 /*
726 * Check for unsupported stuff.
727 */
728 AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
729 if (uAlignment > PAGE_SIZE)
730 return VERR_NOT_SUPPORTED;
731
732 int rc;
733 PRTR0MEMOBJFREEBSD pMemToMapFreeBSD = (PRTR0MEMOBJFREEBSD)pMemToMap;
734 struct proc *pProc = (struct proc *)R0Process;
735 struct vm_map *pProcMap = &pProc->p_vmspace->vm_map;
736
737 /* calc protection */
738 vm_prot_t ProtectionFlags = 0;
739 if ((fProt & RTMEM_PROT_NONE) == RTMEM_PROT_NONE)
740 ProtectionFlags = VM_PROT_NONE;
741 if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ)
742 ProtectionFlags |= VM_PROT_READ;
743 if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE)
744 ProtectionFlags |= VM_PROT_WRITE;
745 if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC)
746 ProtectionFlags |= VM_PROT_EXECUTE;
747
748 /* calc mapping address */
749 vm_offset_t AddrR3;
750 if (R3PtrFixed == (RTR3PTR)-1)
751 {
752 /** @todo: is this needed?. */
753 PROC_LOCK(pProc);
754 AddrR3 = round_page((vm_offset_t)pProc->p_vmspace->vm_daddr + lim_max(pProc, RLIMIT_DATA));
755 PROC_UNLOCK(pProc);
756 }
757 else
758 AddrR3 = (vm_offset_t)R3PtrFixed;
759
760 /* Insert the pObject in the map. */
761 vm_object_reference(pMemToMapFreeBSD->pObject);
762 rc = vm_map_find(pProcMap, /* Map to insert the object in */
763 pMemToMapFreeBSD->pObject, /* Object to map */
764 0, /* Start offset in the object */
765 &AddrR3, /* Start address IN/OUT */
766 pMemToMap->cb, /* Size of the mapping */
767#if __FreeBSD_version >= 1000055
768 0, /* Upper bound of the mapping */
769#endif
770 R3PtrFixed == (RTR3PTR)-1 ? VMFS_ANY_SPACE : VMFS_NO_SPACE,
771 /* Whether a suitable address should be searched for first */
772 ProtectionFlags, /* protection flags */
773 VM_PROT_ALL, /* Maximum protection flags */
774 0); /* copy-on-write and similar flags */
775
776 if (rc == KERN_SUCCESS)
777 {
778 rc = vm_map_wire(pProcMap, AddrR3, AddrR3 + pMemToMap->cb, VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
779 AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
780
781 rc = vm_map_inherit(pProcMap, AddrR3, AddrR3 + pMemToMap->cb, VM_INHERIT_SHARE);
782 AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
783
784 /*
785 * Create a mapping object for it.
786 */
787 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(RTR0MEMOBJFREEBSD),
788 RTR0MEMOBJTYPE_MAPPING,
789 (void *)AddrR3,
790 pMemToMap->cb);
791 if (pMemFreeBSD)
792 {
793 Assert((vm_offset_t)pMemFreeBSD->Core.pv == AddrR3);
794 pMemFreeBSD->Core.u.Mapping.R0Process = R0Process;
795 *ppMem = &pMemFreeBSD->Core;
796 return VINF_SUCCESS;
797 }
798
799 rc = vm_map_remove(pProcMap, AddrR3, AddrR3 + pMemToMap->cb);
800 AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
801 }
802 else
803 vm_object_deallocate(pMemToMapFreeBSD->pObject);
804
805 return VERR_NO_MEMORY;
806}
807
808
809DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
810{
811 vm_prot_t ProtectionFlags = 0;
812 vm_offset_t AddrStart = (uintptr_t)pMem->pv + offSub;
813 vm_offset_t AddrEnd = AddrStart + cbSub;
814 vm_map_t pVmMap = rtR0MemObjFreeBSDGetMap(pMem);
815
816 if (!pVmMap)
817 return VERR_NOT_SUPPORTED;
818
819 if ((fProt & RTMEM_PROT_NONE) == RTMEM_PROT_NONE)
820 ProtectionFlags = VM_PROT_NONE;
821 if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ)
822 ProtectionFlags |= VM_PROT_READ;
823 if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE)
824 ProtectionFlags |= VM_PROT_WRITE;
825 if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC)
826 ProtectionFlags |= VM_PROT_EXECUTE;
827
828 int krc = vm_map_protect(pVmMap, AddrStart, AddrEnd, ProtectionFlags, FALSE);
829 if (krc == KERN_SUCCESS)
830 return VINF_SUCCESS;
831
832 return VERR_NOT_SUPPORTED;
833}
834
835
836DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
837{
838 PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)pMem;
839
840 switch (pMemFreeBSD->Core.enmType)
841 {
842 case RTR0MEMOBJTYPE_LOCK:
843 {
844 if ( pMemFreeBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS
845 && pMemFreeBSD->Core.u.Lock.R0Process != (RTR0PROCESS)curproc)
846 {
847 /* later */
848 return NIL_RTHCPHYS;
849 }
850
851 vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + ptoa(iPage);
852
853 struct proc *pProc = (struct proc *)pMemFreeBSD->Core.u.Lock.R0Process;
854 struct vm_map *pProcMap = &pProc->p_vmspace->vm_map;
855 pmap_t pPhysicalMap = vm_map_pmap(pProcMap);
856
857 return pmap_extract(pPhysicalMap, pb);
858 }
859
860 case RTR0MEMOBJTYPE_MAPPING:
861 {
862 vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + ptoa(iPage);
863
864 if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
865 {
866 struct proc *pProc = (struct proc *)pMemFreeBSD->Core.u.Mapping.R0Process;
867 struct vm_map *pProcMap = &pProc->p_vmspace->vm_map;
868 pmap_t pPhysicalMap = vm_map_pmap(pProcMap);
869
870 return pmap_extract(pPhysicalMap, pb);
871 }
872 return vtophys(pb);
873 }
874
875 case RTR0MEMOBJTYPE_PAGE:
876 case RTR0MEMOBJTYPE_LOW:
877 case RTR0MEMOBJTYPE_PHYS_NC:
878 {
879 RTHCPHYS addr;
880#if __FreeBSD_version >= 1000030
881 VM_OBJECT_WLOCK(pMemFreeBSD->pObject);
882#else
883 VM_OBJECT_LOCK(pMemFreeBSD->pObject);
884#endif
885 addr = VM_PAGE_TO_PHYS(vm_page_lookup(pMemFreeBSD->pObject, iPage));
886#if __FreeBSD_version >= 1000030
887 VM_OBJECT_WUNLOCK(pMemFreeBSD->pObject);
888#else
889 VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
890#endif
891 return addr;
892 }
893
894 case RTR0MEMOBJTYPE_PHYS:
895 return pMemFreeBSD->Core.u.Cont.Phys + ptoa(iPage);
896
897 case RTR0MEMOBJTYPE_CONT:
898 return pMemFreeBSD->Core.u.Phys.PhysBase + ptoa(iPage);
899
900 case RTR0MEMOBJTYPE_RES_VIRT:
901 default:
902 return NIL_RTHCPHYS;
903 }
904}
905
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette