VirtualBox

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

Last change on this file since 34244 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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