VirtualBox

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

Last change on this file since 1321 was 1191, checked in by vboxsync, 18 years ago

svn properties.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.4 KB
Line 
1/* $Id: memobj-r0drv-os2.cpp 1191 2007-03-04 20:46:04Z vboxsync $ */
2/** @file
3 * InnoTek Portable Runtime - Ring-0 Memory Objects, OS/2.
4 */
5
6/*
7 * Copyright (c) 2007 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include "the-os2-kernel.h"
36
37#include <iprt/memobj.h>
38#include <iprt/mem.h>
39#include <iprt/err.h>
40#include <iprt/assert.h>
41#include <iprt/log.h>
42#include <iprt/param.h>
43#include <iprt/process.h>
44#include "internal/memobj.h"
45
46
47/*******************************************************************************
48* Structures and Typedefs *
49*******************************************************************************/
50/**
51 * The OS/2 version of the memory object structure.
52 */
53typedef struct RTR0MEMOBJDARWIN
54{
55 /** The core structure. */
56 RTR0MEMOBJINTERNAL Core;
57 /** Lock for the ring-3 / ring-0 pinned objectes.
58 * This member might not be allocated for some object types. */
59 KernVMLock_t Lock;
60 /** Array of physical pages.
61 * This array can be 0 in length for some object types. */
62 KernPageList_t aPages[1];
63} RTR0MEMOBJOS2, *PRTR0MEMOBJOS2;
64
65
66/*******************************************************************************
67* Internal Functions *
68*******************************************************************************/
69static void rtR0MemObjFixPageList(KernPageList_t *paPages, ULONG cPages, ULONG cPagesRet);
70
71
72int rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
73{
74 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)pMem;
75 int rc;
76
77 switch (pMemOs2->Core.enmType)
78 {
79 case RTR0MEMOBJTYPE_PHYS:
80 if (!pMemOs2->Core.pv)
81 break;
82 case RTR0MEMOBJTYPE_PAGE:
83 case RTR0MEMOBJTYPE_LOW:
84 case RTR0MEMOBJTYPE_CONT:
85 case RTR0MEMOBJTYPE_MAPPING:
86 rc = KernVMFree(pMemOs2->Core.pv);
87 AssertMsg(!rc, ("rc=%d type=%d pv=%p cb=%#zx\n", rc, pMemOs2->Core.enmType, pMemOs2->Core.pv, pMemOs2->Core.cb));
88 break;
89
90 case RTR0MEMOBJTYPE_LOCK:
91 rc = KernVMUnlock(&pMemOs2->Lock);
92 AssertMsg(!rc, ("rc=%d\n", rc));
93 break;
94
95 case RTR0MEMOBJTYPE_RES_VIRT:
96 default:
97 AssertMsgFailed(("enmType=%d\n", pMemOs2->Core.enmType));
98 return VERR_INTERNAL_ERROR;
99 }
100
101 return VINF_SUCCESS;
102}
103
104
105int rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
106{
107 NOREF(fExecutable);
108
109 /* create the object. */
110 const ULONG cPages = cb >> PAGE_SHIFT;
111 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, aPages[cPages]), RTR0MEMOBJTYPE_PAGE, NULL, cb);
112 if (!pMemOs2)
113 return VERR_NO_MEMORY;
114
115 /* do the allocation. */
116 int rc = KernVMAlloc(cb, VMDHA_FIXED, &pMemOs2->Core.pv, (PPVOID)-1, NULL);
117 if (!rc)
118 {
119 ULONG cPagesRet = cPages;
120 rc = KernLinToPageList(pMemOs2->Core.pv, cb, &pMemOs2->aPages[0], &cPagesRet);
121 if (!rc)
122 {
123 rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
124 *ppMem = &pMemOs2->Core;
125 return VINF_SUCCESS;
126 }
127 KernVMFree(pMemOs2->Core.pv);
128 }
129 rtR0MemObjDelete(&pMemOs2->Core);
130 return RTErrConvertFromOS2(rc);
131}
132
133
134int rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
135{
136 NOREF(fExecutable);
137
138 /* create the object. */
139 const ULONG cPages = cb >> PAGE_SHIFT;
140 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, aPages[cPages]), RTR0MEMOBJTYPE_LOW, NULL, cb);
141 if (!pMemOs2)
142 return VERR_NO_MEMORY;
143
144 /* do the allocation. */
145 int rc = KernVMAlloc(cb, VMDHA_FIXED, &pMemOs2->Core.pv, (PPVOID)-1, NULL);
146 if (!rc)
147 {
148 ULONG cPagesRet = cPages;
149 rc = KernLinToPageList(pMemOs2->Core.pv, cb, &pMemOs2->aPages[0], &cPagesRet);
150 if (!rc)
151 {
152 rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
153 *ppMem = &pMemOs2->Core;
154 return VINF_SUCCESS;
155 }
156 KernVMFree(pMemOs2->Core.pv);
157 }
158 rtR0MemObjDelete(&pMemOs2->Core);
159 return RTErrConvertFromOS2(rc);
160}
161
162
163int rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
164{
165 NOREF(fExecutable);
166
167 /* create the object. */
168 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_CONT, NULL, cb);
169 if (!pMemOs2)
170 return VERR_NO_MEMORY;
171
172 /* do the allocation. */
173 ULONG ulPhys = ~0UL;
174 int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG, &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL);
175 if (!rc)
176 {
177 Assert(ulPhys != ~0UL);
178 pMemOs2->Core.u.Cont.Phys = ulPhys;
179 *ppMem = &pMemOs2->Core;
180 return VINF_SUCCESS;
181 }
182 rtR0MemObjDelete(&pMemOs2->Core);
183 return RTErrConvertFromOS2(rc);
184}
185
186
187int rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
188{
189 AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%VHp\n", PhysHighest), VERR_NOT_IMPLEMENTED);
190
191 /* create the object. */
192 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_PHYS, NULL, cb);
193 if (!pMemOs2)
194 return VERR_NO_MEMORY;
195
196 /* do the allocation. */
197 ULONG ulPhys = ~0UL;
198 int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG | (PhysHighest < _4G ? VMDHA_16M : 0), &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL);
199 if (!rc)
200 {
201 Assert(ulPhys != ~0UL);
202 pMemOs2->Core.u.Phys.fAllocated = true;
203 pMemOs2->Core.u.Phys.PhysBase = ulPhys;
204 *ppMem = &pMemOs2->Core;
205 return VINF_SUCCESS;
206 }
207 rtR0MemObjDelete(&pMemOs2->Core);
208 return RTErrConvertFromOS2(rc);
209}
210
211
212int rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb)
213{
214 /* create the object. */
215 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_PHYS, NULL, cb);
216 if (!pMemOs2)
217 return VERR_NO_MEMORY;
218
219 /* there is no allocation here, right? it needs to be mapped somewhere first. */
220 pMemOs2->Core.u.Phys.fAllocated = false;
221 pMemOs2->Core.u.Phys.PhysBase = Phys;
222 *ppMem = &pMemOs2->Core;
223 return VINF_SUCCESS;
224}
225
226
227int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, RTR0PROCESS R0Process)
228{
229 AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
230
231 /* create the object. */
232 const ULONG cPages = cb >> PAGE_SHIFT;
233 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, aPages[cPages]), RTR0MEMOBJTYPE_LOCK, pv, cb);
234 if (!pMemOs2)
235 return VERR_NO_MEMORY;
236
237 /* lock it. */
238 ULONG cPagesRet = cPages;
239 int rc = KernVMLock(VMDHL_LONG | VMDHL_WRITE, pv, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
240 if (!rc)
241 {
242 rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
243 Assert(cb == pMemOs2->Core.cb);
244 Assert(pv == pMemOs2->Core.pv);
245 pMemOs2->Core.u.Lock.R0Process = R0Process;
246 *ppMem = &pMemOs2->Core;
247 return VINF_SUCCESS;
248 }
249 rtR0MemObjDelete(&pMemOs2->Core);
250 return RTErrConvertFromOS2(rc);
251}
252
253
254int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
255{
256 /* create the object. */
257 const ULONG cPages = cb >> PAGE_SHIFT;
258 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, aPages[cPages]), RTR0MEMOBJTYPE_LOCK, pv, cb);
259 if (!pMemOs2)
260 return VERR_NO_MEMORY;
261
262 /* lock it. */
263 ULONG cPagesRet = cPages;
264 int rc = KernVMLock(VMDHL_LONG | VMDHL_WRITE, pv, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
265 if (!rc)
266 {
267 rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
268 pMemOs2->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
269 *ppMem = &pMemOs2->Core;
270 return VINF_SUCCESS;
271 }
272 rtR0MemObjDelete(&pMemOs2->Core);
273 return RTErrConvertFromOS2(rc);
274}
275
276
277int rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
278{
279 return VERR_NOT_IMPLEMENTED;
280}
281
282
283int rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
284{
285 return VERR_NOT_IMPLEMENTED;
286}
287
288
289int rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, unsigned fProt)
290{
291 return VERR_NOT_IMPLEMENTED;
292}
293
294
295int rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
296{
297 AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
298 AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED);
299
300 int rc;
301 void *pvR0;
302 void *pvR3 = NULL;
303 PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap;
304 switch (pMemToMapOs2->Core.enmType)
305 {
306 /*
307 * These has kernel mappings.
308 */
309 case RTR0MEMOBJTYPE_PAGE:
310 case RTR0MEMOBJTYPE_LOW:
311 case RTR0MEMOBJTYPE_CONT:
312 pvR0 = pMemToMapOs2->Core.pv;
313 break;
314
315 case RTR0MEMOBJTYPE_PHYS:
316 pvR0 = pMemToMapOs2->Core.pv;
317 if (!pvR0)
318 {
319 /* no ring-0 mapping, so allocate a mapping in the process. */
320 AssertMsgReturn(uAlignment == PAGE_SIZE, ("%#zx\n", uAlignment), VERR_NOT_SUPPORTED);
321 AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED);
322 Assert(!pMemToMapOs2->Core.u.Phys.fAllocated);
323 ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase;
324 rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS | VMDHA_PROCESS, &pvR3, (PPVOID)&ulPhys, NULL);
325 if (rc)
326 return RTErrConvertFromOS2(rc);
327 }
328 break;
329
330 case RTR0MEMOBJTYPE_LOCK:
331 if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
332 return VERR_NOT_SUPPORTED; /** @todo implement this... */
333 pvR0 = pMemToMapOs2->Core.pv;
334 break;
335
336 case RTR0MEMOBJTYPE_RES_VIRT:
337 case RTR0MEMOBJTYPE_MAPPING:
338 default:
339 AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType));
340 return VERR_INTERNAL_ERROR;
341 }
342
343 /*
344 * Map the ring-0 memory into the current process.
345 */
346 if (!pvR3)
347 {
348 Assert(pvR0);
349 ULONG flFlags = 0;
350 if (uAlignment == PAGE_SIZE)
351 flFlags |= VMDHGP_4MB;
352 if (fProt & RTMEM_PROT_WRITE)
353 flFlags |= VMDHGP_WRITE;
354 rc = RTR0Os2DHVMGlobalToProcess(flFlags, pvR0, pMemToMapOs2->Core.cb, &pvR3);
355 if (rc)
356 return RTErrConvertFromOS2(rc);
357 }
358 Assert(pvR3);
359
360 /*
361 * Create a mapping object for it.
362 */
363 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, pvR3, pMemToMapOs2->Core.cb);
364 if (pMemOs2)
365 {
366Assert(pMemOs2->Core.pv == pvR3);
367 pMemOs2->Core.u.Mapping.R0Process = R0Process;
368 *ppMem = &pMemOs2->Core;
369 return VINF_SUCCESS;
370 }
371 KernVMFree(pvR3);
372 return VERR_NO_MEMORY;
373}
374
375
376RTHCPHYS rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, unsigned iPage)
377{
378 PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)pMem;
379
380 switch (pMemOs2->Core.enmType)
381 {
382 case RTR0MEMOBJTYPE_PAGE:
383 case RTR0MEMOBJTYPE_LOW:
384 case RTR0MEMOBJTYPE_LOCK:
385 return pMemOs2->aPages[iPage].Addr;
386
387 case RTR0MEMOBJTYPE_CONT:
388 return pMemOs2->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
389
390 case RTR0MEMOBJTYPE_PHYS:
391 return pMemOs2->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
392
393 case RTR0MEMOBJTYPE_RES_VIRT:
394 case RTR0MEMOBJTYPE_MAPPING:
395 default:
396 return NIL_RTHCPHYS;
397 }
398}
399
400
401/**
402 * Expands the page list so we can index pages directly.
403 *
404 * @param paPages The page list array to fix.
405 * @param cPages The number of pages that's supposed to go into the list.
406 * @param cPagesRet The actual number of pages in the list.
407 */
408static void rtR0MemObjFixPageList(KernPageList_t *paPages, ULONG cPages, ULONG cPagesRet)
409{
410 Assert(cPages >= cPagesRet);
411 if (cPages != cPagesRet)
412 {
413 ULONG iIn = cPagesRet;
414 ULONG iOut = cPages;
415 do
416 {
417 iIn--;
418 iOut--;
419 Assert(iIn <= iOut);
420
421 KernPageList_t Page = paPages[iIn];
422 Assert(!(Page.Addr & PAGE_OFFSET_MASK));
423 Assert(Page.Size == RT_ALIGN_Z(Page.Size, PAGE_SIZE));
424
425 if (Page.Size > PAGE_SIZE)
426 {
427 do
428 {
429 Page.Size -= PAGE_SIZE;
430 paPages[iOut].Addr = Page.Addr + Page.Size;
431 paPages[iOut].Size = PAGE_SIZE;
432 iOut--;
433 } while (Page.Size > PAGE_SIZE);
434 }
435
436 paPages[iOut].Addr = Page.Addr;
437 paPages[iOut].Size = PAGE_SIZE;
438 } while ( iIn != iOut
439 && iIn > 0);
440 }
441}
442
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