VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c@ 27003

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

rtR0MemObjNativeAllocPhysNC implementation for Solaris.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/* $Id: memobj-r0drv-solaris.c 27003 2010-03-03 18:56:23Z vboxsync $ */
2/** @file
3 * IPRT - Ring-0 Memory Objects, Solaris.
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#include "../the-solaris-kernel.h"
36#include "internal/iprt.h"
37#include <iprt/memobj.h>
38
39#include <iprt/assert.h>
40#include <iprt/err.h>
41#include <iprt/log.h>
42#include <iprt/mem.h>
43#include <iprt/param.h>
44#include <iprt/process.h>
45#include "internal/memobj.h"
46
47
48/*******************************************************************************
49* Structures and Typedefs *
50*******************************************************************************/
51/**
52 * The Solaris version of the memory object structure.
53 */
54typedef struct RTR0MEMOBJSOLARIS
55{
56 /** The core structure. */
57 RTR0MEMOBJINTERNAL Core;
58 /** Pointer to kernel memory cookie. */
59 ddi_umem_cookie_t Cookie;
60 /** Shadow locked pages. */
61 void *pvHandle;
62 /** Access during locking. */
63 int fAccess;
64} RTR0MEMOBJSOLARIS, *PRTR0MEMOBJSOLARIS;
65
66
67
68int rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
69{
70 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)pMem;
71
72 switch (pMemSolaris->Core.enmType)
73 {
74 case RTR0MEMOBJTYPE_LOW:
75 vbi_lowmem_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
76 break;
77
78 case RTR0MEMOBJTYPE_CONT:
79 case RTR0MEMOBJTYPE_PHYS:
80 vbi_contig_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
81 break;
82
83 case RTR0MEMOBJTYPE_PHYS_NC:
84 vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
85 break;
86
87 case RTR0MEMOBJTYPE_PAGE:
88 ddi_umem_free(pMemSolaris->Cookie);
89 break;
90
91 case RTR0MEMOBJTYPE_LOCK:
92 vbi_unlock_va(pMemSolaris->Core.pv, pMemSolaris->Core.cb, pMemSolaris->fAccess, pMemSolaris->pvHandle);
93 break;
94
95 case RTR0MEMOBJTYPE_MAPPING:
96 vbi_unmap(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
97 break;
98
99 case RTR0MEMOBJTYPE_RES_VIRT:
100 {
101 if (pMemSolaris->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
102 vmem_xfree(heap_arena, pMemSolaris->Core.pv, pMemSolaris->Core.cb);
103 else
104 AssertFailed();
105 break;
106 }
107
108 default:
109 AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
110 return VERR_INTERNAL_ERROR;
111 }
112
113 return VINF_SUCCESS;
114}
115
116
117int rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
118{
119 /* Create the object */
120 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PAGE, NULL, cb);
121 if (!pMemSolaris)
122 return VERR_NO_MEMORY;
123
124 void *virtAddr = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
125 if (!virtAddr)
126 {
127 rtR0MemObjDelete(&pMemSolaris->Core);
128 return VERR_NO_PAGE_MEMORY;
129 }
130
131 pMemSolaris->Core.pv = virtAddr;
132 pMemSolaris->pvHandle = NULL;
133 *ppMem = &pMemSolaris->Core;
134 return VINF_SUCCESS;
135}
136
137
138int rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
139{
140 NOREF(fExecutable);
141
142 /* Create the object */
143 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOW, NULL, cb);
144 if (!pMemSolaris)
145 return VERR_NO_MEMORY;
146
147 /* Allocate physically low page-aligned memory. */
148 caddr_t virtAddr;
149 uint64_t phys = (unsigned)0xffffffff;
150 virtAddr = vbi_lowmem_alloc(phys, cb);
151 if (virtAddr == NULL)
152 {
153 rtR0MemObjDelete(&pMemSolaris->Core);
154 return VERR_NO_LOW_MEMORY;
155 }
156 pMemSolaris->Core.pv = virtAddr;
157 pMemSolaris->pvHandle = NULL;
158 *ppMem = &pMemSolaris->Core;
159 return VINF_SUCCESS;
160}
161
162
163int rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
164{
165 NOREF(fExecutable);
166 return rtR0MemObjNativeAllocPhys(ppMem, cb, (uint64_t)0xffffffff /* highest address */, PAGE_SIZE /* alignment */);
167}
168
169
170int rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
171{
172#if HC_ARCH_BITS == 64
173 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS_NC, NULL, cb);
174 if (!pMemSolaris)
175 return VERR_NO_MEMORY;
176
177 if (PhysHighest == NIL_RTHCPHYS)
178 PhysHighest = (uint64_t)0xffffffff;
179
180 /* Allocate physically non-contiguous page-aligned memory. */
181 caddr_t virtAddr;
182 uint64_t phys = PhysHighest;
183 virtAddr = vbi_phys_alloc(&phys, cb, PAGE_SIZE, 0 /* non-contiguous */);
184 if (virtAddr == NULL)
185 {
186 rtR0MemObjDelete(&pMemSolaris->Core);
187 return VERR_NO_MEMORY;
188 }
189 Assert(phys < (uint64_t)1 << 32);
190 pMemSolaris->Core.pv = virtAddr;
191 pMemSolaris->Core.u.Phys.PhysBase = phys;
192 pMemSolaris->Core.u.Phys.fAllocated = true;
193 pMemSolaris->pvHandle = NULL;
194 *ppMem = &pMemSolaris->Core;
195 return VINF_SUCCESS;
196#else
197 /** @todo rtR0MemObjNativeAllocPhysNC / solaris */
198 return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
199#endif
200}
201
202
203int rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
204{
205 AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_IMPLEMENTED);
206
207 /** @todo alignment, vbi currently assumes PAGE_SIZE not even less than PAGE_SIZE */
208 if (uAlignment != PAGE_SIZE)
209 return VERR_NOT_SUPPORTED;
210
211 if (PhysHighest == NIL_RTHCPHYS)
212 PhysHighest = (uint64_t)0xffffffff;
213
214 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_CONT, NULL, cb);
215 if (!pMemSolaris)
216 return VERR_NO_MEMORY;
217
218 /* Allocate physically contiguous memory aligned as specified. */
219 caddr_t virtAddr;
220 uint64_t phys = PhysHighest;
221 virtAddr = vbi_phys_alloc(&phys, cb, uAlignment, 1 /* contiguous */);
222 if (virtAddr == NULL)
223 {
224 rtR0MemObjDelete(&pMemSolaris->Core);
225 return VERR_NO_CONT_MEMORY;
226 }
227 Assert(phys < (uint64_t)1 << 32);
228 pMemSolaris->Core.pv = virtAddr;
229 pMemSolaris->Core.u.Cont.Phys = phys;
230 pMemSolaris->pvHandle = NULL;
231 *ppMem = &pMemSolaris->Core;
232 return VINF_SUCCESS;
233}
234
235
236int rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb)
237{
238 /* Create the object */
239 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
240 if (!pMemSolaris)
241 return VERR_NO_MEMORY;
242
243 /* There is no allocation here, it needs to be mapped somewhere first */
244 pMemSolaris->Core.u.Phys.fAllocated = false;
245 pMemSolaris->Core.u.Phys.PhysBase = Phys;
246 *ppMem = &pMemSolaris->Core;
247 return VINF_SUCCESS;
248}
249
250
251int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
252{
253 AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
254 NOREF(fAccess);
255
256 /* Create the locking object */
257 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
258 if (!pMemSolaris)
259 return VERR_NO_MEMORY;
260
261 int fPageAccess = S_READ;
262 if (fAccess & RTMEM_PROT_WRITE)
263 fPageAccess = S_WRITE;
264 if (fAccess & RTMEM_PROT_EXEC)
265 fPageAccess = S_EXEC;
266 void *pvPageList = NULL;
267
268 /* Lock down user pages */
269 int rc = vbi_lock_va((caddr_t)R3Ptr, cb, fPageAccess, &pvPageList);
270 if (rc != 0)
271 {
272 LogRel(("rtR0MemObjNativeLockUser: vbi_lock_va failed rc=%d\n", rc));
273 rtR0MemObjDelete(&pMemSolaris->Core);
274 return VERR_LOCK_FAILED;
275 }
276
277 pMemSolaris->Core.u.Lock.R0Process = (RTR0PROCESS)vbi_proc();
278 pMemSolaris->pvHandle = pvPageList;
279 pMemSolaris->fAccess = fPageAccess;
280 *ppMem = &pMemSolaris->Core;
281 return VINF_SUCCESS;
282}
283
284
285int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
286{
287 NOREF(fAccess);
288
289 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
290 if (!pMemSolaris)
291 return VERR_NO_MEMORY;
292
293 int fPageAccess = S_READ;
294 if (fAccess & RTMEM_PROT_WRITE)
295 fPageAccess = S_WRITE;
296 if (fAccess & RTMEM_PROT_EXEC)
297 fPageAccess = S_EXEC;
298 void *pvPageList = NULL;
299 int rc = vbi_lock_va((caddr_t)pv, cb, fPageAccess, &pvPageList);
300 if (rc != 0)
301 {
302 LogRel(("rtR0MemObjNativeLockKernel: vbi_lock_va failed rc=%d\n", rc));
303 rtR0MemObjDelete(&pMemSolaris->Core);
304 return VERR_LOCK_FAILED;
305 }
306
307 pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
308 pMemSolaris->pvHandle = pvPageList;
309 pMemSolaris->fAccess = fPageAccess;
310 *ppMem = &pMemSolaris->Core;
311 return VINF_SUCCESS;
312}
313
314
315int rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
316{
317 PRTR0MEMOBJSOLARIS pMemSolaris;
318 void *pv;
319
320 /*
321 * Use xalloc.
322 */
323 pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /*phase*/, 0 /*nocross*/,
324 NULL /*minaddr*/, NULL /*maxaddr*/, VM_SLEEP);
325 if (!pv)
326 return VERR_NO_MEMORY;
327 pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
328 if (!pMemSolaris)
329 {
330 vmem_xfree(heap_arena, pv, cb);
331 return VERR_NO_MEMORY;
332 }
333
334 pMemSolaris->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS;
335 *ppMem = &pMemSolaris->Core;
336 return VINF_SUCCESS;
337}
338
339
340int rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
341{
342 return VERR_NOT_IMPLEMENTED;
343}
344
345int rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
346 unsigned fProt, size_t offSub, size_t cbSub)
347{
348 /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */
349 return VERR_NOT_IMPLEMENTED;
350}
351
352
353int rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
354{
355 AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
356 AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
357 if (uAlignment != PAGE_SIZE)
358 return VERR_NOT_SUPPORTED;
359
360 PRTR0MEMOBJSOLARIS pMemToMapSolaris = (PRTR0MEMOBJSOLARIS)pMemToMap;
361 size_t size = pMemToMapSolaris->Core.cb;
362 void *pv = pMemToMapSolaris->Core.pv;
363 pgcnt_t cPages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
364 pgcnt_t iPage;
365 uint64_t *paddrs;
366 caddr_t addr;
367 int rc;
368
369 /* Create the mapping object */
370 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, size);
371 if (!pMemSolaris)
372 return VERR_NO_MEMORY;
373
374 paddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP);
375 for (iPage = 0; iPage < cPages; iPage++)
376 {
377 paddrs[iPage] = vbi_va_to_pa(pv);
378 if (paddrs[iPage] == -(uint64_t)1)
379 {
380 LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
381 kmem_free(paddrs, sizeof(uint64_t) * cPages);
382 rtR0MemObjDelete(&pMemSolaris->Core);
383 return VERR_MAP_FAILED;
384 }
385 pv = (void *)((uintptr_t)pv + PAGE_SIZE);
386 }
387
388 rc = vbi_user_map(&addr, fProt, paddrs, size);
389 if (rc != 0)
390 {
391 LogRel(("rtR0MemObjNativeMapUser: vbi mapping failure.\n"));
392 kmem_free(paddrs, sizeof(uint64_t) * cPages);
393 rtR0MemObjDelete(&pMemSolaris->Core);
394 return VERR_MAP_FAILED;
395 }
396 else
397 rc = VINF_SUCCESS;
398
399 pMemSolaris->Core.u.Mapping.R0Process = (RTR0PROCESS)vbi_proc();
400 pMemSolaris->Core.pv = addr;
401 *ppMem = &pMemSolaris->Core;
402 kmem_free(paddrs, sizeof(uint64_t) * cPages);
403 return rc;
404}
405
406
407int rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
408{
409 NOREF(pMem);
410 NOREF(offSub);
411 NOREF(cbSub);
412 NOREF(fProt);
413 return VERR_NOT_SUPPORTED;
414}
415
416
417RTHCPHYS rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
418{
419 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)pMem;
420
421 switch (pMemSolaris->Core.enmType)
422 {
423 case RTR0MEMOBJTYPE_PAGE:
424 case RTR0MEMOBJTYPE_LOW:
425 case RTR0MEMOBJTYPE_LOCK:
426 {
427 uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
428 return vbi_va_to_pa(pb);
429 }
430
431 /*
432 * Although mapping can be handled by vbi_va_to_pa(offset) like the above case,
433 * request it from the parent so that we have a clear distinction between CONT/PHYS_NC.
434 */
435 case RTR0MEMOBJTYPE_MAPPING:
436 return rtR0MemObjNativeGetPagePhysAddr(pMemSolaris->Core.uRel.Child.pParent, iPage);
437
438 case RTR0MEMOBJTYPE_CONT:
439 case RTR0MEMOBJTYPE_PHYS:
440 return pMemSolaris->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
441
442 case RTR0MEMOBJTYPE_PHYS_NC:
443 if (pMemSolaris->Core.u.Phys.fAllocated == true)
444 {
445 uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
446 return vbi_va_to_pa(pb);
447 }
448 return pMemSolaris->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
449
450 case RTR0MEMOBJTYPE_RES_VIRT:
451 default:
452 return NIL_RTHCPHYS;
453 }
454}
455
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