Changeset 37281 in vbox for trunk/src/VBox/Runtime/r0drv/solaris
- Timestamp:
- May 31, 2011 9:32:44 PM (14 years ago)
- Location:
- trunk/src/VBox/Runtime/r0drv/solaris/vbi
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/solaris/vbi/i86pc/os/vbi.c
r36623 r37281 20 20 */ 21 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.22 * Copyright 2010-2011 Sun Microsystems, Inc. All rights reserved. 23 23 * Use is subject to license terms. 24 24 */ … … 58 58 #include <sys/utsname.h> 59 59 60 #include <iprt/assert.h> 61 60 62 #include "vbi.h" 61 63 … … 76 78 /* Introduced in v9 */ 77 79 static int use_kflt = 0; 78 page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr);80 static page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr); 79 81 80 82 … … 562 564 563 565 void * 564 vbi_thread_create(void *func, void *arg, size_t len, int priority)566 vbi_thread_create(void (*func)(void *), void *arg, size_t len, int priority) 565 567 { 566 568 kthread_t *t; … … 1013 1015 map_addr(va, len, 0, 0, MAP_SHARED); 1014 1016 if (*va != NULL) 1015 {1016 1017 error = as_map(as, *va, len, segvbi_create, &args); 1017 }1018 1018 else 1019 1019 error = ENOMEM; … … 1030 1030 1031 1031 struct vbi_cpu_watch { 1032 void (*vbi_cpu_func)( );1032 void (*vbi_cpu_func)(void *, int, int); 1033 1033 void *vbi_cpu_arg; 1034 1034 }; … … 1051 1051 1052 1052 vbi_cpu_watch_t * 1053 vbi_watch_cpus(void (*func)( ), void *arg, int current_too)1053 vbi_watch_cpus(void (*func)(void *, int, int), void *arg, int current_too) 1054 1054 { 1055 1055 int c; … … 1211 1211 t->g_cyclic = CYCLIC_NONE; 1212 1212 1213 omni.cyo_online = (void (*)( ))vbi_gtimer_online;1213 omni.cyo_online = (void (*)(void *, cpu_t *, cyc_handler_t *, cyc_time_t *))vbi_gtimer_online; 1214 1214 omni.cyo_offline = NULL; 1215 1215 omni.cyo_arg = t; … … 1434 1434 1435 1435 1436 /* 1437 * This is revision 9 of the interface. 1438 */ 1439 page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr) 1436 1437 static page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr) 1440 1438 { 1441 1439 seg_t kernseg; … … 1474 1472 1475 1473 /* 1474 * Large page code. 1475 */ 1476 1477 page_t * 1478 vbi_large_page_alloc(uint64_t *pphys, size_t pgsize) 1479 { 1480 pgcnt_t const npages = pgsize >> PAGESHIFT; 1481 page_t *pproot, *pp, *pplist; 1482 pgcnt_t ipage; 1483 caddr_t vaddr; 1484 seg_t kernseg; 1485 int rc; 1486 1487 /* 1488 * Reserve available memory for a large page and create it. 1489 */ 1490 rc = page_resv(npages, KM_NOSLEEP); 1491 if (!rc) { 1492 return NULL; 1493 } 1494 rc = page_create_wait(npages, 0 /* flags */); 1495 if (!rc) { 1496 page_unresv(npages); 1497 return NULL; 1498 } 1499 1500 /* 1501 * Get a page off the free list. We set vaddr to 0 since we don't know 1502 * where the memory is going to be mapped. 1503 */ 1504 vaddr = NULL; 1505 kernseg.s_as = &kas; 1506 pproot = page_get_freelist(&vbipagevp, 0 /* offset */, &kernseg, 1507 vaddr, pgsize, 0x0000 /* flags */, NULL /*lgrp*/); 1508 if (!pproot && use_kflt) { 1509 pproot = page_get_freelist(&vbipagevp, 0 /* offset */, &kernseg, 1510 vaddr, pgsize, 0x0200 /* PG_KFLT */, NULL /*lgrp*/); 1511 if (!pproot) { 1512 page_create_putback(npages); 1513 page_unresv(npages); 1514 return NULL; 1515 } 1516 } 1517 AssertMsg(!(page_pptonum(pproot) & (npages - 1)), ("%p:%lx npages=%lx\n", pproot, page_pptonum(pproot), npages)); 1518 1519 /* 1520 * Mark all the sub-pages as non-free and not-hashed-in. 1521 * It is paramount that we destroy the list (before freeing it). 1522 */ 1523 pplist = pproot; 1524 for (ipage = 0; ipage < npages; ipage++) { 1525 pp = pplist; 1526 AssertPtr(pp); 1527 AssertMsg(page_pptonum(pp) == ipage + page_pptonum(pproot), 1528 ("%p:%lx %lx+%lx\n", pp, page_pptonum(pp), ipage, page_pptonum(pproot))); 1529 page_sub(&pplist, pp); 1530 AssertMsg(PP_ISFREE(pp), ("%p\n", pp)); 1531 AssertMsg(pp->p_szc == pproot->p_szc, ("%p - %d expected %d \n", pp, pp->p_szc, pproot->p_szc)); 1532 1533 PP_CLRFREE(pp); 1534 PP_CLRAGED(pp); 1535 } 1536 1537 *pphys = (uint64_t)page_pptonum(pproot) << PAGESHIFT; 1538 AssertMsg(!(*pphys & (pgsize - 1)), ("%llx %zx\n", *pphys, pgsize)); 1539 return pproot; 1540 } 1541 1542 void 1543 vbi_large_page_free(page_t *pproot, size_t pgsize) 1544 { 1545 pgcnt_t const npages = pgsize >> PAGESHIFT; 1546 pgcnt_t ipage; 1547 1548 Assert(page_get_pagecnt(pproot->p_szc) == npages); 1549 AssertMsg(!(page_pptonum(pproot) & (npages - 1)), ("%p:%lx npages=%lx\n", pproot, page_pptonum(pproot), npages)); 1550 1551 /* 1552 * We need to exclusively lock the sub-pages before freeing 1553 * the large one. 1554 */ 1555 for (ipage = 0; ipage < npages; ipage++) { 1556 page_t *pp = page_nextn(pproot, ipage); 1557 AssertMsg(page_pptonum(pp) == ipage + page_pptonum(pproot), 1558 ("%p:%lx %lx+%lx\n", pp, page_pptonum(pp), ipage, page_pptonum(pproot))); 1559 AssertMsg(!PP_ISFREE(pp), ("%p\n", pp)); 1560 1561 int rc = page_tryupgrade(pp); 1562 if (!rc) { 1563 page_unlock(pp); 1564 while (!page_lock(pp, SE_EXCL, NULL /* mutex */, P_RECLAIM)) { 1565 /*nothing*/; 1566 } 1567 } 1568 } 1569 1570 /* 1571 * Free the large page and unreserve the memory. 1572 */ 1573 page_free_pages(pproot); 1574 page_unresv(npages); 1575 } 1576 1577 int 1578 vbi_large_page_premap(page_t *pproot, size_t pgsize) 1579 { 1580 pgcnt_t const npages = pgsize >> PAGESHIFT; 1581 pgcnt_t ipage; 1582 1583 Assert(page_get_pagecnt(pproot->p_szc) == npages); 1584 AssertMsg(!(page_pptonum(pproot) & (npages - 1)), ("%p:%lx npages=%lx\n", pproot, page_pptonum(pproot), npages)); 1585 1586 /* 1587 * We need to downgrade the sub-pages from exclusive to shared locking 1588 * because otherwise we cannot <you go figure>. 1589 */ 1590 for (ipage = 0; ipage < npages; ipage++) { 1591 page_t *pp = page_nextn(pproot, ipage); 1592 AssertMsg(page_pptonum(pp) == ipage + page_pptonum(pproot), 1593 ("%p:%lx %lx+%lx\n", pp, page_pptonum(pp), ipage, page_pptonum(pproot))); 1594 AssertMsg(!PP_ISFREE(pp), ("%p\n", pp)); 1595 1596 if (page_tryupgrade(pp) == 1) 1597 page_downgrade(pp); 1598 AssertMsg(!PP_ISFREE(pp), ("%p\n", pp)); 1599 } 1600 1601 return 0; 1602 } 1603 1604 1605 /* 1476 1606 * As more functions are added, they should start with a comment indicating 1477 1607 * the revision and above this point in the file and the revision level should 1478 1608 * be increased. Also change vbi_modlmisc at the top of the file. 1609 * 1610 * NOTE! We'll start care about this if anything in here ever makes it into 1611 * the solaris kernel proper. 1479 1612 */ 1480 1613 uint_t vbi_revision_level = 9; -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/i86pc/sys/vbi.h
r27727 r37281 138 138 */ 139 139 extern void vbi_set_priority(void *thread, int priority); 140 extern void *vbi_thread_create(void *func, void *arg, size_t len, int priority);140 extern void *vbi_thread_create(void (*func)(void *), void *arg, size_t len, int priority); 141 141 extern void vbi_thread_exit(void); 142 142 … … 249 249 */ 250 250 typedef struct vbi_cpu_watch vbi_cpu_watch_t; 251 extern vbi_cpu_watch_t *vbi_watch_cpus(void (*func)(void ), void *arg,251 extern vbi_cpu_watch_t *vbi_watch_cpus(void (*func)(void *, int, int), void *arg, 252 252 int current_too); 253 253 extern void vbi_ignore_cpus(vbi_cpu_watch_t *); … … 345 345 /* begin interfaces defined for version 7 */ 346 346 /* 347 * Allocate and free physically limited, aligned as specified continuous or non-continuous memory. 347 * Allocate and free physically limited, aligned as specified continuous or non-continuous memory. 348 348 * 349 349 * return value is a) NULL if memory below "phys" not available or … … 369 369 * phys on input is set to the physical address of the first page allocated. 370 370 * 371 * size is the amount to allocate and must be a multiple of PAGESIZE 371 * size is the amount to allocate and must be a multiple of PAGESIZE. 372 372 */ 373 373 extern page_t **vbi_pages_alloc(uint64_t *phys, size_t size); … … 400 400 /* end of interfaces defined for version 8 */ 401 401 402 /* 403 * Allocate, free and map one large page. 404 * 405 * The size of the large page is hardware specific and must be specified 406 * correctly or we'll panic. :-) 407 */ 408 extern page_t *vbi_large_page_alloc(uint64_t *pphys, size_t pgsize); 409 extern void vbi_large_page_free(page_t *ppage, size_t pgsize); 410 extern int vbi_large_page_premap(page_t *pproot, size_t pgsize); 411 412 402 413 #ifdef __cplusplus 403 414 } -
trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c
r36555 r37281 33 33 #include <iprt/memobj.h> 34 34 35 #include <iprt/asm.h> 35 36 #include <iprt/assert.h> 36 37 #include <iprt/err.h> … … 57 58 /** Access during locking. */ 58 59 int fAccess; 60 /** Set if large pages are involved in an RTR0MEMOBJTYPE_PHYS 61 * allocation. */ 62 bool fLargePage; 59 63 } RTR0MEMOBJSOLARIS, *PRTR0MEMOBJSOLARIS; 60 64 … … 71 75 break; 72 76 73 case RTR0MEMOBJTYPE_CONT:74 77 case RTR0MEMOBJTYPE_PHYS: 75 vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb); 78 if (!pMemSolaris->Core.u.Phys.fAllocated) 79 { /* nothing to do here */; } 80 else if (pMemSolaris->fLargePage) 81 vbi_large_page_free(pMemSolaris->pvHandle, pMemSolaris->Core.cb); 82 else 83 vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb); 76 84 break; 77 85 78 86 case RTR0MEMOBJTYPE_PHYS_NC: 79 #if 0 80 vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb); 81 #else 82 if (pMemSolaris->Core.u.Phys.fAllocated == true) 83 ddi_umem_free(pMemSolaris->Cookie); 84 else 85 vbi_pages_free(pMemSolaris->pvHandle, pMemSolaris->Core.cb); 86 #endif 87 vbi_pages_free(pMemSolaris->pvHandle, pMemSolaris->Core.cb); 87 88 break; 88 89 … … 108 109 } 109 110 111 case RTR0MEMOBJTYPE_CONT: /* we don't use this type here. */ 110 112 default: 111 113 AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType)); … … 131 133 } 132 134 133 pMemSolaris->Core.pv = virtAddr;135 pMemSolaris->Core.pv = virtAddr; 134 136 pMemSolaris->pvHandle = NULL; 135 137 *ppMem = &pMemSolaris->Core; … … 176 178 return VERR_NO_MEMORY; 177 179 178 /* Allocate physically non-contiguous page-aligned memory. */ 179 uint64_t physAddr = PhysHighest; 180 181 # if 0 182 /* 183 * The contig_alloc() way of allocating NC pages is broken or does not match our semantics. Refer #4716 for details. 184 */ 185 # if 0 186 /* caddr_t virtAddr = vbi_phys_alloc(&physAddr, cb, PAGE_SIZE, 0 /* non-contiguous */); 187 # endif 188 caddr_t virtAddr = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie); 189 if (RT_UNLIKELY(virtAddr == NULL)) 190 { 191 rtR0MemObjDelete(&pMemSolaris->Core); 192 return VERR_NO_MEMORY; 193 } 194 pMemSolaris->Core.pv = virtAddr; 195 pMemSolaris->Core.u.Phys.PhysBase = physAddr; 196 pMemSolaris->Core.u.Phys.fAllocated = true; 197 pMemSolaris->pvHandle = NULL; 198 # else 199 void *pvPages = vbi_pages_alloc(&physAddr, cb); 180 uint64_t PhysAddr = PhysHighest; 181 void *pvPages = vbi_pages_alloc(&PhysAddr, cb); 200 182 if (!pvPages) 201 183 { … … 204 186 return VERR_NO_MEMORY; 205 187 } 206 pMemSolaris->Core.pv = NULL; 207 pMemSolaris->Core.u.Phys.PhysBase = physAddr; 208 pMemSolaris->Core.u.Phys.fAllocated = false; 209 pMemSolaris->pvHandle = pvPages; 210 # endif 211 212 Assert(!(physAddr & PAGE_OFFSET_MASK)); 213 *ppMem = &pMemSolaris->Core; 214 return VINF_SUCCESS; 215 #else 216 /** @todo rtR0MemObjNativeAllocPhysNC / solaris */ 188 pMemSolaris->Core.pv = NULL; 189 pMemSolaris->pvHandle = pvPages; 190 191 Assert(!(PhysAddr & PAGE_OFFSET_MASK)); 192 *ppMem = &pMemSolaris->Core; 193 return VINF_SUCCESS; 194 195 #else /* 32 bit: */ 217 196 return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */ 218 197 #endif … … 228 207 return VERR_NO_MEMORY; 229 208 230 AssertCompile(NIL_RTHCPHYS == UINT64_MAX); 231 232 /* Allocate physically contiguous memory aligned as specified. */ 233 uint64_t physAddr = PhysHighest; 234 caddr_t virtAddr = vbi_phys_alloc(&physAddr, cb, uAlignment, 1 /* contiguous */); 235 if (RT_UNLIKELY(virtAddr == NULL)) 236 { 237 rtR0MemObjDelete(&pMemSolaris->Core); 238 return VERR_NO_CONT_MEMORY; 239 } 240 Assert(!(physAddr & PAGE_OFFSET_MASK)); 241 Assert(physAddr < PhysHighest); 242 Assert(physAddr + cb <= PhysHighest); 243 #if 0 244 if (uAlignment != PAGE_SIZE) 245 { 246 /* uAlignment is always a multiple of PAGE_SIZE */ 247 pgcnt_t cPages = (cb + uAlignment - 1) >> PAGE_SHIFT; 248 void *pvPage = virtAddr; 249 while (cPages-- > 0) 250 { 251 uint64_t u64Page = vbi_va_to_pa(pvPage); 252 if (u64Page & (uAlignment - 1)) 253 { 254 LogRel(("rtR0MemObjNativeAllocPhys: alignment mismatch! cb=%u uAlignment=%u physAddr=%#x\n", cb, uAlignment, u64Page)); 255 vbi_phys_free(virtAddr, cb); 256 rtR0MemObjDelete(&pMemSolaris->Core); 257 return VERR_NO_MEMORY; 258 } 259 pvPage = (void *)((uintptr_t)pvPage + PAGE_SIZE); 260 } 261 } 209 /* 210 * Allocating one large page gets special treatment. 211 */ 212 static uint32_t s_cbLargePage = UINT32_MAX; 213 if (s_cbLargePage == UINT32_MAX) 214 { 215 #if 0 /* currently not entirely stable, so disabled. */ 216 if (page_num_pagesizes() > 1) 217 ASMAtomicWriteU32(&s_cbLargePage, page_get_pagesize(1)); 218 else 262 219 #endif 263 pMemSolaris->Core.pv = virtAddr; 264 pMemSolaris->Core.u.Cont.Phys = physAddr; 265 pMemSolaris->pvHandle = NULL; 266 *ppMem = &pMemSolaris->Core; 267 return VINF_SUCCESS; 220 ASMAtomicWriteU32(&s_cbLargePage, 0); 221 } 222 uint64_t PhysAddr; 223 if ( cb == s_cbLargePage 224 && cb == uAlignment 225 && PhysHighest == NIL_RTHCPHYS) 226 { 227 /* 228 * Allocate one large page. 229 */ 230 void *pvPages = vbi_large_page_alloc(&PhysAddr, cb); 231 if (pvPages) 232 { 233 AssertMsg(!(PhysAddr & (cb - 1)), ("%RHp\n", PhysAddr)); 234 pMemSolaris->Core.pv = NULL; 235 pMemSolaris->Core.u.Phys.PhysBase = PhysAddr; 236 pMemSolaris->Core.u.Phys.fAllocated = true; 237 pMemSolaris->pvHandle = pvPages; 238 pMemSolaris->fLargePage = true; 239 240 *ppMem = &pMemSolaris->Core; 241 return VINF_SUCCESS; 242 } 243 } 244 else 245 { 246 /* 247 * Allocate physically contiguous memory aligned as specified. 248 */ 249 AssertCompile(NIL_RTHCPHYS == UINT64_MAX); 250 PhysAddr = PhysHighest; 251 caddr_t pvMem = vbi_phys_alloc(&PhysAddr, cb, uAlignment, 1 /* contiguous */); 252 if (RT_LIKELY(pvMem)) 253 { 254 Assert(!(PhysAddr & PAGE_OFFSET_MASK)); 255 Assert(PhysAddr < PhysHighest); 256 Assert(PhysAddr + cb <= PhysHighest); 257 258 pMemSolaris->Core.pv = pvMem; 259 pMemSolaris->Core.u.Phys.PhysBase = PhysAddr; 260 pMemSolaris->Core.u.Phys.fAllocated = true; 261 pMemSolaris->pvHandle = NULL; 262 pMemSolaris->fLargePage = false; 263 264 *ppMem = &pMemSolaris->Core; 265 return VINF_SUCCESS; 266 } 267 } 268 rtR0MemObjDelete(&pMemSolaris->Core); 269 return VERR_NO_CONT_MEMORY; 268 270 } 269 271 … … 279 281 280 282 /* There is no allocation here, it needs to be mapped somewhere first. */ 281 pMemSolaris->Core.u.Phys.fAllocated = false;282 pMemSolaris->Core.u.Phys.PhysBase = Phys;283 pMemSolaris->Core.u.Phys.fAllocated = false; 284 pMemSolaris->Core.u.Phys.PhysBase = Phys; 283 285 pMemSolaris->Core.u.Phys.uCachePolicy = uCachePolicy; 284 286 *ppMem = &pMemSolaris->Core; … … 298 300 return VERR_NO_MEMORY; 299 301 302 /* Lock down user pages. */ 300 303 int fPageAccess = S_READ; 301 304 if (fAccess & RTMEM_PROT_WRITE) … … 304 307 fPageAccess = S_EXEC; 305 308 void *pvPageList = NULL; 306 307 /* Lock down user pages */308 309 int rc = vbi_lock_va((caddr_t)R3Ptr, cb, fPageAccess, &pvPageList); 309 310 if (rc != 0) … … 314 315 } 315 316 316 pMemSolaris->Core.u.Lock.R0Process = (RTR0PROCESS)vbi_proc(); 317 pMemSolaris->pvHandle = pvPageList; 318 pMemSolaris->fAccess = fPageAccess; 317 /* Fill in the object attributes and return successfully. */ 318 pMemSolaris->Core.u.Lock.R0Process = R0Process; 319 pMemSolaris->pvHandle = pvPageList; 320 pMemSolaris->fAccess = fPageAccess; 319 321 *ppMem = &pMemSolaris->Core; 320 322 return VINF_SUCCESS; … … 330 332 return VERR_NO_MEMORY; 331 333 334 /* Lock down kernel pages. */ 332 335 int fPageAccess = S_READ; 333 336 if (fAccess & RTMEM_PROT_WRITE) … … 344 347 } 345 348 349 /* Fill in the object attributes and return successfully. */ 346 350 pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS; 347 351 pMemSolaris->pvHandle = pvPageList; … … 360 364 */ 361 365 void *pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /*phase*/, 0 /*nocross*/, 362 NULL /*minaddr*/, NULL /*maxaddr*/, VM_SLEEP);366 NULL /*minaddr*/, NULL /*maxaddr*/, VM_SLEEP); 363 367 if (RT_UNLIKELY(!pv)) 364 368 return VERR_NO_MEMORY; … … 386 390 387 391 DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, 388 unsigned fProt, size_t offSub, size_t cbSub)392 unsigned fProt, size_t offSub, size_t cbSub) 389 393 { 390 394 /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */ … … 396 400 size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process) 397 401 { 402 /* 403 * Fend off things we cannot do. 404 */ 398 405 AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED); 399 406 AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED); … … 401 408 return VERR_NOT_SUPPORTED; 402 409 403 PRTR0MEMOBJSOLARIS pMemToMapSolaris = (PRTR0MEMOBJSOLARIS)pMemToMap; 404 size_t cb = pMemToMapSolaris->Core.cb; 405 void *pv = pMemToMapSolaris->Core.pv; 406 pgcnt_t cPages = (cb + PAGE_SIZE - 1) >> PAGE_SHIFT; 407 408 /* Create the mapping object */ 409 PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb); 410 /* 411 * Get parameters from the source object. 412 */ 413 PRTR0MEMOBJSOLARIS pMemToMapSolaris = (PRTR0MEMOBJSOLARIS)pMemToMap; 414 void *pv = pMemToMapSolaris->Core.pv; 415 size_t cb = pMemToMapSolaris->Core.cb; 416 pgcnt_t cPages = cb >> PAGE_SHIFT; 417 418 /* 419 * Create the mapping object 420 */ 421 PRTR0MEMOBJSOLARIS pMemSolaris; 422 pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb); 410 423 if (RT_UNLIKELY(!pMemSolaris)) 411 424 return VERR_NO_MEMORY; 412 425 426 int rc = VINF_SUCCESS; 413 427 uint64_t *paPhysAddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP); 414 if (RT_UNLIKELY(!paPhysAddrs)) 415 return VERR_NO_MEMORY; 416 417 if ( pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC 418 && pMemSolaris->Core.u.Phys.fAllocated == false) 428 if (RT_LIKELY(paPhysAddrs)) 419 429 { 420 430 /* 421 * The PhysNC object has no kernel mapping backing it. The call to vbi_pages_premap() 422 * prepares the physical pages to be mapped into user or kernel space. 431 * Prepare the pages according to type. 423 432 */ 424 int rc = vbi_pages_premap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs); 425 if (rc) 426 { 427 LogRel(("rtR0MemObjNativeMapUser: vbi_pages_premap failed. rc=%d\n", rc)); 428 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages); 429 rtR0MemObjDelete(&pMemSolaris->Core); 430 return VERR_MAP_FAILED; 431 } 433 if (pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC) 434 rc = vbi_pages_premap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs); 435 else if ( pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS 436 && pMemToMapSolaris->fLargePage) 437 { 438 RTHCPHYS Phys = pMemToMapSolaris->Core.u.Phys.PhysBase; 439 for (pgcnt_t iPage = 0; iPage < cPages; iPage++, Phys += PAGE_SIZE) 440 paPhysAddrs[iPage] = Phys; 441 rc = vbi_large_page_premap(pMemToMapSolaris->pvHandle, cb); 442 } 443 else 444 { 445 /* Have kernel mapping, just translate virtual to physical. */ 446 AssertPtr(pv); 447 rc = 0; 448 for (pgcnt_t iPage = 0; iPage < cPages; iPage++) 449 { 450 paPhysAddrs[iPage] = vbi_va_to_pa(pv); 451 if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1)) 452 { 453 LogRel(("rtR0MemObjNativeMapUser: no page to map.\n")); 454 rc = -1; 455 break; 456 } 457 pv = (void *)((uintptr_t)pv + PAGE_SIZE); 458 } 459 } 460 if (!rc) 461 { 462 /* 463 * Perform the actual mapping. 464 */ 465 caddr_t UserAddr = NULL; 466 rc = vbi_user_map(&UserAddr, fProt, paPhysAddrs, cb); 467 if (!rc) 468 { 469 pMemSolaris->Core.u.Mapping.R0Process = R0Process; 470 pMemSolaris->Core.pv = UserAddr; 471 472 *ppMem = &pMemSolaris->Core; 473 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages); 474 return VINF_SUCCESS; 475 } 476 477 LogRel(("rtR0MemObjNativeMapUser: vbi_user_map failed.\n")); 478 } 479 rc = VERR_MAP_FAILED; 480 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages); 432 481 } 433 482 else 434 { 435 /* 436 * All other memory object types have allocated memory with kernel mappings. 437 */ 438 for (pgcnt_t iPage = 0; iPage < cPages; iPage++) 439 { 440 paPhysAddrs[iPage] = vbi_va_to_pa(pv); 441 if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1)) 442 { 443 LogRel(("rtR0MemObjNativeMapUser: no page to map.\n")); 444 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages); 445 rtR0MemObjDelete(&pMemSolaris->Core); 446 return VERR_MAP_FAILED; 447 } 448 pv = (void *)((uintptr_t)pv + PAGE_SIZE); 449 } 450 } 451 452 caddr_t virtAddr = NULL; 453 int rc = vbi_user_map(&virtAddr, fProt, paPhysAddrs, cb); 454 if (rc != 0) 455 { 456 LogRel(("rtR0MemObjNativeMapUser: vbi mapping failure.\n")); 457 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages); 458 rtR0MemObjDelete(&pMemSolaris->Core); 459 return VERR_MAP_FAILED; 460 } 461 462 pMemSolaris->Core.u.Mapping.R0Process = (RTR0PROCESS)vbi_proc(); 463 pMemSolaris->Core.pv = virtAddr; 464 *ppMem = &pMemSolaris->Core; 465 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages); 466 return VINF_SUCCESS; 483 rc = VERR_NO_MEMORY; 484 rtR0MemObjDelete(&pMemSolaris->Core); 485 return rc; 467 486 } 468 487 … … 484 503 switch (pMemSolaris->Core.enmType) 485 504 { 505 case RTR0MEMOBJTYPE_PHYS_NC: 506 if (pMemSolaris->Core.u.Phys.fAllocated) 507 { 508 uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT); 509 return vbi_va_to_pa(pb); 510 } 511 return vbi_page_to_pa(pMemSolaris->pvHandle, iPage); 512 486 513 case RTR0MEMOBJTYPE_PAGE: 487 514 case RTR0MEMOBJTYPE_LOW: … … 501 528 case RTR0MEMOBJTYPE_CONT: 502 529 case RTR0MEMOBJTYPE_PHYS: 503 return pMemSolaris->Core.u.Cont.Phys + (iPage << PAGE_SHIFT); 504 505 case RTR0MEMOBJTYPE_PHYS_NC: 506 if (pMemSolaris->Core.u.Phys.fAllocated == true) 507 { 508 uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT); 509 return vbi_va_to_pa(pb); 510 } 511 return vbi_page_to_pa(pMemSolaris->pvHandle, iPage); 512 530 AssertFailed(); /* handled by the caller */ 513 531 case RTR0MEMOBJTYPE_RES_VIRT: 514 532 default:
Note:
See TracChangeset
for help on using the changeset viewer.