VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp@ 8013

Last change on this file since 8013 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Rev
File size: 29.1 KB
Line 
1/* $Revision: 5999 $ */
2/** @file
3 * innotek Portable Runtime - Ring-0 Memory Objects, Common Code.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DEFAULT ///@todo RTLOGGROUP_MEM
32#include <iprt/memobj.h>
33#include <iprt/alloc.h>
34#include <iprt/process.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37#include <iprt/log.h>
38#include <iprt/param.h>
39#include "internal/memobj.h"
40
41
42/**
43 * Internal function for allocating a new memory object.
44 *
45 * @returns The allocated and initialized handle.
46 * @param cbSelf The size of the memory object handle. 0 mean default size.
47 * @param enmType The memory object type.
48 * @param pv The memory object mapping.
49 * @param cb The size of the memory object.
50 */
51PRTR0MEMOBJINTERNAL rtR0MemObjNew(size_t cbSelf, RTR0MEMOBJTYPE enmType, void *pv, size_t cb)
52{
53 PRTR0MEMOBJINTERNAL pNew;
54
55 /* validate the size */
56 if (!cbSelf)
57 cbSelf = sizeof(*pNew);
58 Assert(cbSelf >= sizeof(*pNew));
59 Assert(cbSelf == (uint32_t)cbSelf);
60
61 /*
62 * Allocate and initialize the object.
63 */
64 pNew = (PRTR0MEMOBJINTERNAL)RTMemAllocZ(cbSelf);
65 if (pNew)
66 {
67 pNew->u32Magic = RTR0MEMOBJ_MAGIC;
68 pNew->cbSelf = (uint32_t)cbSelf;
69 pNew->enmType = enmType;
70 pNew->cb = cb;
71 pNew->pv = pv;
72 }
73 return pNew;
74}
75
76
77/**
78 * Deletes an incomplete memory object.
79 *
80 * This is for cleaning up after failures during object creation.
81 *
82 * @param pMem The incomplete memory object to delete.
83 */
84void rtR0MemObjDelete(PRTR0MEMOBJINTERNAL pMem)
85{
86 if (pMem)
87 {
88 pMem->u32Magic++;
89 pMem->enmType = RTR0MEMOBJTYPE_END;
90 RTMemFree(pMem);
91 }
92}
93
94
95/**
96 * Links a mapping object to a primary object.
97 *
98 * @returns IPRT status code.
99 * @retval VINF_SUCCESS on success.
100 * @retval VINF_NO_MEMORY if we couldn't expand the mapping array of the parent.
101 * @param pParent The parent (primary) memory object.
102 * @param pChild The child (mapping) memory object.
103 */
104static int rtR0MemObjLink(PRTR0MEMOBJINTERNAL pParent, PRTR0MEMOBJINTERNAL pChild)
105{
106 uint32_t i;
107
108 /* sanity */
109 Assert(rtR0MemObjIsMapping(pChild));
110 Assert(!rtR0MemObjIsMapping(pParent));
111
112 /* expand the array? */
113 i = pParent->uRel.Parent.cMappings;
114 if (i >= pParent->uRel.Parent.cMappingsAllocated)
115 {
116 void *pv = RTMemRealloc(pParent->uRel.Parent.papMappings,
117 (i + 32) * sizeof(pParent->uRel.Parent.papMappings[0]));
118 if (!pv)
119 return VERR_NO_MEMORY;
120 pParent->uRel.Parent.papMappings = (PPRTR0MEMOBJINTERNAL)pv;
121 pParent->uRel.Parent.cMappingsAllocated = i + 32;
122 Assert(i == pParent->uRel.Parent.cMappings);
123 }
124
125 /* do the linking. */
126 pParent->uRel.Parent.papMappings[i] = pChild;
127 pParent->uRel.Parent.cMappings++;
128 pChild->uRel.Child.pParent = pParent;
129
130 return VINF_SUCCESS;
131}
132
133
134/**
135 * Checks if this is mapping or not.
136 *
137 * @returns true if it's a mapping, otherwise false.
138 * @param MemObj The ring-0 memory object handle.
139 */
140RTR0DECL(bool) RTR0MemObjIsMapping(RTR0MEMOBJ MemObj)
141{
142 /* Validate the object handle. */
143 PRTR0MEMOBJINTERNAL pMem;
144 AssertPtrReturn(MemObj, false);
145 pMem = (PRTR0MEMOBJINTERNAL)MemObj;
146 AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), false);
147 AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), false);
148
149 /* hand it on to the inlined worker. */
150 return rtR0MemObjIsMapping(pMem);
151}
152
153
154/**
155 * Gets the address of a ring-0 memory object.
156 *
157 * @returns The address of the memory object.
158 * @returns NULL if the handle is invalid (asserts in strict builds) or if there isn't any mapping.
159 * @param MemObj The ring-0 memory object handle.
160 */
161RTR0DECL(void *) RTR0MemObjAddress(RTR0MEMOBJ MemObj)
162{
163 /* Validate the object handle. */
164 PRTR0MEMOBJINTERNAL pMem;
165 if (RT_UNLIKELY(MemObj == NIL_RTR0MEMOBJ))
166 return NULL;
167 AssertPtrReturn(MemObj, NULL);
168 pMem = (PRTR0MEMOBJINTERNAL)MemObj;
169 AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), NULL);
170 AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), NULL);
171
172 /* return the mapping address. */
173 return pMem->pv;
174}
175
176
177/**
178 * Gets the ring-3 address of a ring-0 memory object.
179 *
180 * This only applies to ring-0 memory object with ring-3 mappings of some kind, i.e.
181 * locked user memory, reserved user address space and user mappings. This API should
182 * not be used on any other objects.
183 *
184 * @returns The address of the memory object.
185 * @returns NIL_RTR3PTR if the handle is invalid or if it's not an object with a ring-3 mapping.
186 * Strict builds will assert in both cases.
187 * @param MemObj The ring-0 memory object handle.
188 */
189RTR0DECL(RTR3PTR) RTR0MemObjAddressR3(RTR0MEMOBJ MemObj)
190{
191 PRTR0MEMOBJINTERNAL pMem;
192
193 /* Validate the object handle. */
194 if (RT_UNLIKELY(MemObj == NIL_RTR0MEMOBJ))
195 return NIL_RTR3PTR;
196 AssertPtrReturn(MemObj, NIL_RTR3PTR);
197 pMem = (PRTR0MEMOBJINTERNAL)MemObj;
198 AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), NIL_RTR3PTR);
199 AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), NIL_RTR3PTR);
200 if (RT_UNLIKELY( ( pMem->enmType != RTR0MEMOBJTYPE_MAPPING
201 || pMem->u.Mapping.R0Process == NIL_RTR0PROCESS)
202 && ( pMem->enmType != RTR0MEMOBJTYPE_LOCK
203 || pMem->u.Lock.R0Process == NIL_RTR0PROCESS)
204 && ( pMem->enmType != RTR0MEMOBJTYPE_PHYS_NC
205 || pMem->u.Lock.R0Process == NIL_RTR0PROCESS)
206 && ( pMem->enmType != RTR0MEMOBJTYPE_RES_VIRT
207 || pMem->u.ResVirt.R0Process == NIL_RTR0PROCESS)))
208 return NIL_RTR3PTR;
209
210 /* return the mapping address. */
211 return (RTR3PTR)pMem->pv;
212}
213
214
215/**
216 * Gets the size of a ring-0 memory object.
217 *
218 * @returns The address of the memory object.
219 * @returns 0 if the handle is invalid (asserts in strict builds) or if there isn't any mapping.
220 * @param MemObj The ring-0 memory object handle.
221 */
222RTR0DECL(size_t) RTR0MemObjSize(RTR0MEMOBJ MemObj)
223{
224 PRTR0MEMOBJINTERNAL pMem;
225
226 /* Validate the object handle. */
227 if (RT_UNLIKELY(MemObj == NIL_RTR0MEMOBJ))
228 return 0;
229 AssertPtrReturn(MemObj, 0);
230 pMem = (PRTR0MEMOBJINTERNAL)MemObj;
231 AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), 0);
232 AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), 0);
233
234 /* return the size. */
235 return pMem->cb;
236}
237
238
239/**
240 * Get the physical address of an page in the memory object.
241 *
242 * @returns The physical address.
243 * @returns NIL_RTHCPHYS if the object doesn't contain fixed physical pages.
244 * @returns NIL_RTHCPHYS if the iPage is out of range.
245 * @returns NIL_RTHCPHYS if the object handle isn't valid.
246 * @param MemObj The ring-0 memory object handle.
247 * @param iPage The page number within the object.
248 */
249RTR0DECL(RTHCPHYS) RTR0MemObjGetPagePhysAddr(RTR0MEMOBJ MemObj, size_t iPage)
250{
251 /* Validate the object handle. */
252 PRTR0MEMOBJINTERNAL pMem;
253 size_t cPages;
254 AssertPtrReturn(MemObj, NIL_RTHCPHYS);
255 pMem = (PRTR0MEMOBJINTERNAL)MemObj;
256 AssertReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, NIL_RTHCPHYS);
257 AssertReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, NIL_RTHCPHYS);
258 AssertMsgReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, ("%p: %#x\n", pMem, pMem->u32Magic), NIL_RTHCPHYS);
259 AssertMsgReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, ("%p: %d\n", pMem, pMem->enmType), NIL_RTHCPHYS);
260 cPages = (pMem->cb >> PAGE_SHIFT);
261 if (iPage >= cPages)
262 {
263 /* permit: while (RTR0MemObjGetPagePhysAddr(pMem, iPage++) != NIL_RTHCPHYS) {} */
264 if (iPage == cPages)
265 return NIL_RTHCPHYS;
266 AssertReturn(iPage < (pMem->cb >> PAGE_SHIFT), NIL_RTHCPHYS);
267 }
268
269 /*
270 * We know the address of physically contiguous allocations and mappings.
271 */
272 if (pMem->enmType == RTR0MEMOBJTYPE_CONT)
273 return pMem->u.Cont.Phys + iPage * PAGE_SIZE;
274 if (pMem->enmType == RTR0MEMOBJTYPE_PHYS)
275 return pMem->u.Phys.PhysBase + iPage * PAGE_SIZE;
276
277 /*
278 * Do the job.
279 */
280 return rtR0MemObjNativeGetPagePhysAddr(pMem, iPage);
281}
282
283
284/**
285 * Frees a ring-0 memory object.
286 *
287 * @returns IPRT status code.
288 * @retval VERR_INVALID_HANDLE if
289 * @param MemObj The ring-0 memory object to be freed. NULL is accepted.
290 * @param fFreeMappings Whether or not to free mappings of the object.
291 */
292RTR0DECL(int) RTR0MemObjFree(RTR0MEMOBJ MemObj, bool fFreeMappings)
293{
294 /*
295 * Validate the object handle.
296 */
297 PRTR0MEMOBJINTERNAL pMem;
298 int rc;
299
300 if (MemObj == NIL_RTR0MEMOBJ)
301 return VINF_SUCCESS;
302 AssertPtrReturn(MemObj, VERR_INVALID_HANDLE);
303 pMem = (PRTR0MEMOBJINTERNAL)MemObj;
304 AssertReturn(pMem->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
305 AssertReturn(pMem->enmType > RTR0MEMOBJTYPE_INVALID && pMem->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
306
307 /*
308 * Deal with mapings according to fFreeMappings.
309 */
310 if ( !rtR0MemObjIsMapping(pMem)
311 && pMem->uRel.Parent.cMappings > 0)
312 {
313 /* fail if not requested to free mappings. */
314 if (!fFreeMappings)
315 return VERR_MEMORY_BUSY;
316
317 while (pMem->uRel.Parent.cMappings > 0)
318 {
319 PRTR0MEMOBJINTERNAL pChild = pMem->uRel.Parent.papMappings[--pMem->uRel.Parent.cMappings];
320 pMem->uRel.Parent.papMappings[pMem->uRel.Parent.cMappings] = NULL;
321
322 /* sanity checks. */
323 AssertPtr(pChild);
324 AssertFatal(pChild->u32Magic == RTR0MEMOBJ_MAGIC);
325 AssertFatal(pChild->enmType > RTR0MEMOBJTYPE_INVALID && pChild->enmType < RTR0MEMOBJTYPE_END);
326 AssertFatal(rtR0MemObjIsMapping(pChild));
327
328 /* free the mapping. */
329 rc = rtR0MemObjNativeFree(pChild);
330 if (RT_FAILURE(rc))
331 {
332 Log(("RTR0MemObjFree: failed to free mapping %p: %p %#zx; rc=%Vrc\n", pChild, pChild->pv, pChild->cb, rc));
333 pMem->uRel.Parent.papMappings[pMem->uRel.Parent.cMappings++] = pChild;
334 return rc;
335 }
336 }
337 }
338
339 /*
340 * Free this object.
341 */
342 rc = rtR0MemObjNativeFree(pMem);
343 if (RT_SUCCESS(rc))
344 {
345 /*
346 * Ok, it was freed just fine. Now, if it's a mapping we'll have to remove it from the parent.
347 */
348 if (rtR0MemObjIsMapping(pMem))
349 {
350 PRTR0MEMOBJINTERNAL pParent = pMem->uRel.Child.pParent;
351 uint32_t i;
352
353 /* sanity checks */
354 AssertPtr(pParent);
355 AssertFatal(pParent->u32Magic == RTR0MEMOBJ_MAGIC);
356 AssertFatal(pParent->enmType > RTR0MEMOBJTYPE_INVALID && pParent->enmType < RTR0MEMOBJTYPE_END);
357 AssertFatal(!rtR0MemObjIsMapping(pParent));
358 AssertFatal(pParent->uRel.Parent.cMappings > 0);
359 AssertPtr(pParent->uRel.Parent.papMappings);
360
361 /* locate and remove from the array of mappings. */
362 i = pParent->uRel.Parent.cMappings;
363 while (i-- > 0)
364 {
365 if (pParent->uRel.Parent.papMappings[i] == pMem)
366 {
367 pParent->uRel.Parent.papMappings[i] = pParent->uRel.Parent.papMappings[--pParent->uRel.Parent.cMappings];
368 break;
369 }
370 }
371 Assert(i != UINT32_MAX);
372 }
373 else
374 Assert(pMem->uRel.Parent.cMappings == 0);
375
376 /*
377 * Finally, destroy the handle.
378 */
379 pMem->u32Magic++;
380 pMem->enmType = RTR0MEMOBJTYPE_END;
381 if (!rtR0MemObjIsMapping(pMem))
382 RTMemFree(pMem->uRel.Parent.papMappings);
383 RTMemFree(pMem);
384 }
385 else
386 Log(("RTR0MemObjFree: failed to free %p: %d %p %#zx; rc=%Vrc\n",
387 pMem, pMem->enmType, pMem->pv, pMem->cb, rc));
388 return rc;
389}
390
391
392
393/**
394 * Allocates page aligned virtual kernel memory.
395 *
396 * The memory is taken from a non paged (= fixed physical memory backing) pool.
397 *
398 * @returns IPRT status code.
399 * @param pMemObj Where to store the ring-0 memory object handle.
400 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
401 * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
402 */
403RTR0DECL(int) RTR0MemObjAllocPage(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable)
404{
405 /* sanity checks. */
406 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
407 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
408 *pMemObj = NIL_RTR0MEMOBJ;
409 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
410 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
411
412 /* do the allocation. */
413 return rtR0MemObjNativeAllocPage(pMemObj, cbAligned, fExecutable);
414}
415
416
417/**
418 * Allocates page aligned virtual kernel memory with physical backing below 4GB.
419 *
420 * The physical memory backing the allocation is fixed.
421 *
422 * @returns IPRT status code.
423 * @param pMemObj Where to store the ring-0 memory object handle.
424 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
425 * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
426 */
427RTR0DECL(int) RTR0MemObjAllocLow(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable)
428{
429 /* sanity checks. */
430 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
431 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
432 *pMemObj = NIL_RTR0MEMOBJ;
433 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
434 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
435
436 /* do the allocation. */
437 return rtR0MemObjNativeAllocLow(pMemObj, cbAligned, fExecutable);
438}
439
440
441/**
442 * Allocates page aligned virtual kernel memory with contiguous physical backing below 4GB.
443 *
444 * The physical memory backing the allocation is fixed.
445 *
446 * @returns IPRT status code.
447 * @param pMemObj Where to store the ring-0 memory object handle.
448 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
449 * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
450 */
451RTR0DECL(int) RTR0MemObjAllocCont(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable)
452{
453 /* sanity checks. */
454 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
455 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
456 *pMemObj = NIL_RTR0MEMOBJ;
457 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
458 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
459
460 /* do the allocation. */
461 return rtR0MemObjNativeAllocCont(pMemObj, cbAligned, fExecutable);
462}
463
464
465/**
466 * Locks a range of user virtual memory.
467 *
468 * @returns IPRT status code.
469 * @param pMemObj Where to store the ring-0 memory object handle.
470 * @param R3Ptr User virtual address. This is rounded down to a page boundrary.
471 * @param cb Number of bytes to lock. This is rounded up to nearest page boundrary.
472 * @param R0Process The process to lock pages in. NIL_R0PROCESS is an alias for the current one.
473 *
474 * @remark RTR0MemGetAddressR3() and RTR0MemGetAddress() will return the rounded down address.
475 */
476RTR0DECL(int) RTR0MemObjLockUser(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
477{
478 /* sanity checks. */
479 const size_t cbAligned = RT_ALIGN_Z(cb + (R3Ptr & PAGE_OFFSET_MASK), PAGE_SIZE);
480 RTR3PTR const R3PtrAligned = (R3Ptr & ~(RTR3PTR)PAGE_OFFSET_MASK);
481 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
482 *pMemObj = NIL_RTR0MEMOBJ;
483 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
484 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
485 if (R0Process == NIL_RTR0PROCESS)
486 R0Process = RTR0ProcHandleSelf();
487
488 /* do the locking. */
489 return rtR0MemObjNativeLockUser(pMemObj, R3PtrAligned, cbAligned, R0Process);
490}
491
492
493/**
494 * Locks a range of kernel virtual memory.
495 *
496 * @returns IPRT status code.
497 * @param pMemObj Where to store the ring-0 memory object handle.
498 * @param pv Kernel virtual address. This is rounded down to a page boundrary.
499 * @param cb Number of bytes to lock. This is rounded up to nearest page boundrary.
500 *
501 * @remark RTR0MemGetAddress() will return the rounded down address.
502 */
503RTR0DECL(int) RTR0MemObjLockKernel(PRTR0MEMOBJ pMemObj, void *pv, size_t cb)
504{
505 /* sanity checks. */
506 const size_t cbAligned = RT_ALIGN_Z(cb + ((uintptr_t)pv & PAGE_OFFSET_MASK), PAGE_SIZE);
507 void * const pvAligned = (void *)((uintptr_t)pv & ~(uintptr_t)PAGE_OFFSET_MASK);
508 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
509 *pMemObj = NIL_RTR0MEMOBJ;
510 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
511 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
512 AssertPtrReturn(pvAligned, VERR_INVALID_POINTER);
513
514 /* do the allocation. */
515 return rtR0MemObjNativeLockKernel(pMemObj, pvAligned, cbAligned);
516}
517
518
519/**
520 * Allocates contiguous page aligned physical memory without (necessarily) any kernel mapping.
521 *
522 * @returns IPRT status code.
523 * @param pMemObj Where to store the ring-0 memory object handle.
524 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
525 * @param PhysHighest The highest permittable address (inclusive).
526 * Pass NIL_RTHCPHYS if any address is acceptable.
527 */
528RTR0DECL(int) RTR0MemObjAllocPhys(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest)
529{
530 /* sanity checks. */
531 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
532 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
533 *pMemObj = NIL_RTR0MEMOBJ;
534 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
535 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
536 AssertReturn(PhysHighest >= cb, VERR_INVALID_PARAMETER);
537
538 /* do the allocation. */
539 return rtR0MemObjNativeAllocPhys(pMemObj, cbAligned, PhysHighest);
540}
541
542
543/**
544 * Allocates non-contiguous page aligned physical memory without (necessarily) any kernel mapping.
545 *
546 * @returns IPRT status code.
547 * @param pMemObj Where to store the ring-0 memory object handle.
548 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
549 * @param PhysHighest The highest permittable address (inclusive).
550 * Pass NIL_RTHCPHYS if any address is acceptable.
551 */
552RTR0DECL(int) RTR0MemObjAllocPhysNC(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest)
553{
554 /* sanity checks. */
555 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
556 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
557 *pMemObj = NIL_RTR0MEMOBJ;
558 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
559 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
560 AssertReturn(PhysHighest >= cb, VERR_INVALID_PARAMETER);
561
562 /* do the allocation. */
563 return rtR0MemObjNativeAllocPhysNC(pMemObj, cbAligned, PhysHighest);
564}
565
566
567/**
568 * Creates a page aligned, contiguous, physical memory object.
569 *
570 * No physical memory is allocated, we trust you do know what you're doing.
571 *
572 * @returns IPRT status code.
573 * @param pMemObj Where to store the ring-0 memory object handle.
574 * @param Phys The physical address to start at. This is rounded down to the
575 * nearest page boundrary.
576 * @param cb The size of the object in bytes. This is rounded up to nearest page boundrary.
577 */
578RTR0DECL(int) RTR0MemObjEnterPhys(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb)
579{
580 /* sanity checks. */
581 const size_t cbAligned = RT_ALIGN_Z(cb + (Phys & PAGE_OFFSET_MASK), PAGE_SIZE);
582 const RTHCPHYS PhysAligned = Phys & ~(RTHCPHYS)PAGE_OFFSET_MASK;
583 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
584 *pMemObj = NIL_RTR0MEMOBJ;
585 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
586 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
587 AssertReturn(Phys != NIL_RTHCPHYS, VERR_INVALID_PARAMETER);
588
589 /* do the allocation. */
590 return rtR0MemObjNativeEnterPhys(pMemObj, PhysAligned, cbAligned);
591}
592
593
594/**
595 * Reserves kernel virtual address space.
596 *
597 * @returns IPRT status code.
598 * @param pMemObj Where to store the ring-0 memory object handle.
599 * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment.
600 * @param cb The number of bytes to reserve. This is rounded up to nearest page.
601 * @param uAlignment The alignment of the reserved memory.
602 * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
603 */
604RTR0DECL(int) RTR0MemObjReserveKernel(PRTR0MEMOBJ pMemObj, void *pvFixed, size_t cb, size_t uAlignment)
605{
606 /* sanity checks. */
607 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
608 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
609 *pMemObj = NIL_RTR0MEMOBJ;
610 if (uAlignment == 0)
611 uAlignment = PAGE_SIZE;
612 AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
613 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
614 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
615 if (pvFixed != (void *)-1)
616 AssertReturn(!((uintptr_t)pvFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
617
618 /* do the reservation. */
619 return rtR0MemObjNativeReserveKernel(pMemObj, pvFixed, cbAligned, uAlignment);
620}
621
622
623/**
624 * Reserves user virtual address space in the current process.
625 *
626 * @returns IPRT status code.
627 * @param pMemObj Where to store the ring-0 memory object handle.
628 * @param R3PtrFixed Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
629 * @param cb The number of bytes to reserve. This is rounded up to nearest PAGE_SIZE.
630 * @param uAlignment The alignment of the reserved memory.
631 * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
632 * @param R0Process The process to reserve the memory in. NIL_R0PROCESS is an alias for the current one.
633 */
634RTR0DECL(int) RTR0MemObjReserveUser(PRTR0MEMOBJ pMemObj, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
635{
636 /* sanity checks. */
637 const size_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
638 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
639 *pMemObj = NIL_RTR0MEMOBJ;
640 if (uAlignment == 0)
641 uAlignment = PAGE_SIZE;
642 AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
643 AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
644 AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
645 if (R3PtrFixed != (RTR3PTR)-1)
646 AssertReturn(!(R3PtrFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
647 if (R0Process == NIL_RTR0PROCESS)
648 R0Process = RTR0ProcHandleSelf();
649
650 /* do the reservation. */
651 return rtR0MemObjNativeReserveUser(pMemObj, R3PtrFixed, cbAligned, uAlignment, R0Process);
652}
653
654
655/**
656 * Maps a memory object into kernel virtual address space.
657 *
658 * @returns IPRT status code.
659 * @param pMemObj Where to store the ring-0 memory object handle of the mapping object.
660 * @param MemObjToMap The object to be map.
661 * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment.
662 * @param uAlignment The alignment of the reserved memory.
663 * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
664 * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
665 */
666RTR0DECL(int) RTR0MemObjMapKernel(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, unsigned fProt)
667{
668 /* sanity checks. */
669 PRTR0MEMOBJINTERNAL pMemToMap;
670 PRTR0MEMOBJINTERNAL pNew;
671 int rc;
672 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
673 *pMemObj = NIL_RTR0MEMOBJ;
674 AssertPtrReturn(MemObjToMap, VERR_INVALID_HANDLE);
675 pMemToMap = (PRTR0MEMOBJINTERNAL)MemObjToMap;
676 AssertReturn(pMemToMap->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
677 AssertReturn(pMemToMap->enmType > RTR0MEMOBJTYPE_INVALID && pMemToMap->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
678 AssertReturn(!rtR0MemObjIsMapping(pMemToMap), VERR_INVALID_PARAMETER);
679 AssertReturn(pMemToMap->enmType != RTR0MEMOBJTYPE_RES_VIRT, VERR_INVALID_PARAMETER);
680 if (uAlignment == 0)
681 uAlignment = PAGE_SIZE;
682 AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
683 if (pvFixed != (void *)-1)
684 AssertReturn(!((uintptr_t)pvFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
685 AssertReturn(fProt != RTMEM_PROT_NONE, VERR_INVALID_PARAMETER);
686 AssertReturn(!(fProt & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
687
688
689 /* do the mapping. */
690 rc = rtR0MemObjNativeMapKernel(&pNew, pMemToMap, pvFixed, uAlignment, fProt);
691 if (RT_SUCCESS(rc))
692 {
693 /* link it. */
694 rc = rtR0MemObjLink(pMemToMap, pNew);
695 if (RT_SUCCESS(rc))
696 *pMemObj = pNew;
697 else
698 {
699 /* damn, out of memory. bail out. */
700 int rc2 = rtR0MemObjNativeFree(pNew);
701 AssertRC(rc2);
702 pNew->u32Magic++;
703 pNew->enmType = RTR0MEMOBJTYPE_END;
704 RTMemFree(pNew);
705 }
706 }
707
708 return rc;
709}
710
711
712/**
713 * Maps a memory object into user virtual address space in the current process.
714 *
715 * @returns IPRT status code.
716 * @param pMemObj Where to store the ring-0 memory object handle of the mapping object.
717 * @param MemObjToMap The object to be map.
718 * @param R3PtrFixed Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
719 * @param uAlignment The alignment of the reserved memory.
720 * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
721 * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
722 * @param R0Process The process to map the memory into. NIL_R0PROCESS is an alias for the current one.
723 */
724RTR0DECL(int) RTR0MemObjMapUser(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
725{
726 /* sanity checks. */
727 PRTR0MEMOBJINTERNAL pMemToMap;
728 PRTR0MEMOBJINTERNAL pNew;
729 int rc;
730 AssertPtrReturn(pMemObj, VERR_INVALID_POINTER);
731 pMemToMap = (PRTR0MEMOBJINTERNAL)MemObjToMap;
732 *pMemObj = NIL_RTR0MEMOBJ;
733 AssertPtrReturn(MemObjToMap, VERR_INVALID_HANDLE);
734 AssertReturn(pMemToMap->u32Magic == RTR0MEMOBJ_MAGIC, VERR_INVALID_HANDLE);
735 AssertReturn(pMemToMap->enmType > RTR0MEMOBJTYPE_INVALID && pMemToMap->enmType < RTR0MEMOBJTYPE_END, VERR_INVALID_HANDLE);
736 AssertReturn(!rtR0MemObjIsMapping(pMemToMap), VERR_INVALID_PARAMETER);
737 AssertReturn(pMemToMap->enmType != RTR0MEMOBJTYPE_RES_VIRT, VERR_INVALID_PARAMETER);
738 if (uAlignment == 0)
739 uAlignment = PAGE_SIZE;
740 AssertReturn(uAlignment == PAGE_SIZE || uAlignment == _2M || uAlignment == _4M, VERR_INVALID_PARAMETER);
741 if (R3PtrFixed != (RTR3PTR)-1)
742 AssertReturn(!(R3PtrFixed & (uAlignment - 1)), VERR_INVALID_PARAMETER);
743 AssertReturn(fProt != RTMEM_PROT_NONE, VERR_INVALID_PARAMETER);
744 AssertReturn(!(fProt & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
745 if (R0Process == NIL_RTR0PROCESS)
746 R0Process = RTR0ProcHandleSelf();
747
748 /* do the mapping. */
749 rc = rtR0MemObjNativeMapUser(&pNew, pMemToMap, R3PtrFixed, uAlignment, fProt, R0Process);
750 if (RT_SUCCESS(rc))
751 {
752 /* link it. */
753 rc = rtR0MemObjLink(pMemToMap, pNew);
754 if (RT_SUCCESS(rc))
755 *pMemObj = pNew;
756 else
757 {
758 /* damn, out of memory. bail out. */
759 int rc2 = rtR0MemObjNativeFree(pNew);
760 AssertRC(rc2);
761 pNew->u32Magic++;
762 pNew->enmType = RTR0MEMOBJTYPE_END;
763 RTMemFree(pNew);
764 }
765 }
766
767 return rc;
768}
769
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