VirtualBox

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

Last change on this file since 8217 was 8170, checked in by vboxsync, 17 years ago

Rebranding: replacing more innotek strings.

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