VirtualBox

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

Last change on this file since 20525 was 20525, checked in by vboxsync, 15 years ago

iprt/memobj.h: Added RTR0MemObjProtect, only implemented for darwin.

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