2  * Copyright (c) 2014-2016 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 #include <sys/cdefs.h> 
  31 #include <IOKit/assert.h> 
  32 #include <IOKit/system.h> 
  33 #include <IOKit/IOLib.h> 
  34 #include <IOKit/IOMemoryDescriptor.h> 
  35 #include <IOKit/IOMapper.h> 
  36 #include <IOKit/IODMACommand.h> 
  37 #include <IOKit/IOKitKeysPrivate.h> 
  41 #include <IOKit/IOSubMemoryDescriptor.h> 
  42 #endif /* !__LP64__ */ 
  43 #include <IOKit/IOSubMemoryDescriptor.h> 
  44 #include <IOKit/IOMultiMemoryDescriptor.h> 
  45 #include <IOKit/IOBufferMemoryDescriptor.h> 
  47 #include <IOKit/IOKitDebug.h> 
  48 #include <libkern/OSDebug.h> 
  53 #include <vm/vm_pageout.h> 
  54 #include <mach/memory_object_types.h> 
  55 #include <device/device_port.h> 
  57 #include <mach/vm_prot.h> 
  58 #include <mach/mach_vm.h> 
  59 #include <vm/vm_fault.h> 
  60 #include <vm/vm_protos.h> 
  64 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  66 #if DEVELOPMENT || DEBUG 
  68 extern SInt32 gIOMemoryReferenceCount
; 
  71 IOMultMemoryDescriptorTest(int newValue
) 
  73         IOMemoryDescriptor 
* mds
[3]; 
  74         IOMultiMemoryDescriptor 
* mmd
; 
  79         IOAddressRange ranges
[2]; 
  81         data 
= (typeof(data
))IOMallocAligned(ptoa(8), page_size
); 
  82         for (i 
= 0; i 
< ptoa(8); i
++) { 
  83                 data
[i
] = atop(i
) | 0xD0; 
  86         ranges
[0].address 
= (IOVirtualAddress
)(data 
+ ptoa(4)); 
  87         ranges
[0].length  
= ptoa(4); 
  88         ranges
[1].address 
= (IOVirtualAddress
)(data 
+ ptoa(0)); 
  89         ranges
[1].length  
= ptoa(4); 
  91         mds
[0] = IOMemoryDescriptor::withAddressRanges(&ranges
[0], 2, kIODirectionOutIn
, kernel_task
); 
  93         mds
[1] = IOSubMemoryDescriptor::withSubRange(mds
[0], ptoa(3), ptoa(2), kIODirectionOutIn
); 
  94         mds
[2] = IOSubMemoryDescriptor::withSubRange(mds
[0], ptoa(7), ptoa(1), kIODirectionOutIn
); 
  96         mmd 
= IOMultiMemoryDescriptor::withDescriptors(&mds
[0], sizeof(mds
) / sizeof(mds
[0]), kIODirectionOutIn
, false); 
 100         map 
= mmd
->createMappingInTask(kernel_task
, 0, kIOMapAnywhere
, ptoa(7), mmd
->getLength() - ptoa(7)); 
 104         addr 
= (void *) map
->getVirtualAddress(); 
 105         assert(ptoa(4) == map
->getLength()); 
 106         assert(0xd3d3d3d3 == ((uint32_t *)addr
)[ptoa(0) / sizeof(uint32_t)]); 
 107         assert(0xd7d7d7d7 == ((uint32_t *)addr
)[ptoa(1) / sizeof(uint32_t)]); 
 108         assert(0xd0d0d0d0 == ((uint32_t *)addr
)[ptoa(2) / sizeof(uint32_t)]); 
 109         assert(0xd3d3d3d3 == ((uint32_t *)addr
)[ptoa(3) / sizeof(uint32_t)]); 
 111         IOFreeAligned(data
, ptoa(8)); 
 118 // <rdar://problem/30102458> 
 120 IODMACommandForceDoubleBufferTest(int newValue
) 
 123         IOBufferMemoryDescriptor 
* bmd
; 
 126         IODMACommand::SegmentOptions segOptions 
= 
 128                 .fStructSize      
= sizeof(segOptions
), 
 129                 .fNumAddressBits  
= 64, 
 130                 .fMaxSegmentSize  
= 0x2000, 
 131                 .fMaxTransferSize 
= 128 * 1024, 
 133                 .fAlignmentLength 
= 1, 
 134                 .fAlignmentInternalSegments 
= 1 
 136         IODMACommand::Segment64 segments
[1]; 
 141         for (dir 
= kIODirectionIn
;; dir
++) { 
 142                 bmd 
= IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task
, 
 143                     dir 
| kIOMemoryPageable
, ptoa(8)); 
 146                 ((uint32_t*) bmd
->getBytesNoCopy())[0] = 0x53535300 | dir
; 
 148                 ret 
= bmd
->prepare((IODirection
) dir
); 
 149                 assert(kIOReturnSuccess 
== ret
); 
 151                 dma 
= IODMACommand::withSpecification(kIODMACommandOutputHost64
, &segOptions
, 
 152                     kIODMAMapOptionMapped
, 
 155                 ret 
= dma
->setMemoryDescriptor(bmd
, true); 
 156                 assert(kIOReturnSuccess 
== ret
); 
 158                 ret 
= dma
->synchronize(IODMACommand::kForceDoubleBuffer 
| kIODirectionOut
); 
 159                 assert(kIOReturnSuccess 
== ret
); 
 163                 ret 
= dma
->gen64IOVMSegments(&dmaOffset
, &segments
[0], &numSegments
); 
 164                 assert(kIOReturnSuccess 
== ret
); 
 165                 assert(1 == numSegments
); 
 167                 if (kIODirectionOut 
& dir
) { 
 168                         data 
= ((uint32_t*) bmd
->getBytesNoCopy())[0]; 
 169                         assertf((0x53535300 | dir
) == data
, "mismatch 0x%x", data
); 
 171                 if (kIODirectionIn 
& dir
) { 
 172                         IOMappedWrite32(segments
[0].fIOVMAddr
, 0x11223300 | dir
); 
 175                 ret 
= dma
->clearMemoryDescriptor(true); 
 176                 assert(kIOReturnSuccess 
== ret
); 
 179                 bmd
->complete((IODirection
) dir
); 
 181                 if (kIODirectionIn 
& dir
) { 
 182                         data 
= ((uint32_t*) bmd
->getBytesNoCopy())[0]; 
 183                         assertf((0x11223300 | dir
) == data
, "mismatch 0x%x", data
); 
 188                 if (dir 
== kIODirectionInOut
) { 
 196 // <rdar://problem/34322778> 
 198 IODMACommandLocalMappedNonContig(int newValue
) 
 201         IOMemoryDescriptor       
* md
; 
 203         OSDictionary             
* matching
; 
 206         IODMACommand::SegmentOptions segOptions 
= 
 208                 .fStructSize      
= sizeof(segOptions
), 
 209                 .fNumAddressBits  
= 64, 
 210                 .fMaxSegmentSize  
= 128 * 1024, 
 211                 .fMaxTransferSize 
= 128 * 1024, 
 213                 .fAlignmentLength 
= 1, 
 214                 .fAlignmentInternalSegments 
= 1 
 216         IODMACommand::Segment64 segments
[1]; 
 221         vm_size_t               bufSize 
= ptoa(4); 
 223         if (!IOMapper::gSystem
) { 
 228         kr 
= vm_allocate_kernel(kernel_map
, &buffer
, bufSize
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
); 
 229         assert(KERN_SUCCESS 
== kr
); 
 231         // fragment the vmentries 
 232         kr 
= vm_inherit(kernel_map
, buffer 
+ ptoa(1), ptoa(1), VM_INHERIT_NONE
); 
 233         assert(KERN_SUCCESS 
== kr
); 
 235         md 
= IOMemoryDescriptor::withAddressRange( 
 236                 buffer 
+ 0xa00, 0x2000, kIODirectionOutIn
, kernel_task
); 
 238         kr 
= md
->prepare(kIODirectionOutIn
); 
 239         assert(kIOReturnSuccess 
== kr
); 
 241         segPhys 
= md
->getPhysicalSegment(0, NULL
, 0); 
 243         matching 
= IOService::nameMatching("XHC1"); 
 245         device 
= IOService::copyMatchingService(matching
); 
 247         mapper 
= device 
? IOMapper::copyMapperForDeviceWithIndex(device
, 0) : NULL
; 
 249         dma 
= IODMACommand::withSpecification(kIODMACommandOutputHost64
, &segOptions
, 
 250             kIODMAMapOptionMapped
, 
 253         kr 
= dma
->setMemoryDescriptor(md
, true); 
 254         assert(kIOReturnSuccess 
== kr
); 
 258         kr 
= dma
->gen64IOVMSegments(&dmaOffset
, &segments
[0], &numSegments
); 
 259         assert(kIOReturnSuccess 
== kr
); 
 260         assert(1 == numSegments
); 
 263                 assertf(segments
[0].fIOVMAddr 
!= segPhys
, "phys !local 0x%qx, 0x%qx, %p", segments
[0].fIOVMAddr
, segPhys
, dma
); 
 266         kr 
= dma
->clearMemoryDescriptor(true); 
 267         assert(kIOReturnSuccess 
== kr
); 
 270         kr 
= md
->complete(kIODirectionOutIn
); 
 271         assert(kIOReturnSuccess 
== kr
); 
 274         kr 
= vm_deallocate(kernel_map
, buffer
, bufSize
); 
 275         assert(KERN_SUCCESS 
== kr
); 
 276         OSSafeReleaseNULL(mapper
); 
 281 // <rdar://problem/30102458> 
 283 IOMemoryRemoteTest(int newValue
) 
 286         IOMemoryDescriptor 
* md
; 
 287         IOByteCount          offset
, length
; 
 292         IODMACommand::SegmentOptions segOptions 
= 
 294                 .fStructSize      
= sizeof(segOptions
), 
 295                 .fNumAddressBits  
= 64, 
 296                 .fMaxSegmentSize  
= 0x2000, 
 297                 .fMaxTransferSize 
= 128 * 1024, 
 299                 .fAlignmentLength 
= 1, 
 300                 .fAlignmentInternalSegments 
= 1 
 302         IODMACommand::Segment64 segments
[1]; 
 306         IOAddressRange ranges
[2] = { 
 307                 { 0x1234567890123456ULL
, 0x1000 }, { 0x5432109876543210, 0x2000 }, 
 310         md 
= IOMemoryDescriptor::withAddressRanges(&ranges
[0], 2, kIODirectionOutIn 
| kIOMemoryRemote
, TASK_NULL
); 
 314 //    md->readBytes(0, &idx, sizeof(idx)); 
 316         ret 
= md
->prepare(kIODirectionOutIn
); 
 317         assert(kIOReturnSuccess 
== ret
); 
 319         printf("remote md flags 0x%qx, r %d\n", 
 320             md
->getFlags(), (0 != (kIOMemoryRemote 
& md
->getFlags()))); 
 322         for (offset 
= 0, idx 
= 0; true; offset 
+= length
, idx
++) { 
 323                 addr 
= md
->getPhysicalSegment(offset
, &length
, 0); 
 328                 assert(addr 
== ranges
[idx
].address
); 
 329                 assert(length 
== ranges
[idx
].length
); 
 331         assert(offset 
== md
->getLength()); 
 333         dma 
= IODMACommand::withSpecification(kIODMACommandOutputHost64
, &segOptions
, 
 334             kIODMAMapOptionUnmapped 
| kIODMAMapOptionIterateOnly
, 
 337         ret 
= dma
->setMemoryDescriptor(md
, true); 
 338         assert(kIOReturnSuccess 
== ret
); 
 340         for (dmaOffset 
= 0, idx 
= 0; dmaOffset 
< md
->getLength(); idx
++) { 
 342                 ret 
= dma
->gen64IOVMSegments(&dmaOffset
, &segments
[0], &numSegments
); 
 343                 assert(kIOReturnSuccess 
== ret
); 
 344                 assert(1 == numSegments
); 
 346                 assert(segments
[0].fIOVMAddr 
== ranges
[idx
].address
); 
 347                 assert(segments
[0].fLength 
== ranges
[idx
].length
); 
 349         assert(dmaOffset 
== md
->getLength()); 
 351         ret 
= dma
->clearMemoryDescriptor(true); 
 352         assert(kIOReturnSuccess 
== ret
); 
 354         md
->complete(kIODirectionOutIn
); 
 361 IOMemoryPrefaultTest(uint32_t options
) 
 363         IOBufferMemoryDescriptor 
* bmd
; 
 370         lock 
= IOSimpleLockAlloc(); 
 373         bmd 
= IOBufferMemoryDescriptor::inTaskWithOptions(current_task(), 
 374             kIODirectionOutIn 
| kIOMemoryPageable
, ptoa(8)); 
 377         assert(KERN_SUCCESS 
== kr
); 
 379         map 
= bmd
->map(kIOMapPrefault
); 
 382         p 
= (typeof(p
))map
->getVirtualAddress(); 
 383         IOSimpleLockLock(lock
); 
 385         IOSimpleLockUnlock(lock
); 
 387         IOLog("IOMemoryPrefaultTest %d\n", data
); 
 391         IOSimpleLockFree(lock
); 
 393         return kIOReturnSuccess
; 
 397 // <rdar://problem/26375234> 
 399 ZeroLengthTest(int newValue
) 
 401         IOMemoryDescriptor 
* md
; 
 403         md 
= IOMemoryDescriptor::withAddressRange( 
 404                 0, 0, kIODirectionNone
, current_task()); 
 412 // <rdar://problem/27002624> 
 414 BadFixedAllocTest(int newValue
) 
 416         IOBufferMemoryDescriptor 
* bmd
; 
 419         bmd 
= IOBufferMemoryDescriptor::inTaskWithOptions(NULL
, 
 420             kIODirectionIn 
| kIOMemoryPageable
, ptoa(1)); 
 422         map 
= bmd
->createMappingInTask(kernel_task
, 0x2000, 0); 
 429 // <rdar://problem/26466423> 
 431 IODirectionPrepareNoZeroFillTest(int newValue
) 
 433         IOBufferMemoryDescriptor 
* bmd
; 
 435         bmd 
= IOBufferMemoryDescriptor::inTaskWithOptions(NULL
, 
 436             kIODirectionIn 
| kIOMemoryPageable
, ptoa(24)); 
 438         bmd
->prepare((IODirection
)(kIODirectionIn 
| kIODirectionPrepareNoZeroFill
)); 
 439         bmd
->prepare(kIODirectionIn
); 
 440         bmd
->complete((IODirection
)(kIODirectionIn 
| kIODirectionCompleteWithDataValid
)); 
 441         bmd
->complete(kIODirectionIn
); 
 446 // <rdar://problem/28190483> 
 448 IOMemoryMapTest(uint32_t options
) 
 450         IOBufferMemoryDescriptor 
* bmd
; 
 451         IOMemoryDescriptor       
* md
; 
 459         bmd 
= IOBufferMemoryDescriptor::inTaskWithOptions(current_task(), 
 460             kIODirectionOutIn 
| kIOMemoryPageable
, 0x4018 + 0x800); 
 462         p 
= (typeof(p
))bmd
->getBytesNoCopy(); 
 465         r 
= copyout(&data
, p
, sizeof(data
)); 
 468         r 
= copyout(&data
, p 
+ 0x1000, sizeof(data
)); 
 471         r 
= copyout(&data
, p 
+ 0x2000, sizeof(data
)); 
 474         r 
= copyout(&data
, p 
+ 0x3000, sizeof(data
)); 
 477         md 
= IOMemoryDescriptor::withAddressRange(p
, 0x4018, 
 478             kIODirectionOut 
| options
, 
 481         time 
= mach_absolute_time(); 
 482         map 
= md
->map(kIOMapReadOnly
); 
 483         time 
= mach_absolute_time() - time
; 
 485         absolutetime_to_nanoseconds(time
, &nano
); 
 487         p2 
= (typeof(p2
))map
->getVirtualAddress(); 
 488         assert(0x11 == p2
[0]); 
 489         assert(0x22 == p2
[0x1000]); 
 490         assert(0x33 == p2
[0x2000]); 
 491         assert(0x44 == p2
[0x3000]); 
 494         r 
= copyout(&data
, p 
+ 0x2000, sizeof(data
)); 
 497         assert(0x11 == p2
[0]); 
 498         assert(0x22 == p2
[0x1000]); 
 499         assert(0x44 == p2
[0x3000]); 
 500         if (kIOMemoryMapCopyOnWrite 
& options
) { 
 501                 assert(0x33 == p2
[0x2000]); 
 503                 assert(0x99 == p2
[0x2000]); 
 506         IOLog("IOMemoryMapCopyOnWriteTest map(%s) %lld ns\n", 
 507             kIOMemoryMapCopyOnWrite 
& options 
? "kIOMemoryMapCopyOnWrite" : "", 
 514         return kIOReturnSuccess
; 
 518 IOMemoryMapCopyOnWriteTest(int newValue
) 
 521         IOMemoryMapTest(kIOMemoryMapCopyOnWrite
); 
 526 AllocationNameTest(int newValue
) 
 528         IOMemoryDescriptor 
* bmd
; 
 529         kern_allocation_name_t name
, prior
; 
 531         name 
= kern_allocation_name_allocate("com.apple.iokit.test", 0); 
 534         prior 
= thread_set_allocation_name(name
); 
 536         bmd 
= IOBufferMemoryDescriptor::inTaskWithOptions(TASK_NULL
, 
 537             kIODirectionOutIn 
| kIOMemoryPageable 
| kIOMemoryKernelUserShared
, 
 542         thread_set_allocation_name(prior
); 
 543         kern_allocation_name_release(name
); 
 553 IOMemoryDescriptorTest(int newValue
) 
 557         IOLog("/IOMemoryDescriptorTest %d\n", (int) gIOMemoryReferenceCount
); 
 561                 IOMemoryDescriptor 
* sbmds
[3]; 
 562                 IOMultiMemoryDescriptor 
* smmd
; 
 563                 IOMemoryDescriptor 
* mds
[2]; 
 564                 IOMultiMemoryDescriptor 
* mmd
; 
 567                 sbmds
[0] = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task
, kIODirectionOutIn 
| kIOMemoryKernelUserShared
, ptoa(1)); 
 568                 sbmds
[1] = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task
, kIODirectionOutIn 
| kIOMemoryKernelUserShared
, ptoa(2)); 
 569                 sbmds
[2] = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task
, kIODirectionOutIn 
| kIOMemoryKernelUserShared
, ptoa(3)); 
 570                 smmd 
= IOMultiMemoryDescriptor::withDescriptors(&sbmds
[0], sizeof(sbmds
) / sizeof(sbmds
[0]), kIODirectionOutIn
, false); 
 572                 mds
[0] = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task
, kIODirectionOutIn 
| kIOMemoryKernelUserShared
, ptoa(1)); 
 574                 mmd 
= IOMultiMemoryDescriptor::withDescriptors(&mds
[0], sizeof(mds
) / sizeof(mds
[0]), kIODirectionOutIn
, false); 
 575                 map 
= mmd
->createMappingInTask(kernel_task
, 0, kIOMapAnywhere
); 
 586         } else if (5 == newValue
) { 
 588                 IOMemoryDescriptor 
* md
; 
 590                 IODMACommand::SegmentOptions segOptions 
= 
 592                         .fStructSize      
= sizeof(segOptions
), 
 593                         .fNumAddressBits  
= 64, 
 594                         .fMaxSegmentSize  
= 4096, 
 595                         .fMaxTransferSize 
= 128 * 1024, 
 597                         .fAlignmentLength 
= 4, 
 598                         .fAlignmentInternalSegments 
= 0x1000 
 601                 IOAddressRange ranges
[3][2] = 
 604                                 { (uintptr_t) &IOMemoryDescriptorTest
, 0x2ffc }, 
 608                                 { ranges
[0][0].address
, 0x10 }, 
 609                                 { 0x3000 + ranges
[0][0].address
, 0xff0 }, 
 612                                 { ranges
[0][0].address
, 0x2ffc }, 
 613                                 { trunc_page(ranges
[0][0].address
), 0x800 }, 
 616                 static const uint32_t rangesCount
[3] = { 1, 2, 2 }; 
 619                 for (test 
= 0; test 
< 3; test
++) { 
 620                         kprintf("---[%d] address 0x%qx-0x%qx, 0x%qx-0x%qx\n", test
, 
 621                             ranges
[test
][0].address
, ranges
[test
][0].length
, 
 622                             ranges
[test
][1].address
, ranges
[test
][1].length
); 
 624                         md 
= IOMemoryDescriptor::withAddressRanges((IOAddressRange
*)&ranges
[test
][0], rangesCount
[test
], kIODirectionOut
, kernel_task
); 
 627                         assert(kIOReturnSuccess 
== ret
); 
 628                         dma 
= IODMACommand::withSpecification(kIODMACommandOutputHost64
, &segOptions
, 
 629                             IODMACommand::kMapped
, NULL
, NULL
); 
 631                         ret 
= dma
->setMemoryDescriptor(md
, true); 
 632                         if (kIOReturnSuccess 
== ret
) { 
 633                                 IODMACommand::Segment64 segments
[1]; 
 640                                         ret 
= dma
->gen64IOVMSegments(&offset
, &segments
[0], &numSegments
); 
 641                                         assert(kIOReturnSuccess 
== ret
); 
 642                                         assert(1 == numSegments
); 
 643                                         kprintf("seg 0x%qx, 0x%qx\n", segments
[0].fIOVMAddr
, segments
[0].fLength
); 
 644                                 }while (offset 
< md
->getLength()); 
 646                                 ret 
= dma
->clearMemoryDescriptor(true); 
 647                                 assert(kIOReturnSuccess 
== ret
); 
 653                 return kIOReturnSuccess
; 
 654         } else if (4 == newValue
) { 
 657                 IOBufferMemoryDescriptor 
* md1
; 
 660                 size_t         bufSize 
= 8192 * 8192 * sizeof(uint32_t); 
 661                 uint64_t start
, time
, nano
; 
 663                 isp 
= IOService::copyMatchingService(IOService::nameMatching("isp")); 
 665                 mapper 
= IOMapper::copyMapperForDeviceWithIndex(isp
, 0); 
 668                 md1 
= IOBufferMemoryDescriptor::inTaskWithOptions(TASK_NULL
, 
 669                     kIODirectionOutIn 
| kIOMemoryPersistent 
| kIOMemoryPageable
, 
 672                 ret 
= md1
->prepare(); 
 673                 assert(kIOReturnSuccess 
== ret
); 
 675                 IODMAMapSpecification mapSpec
; 
 676                 bzero(&mapSpec
, sizeof(mapSpec
)); 
 678                 uint64_t mappedLength
; 
 680                 start 
= mach_absolute_time(); 
 682                 ret 
=  md1
->dmaMap(mapper
, NULL
, &mapSpec
, 0, bufSize
, &mapped
, &mappedLength
); 
 683                 assert(kIOReturnSuccess 
== ret
); 
 685                 time 
= mach_absolute_time() - start
; 
 687                 absolutetime_to_nanoseconds(time
, &nano
); 
 688                 kprintf("time %lld us\n", nano 
/ 1000ULL); 
 689                 kprintf("seg0 0x%qx, 0x%qx\n", mapped
, mappedLength
); 
 693                 dma 
= IODMACommand::withSpecification(kIODMACommandOutputHost32
, 
 694                     32, 0, IODMACommand::kMapped
, 0, 1, mapper
, NULL
); 
 698                 start 
= mach_absolute_time(); 
 699                 ret 
= dma
->setMemoryDescriptor(md1
, true); 
 700                 assert(kIOReturnSuccess 
== ret
); 
 701                 time 
= mach_absolute_time() - start
; 
 703                 absolutetime_to_nanoseconds(time
, &nano
); 
 704                 kprintf("time %lld us\n", nano 
/ 1000ULL); 
 707                 IODMACommand::Segment32 segments
[1]; 
 708                 UInt32                  numSegments 
= 1; 
 712                 ret 
= dma
->gen32IOVMSegments(&offset
, &segments
[0], &numSegments
); 
 713                 assert(kIOReturnSuccess 
== ret
); 
 714                 assert(1 == numSegments
); 
 715                 kprintf("seg0 0x%x, 0x%x\n", (int)segments
[0].fIOVMAddr
, (int)segments
[0].fLength
); 
 717                 ret 
= dma
->clearMemoryDescriptor(true); 
 718                 assert(kIOReturnSuccess 
== ret
); 
 722                 return kIOReturnSuccess
; 
 726                 IOBufferMemoryDescriptor 
* md1
; 
 727                 IOBufferMemoryDescriptor 
* md2
; 
 734                 md1 
= IOBufferMemoryDescriptor::inTaskWithOptions(TASK_NULL
, 
 735                     kIODirectionOutIn 
| kIOMemoryPersistent 
| kIOMemoryPageable
, 
 736                     64 * 1024, page_size
); 
 738                 map1 
= md1
->createMappingInTask(kernel_task
, 0, kIOMapAnywhere 
| kIOMapUnique
); 
 740                 buf1 
= (uint32_t *) map1
->getVirtualAddress(); 
 742                 md2 
= IOBufferMemoryDescriptor::inTaskWithOptions(TASK_NULL
, 
 743                     kIODirectionOutIn 
| kIOMemoryPersistent 
| kIOMemoryPageable
, 
 744                     64 * 1024, page_size
); 
 746                 map2 
= md2
->createMappingInTask(kernel_task
, 0, kIOMapAnywhere 
| kIOMapUnique
); 
 748                 buf2 
= (uint32_t *) map2
->getVirtualAddress(); 
 750                 memset(buf1
, 0x11, 64 * 1024L); 
 751                 memset(buf2
, 0x22, 64 * 1024L); 
 753                 kprintf("md1 %p, map1 %p, buf2 %p; md2 %p, map2 %p, buf2 %p\n", md1
, map1
, buf1
, md2
, map2
, buf2
); 
 755                 kprintf("no redir 0x%08x, 0x%08x\n", buf1
[0], buf2
[0]); 
 756                 assert(0x11111111 == buf1
[0]); 
 757                 assert(0x22222222 == buf2
[0]); 
 758                 err 
= map1
->redirect(md2
, 0, 0ULL); 
 759                 kprintf("redir md2(0x%x) 0x%08x, 0x%08x\n", err
, buf1
[0], buf2
[0]); 
 760                 assert(0x11111111 == buf2
[0]); 
 761                 assert(0x22222222 == buf1
[0]); 
 762                 err 
= map1
->redirect(md1
, 0, 0ULL); 
 763                 kprintf("redir md1(0x%x) 0x%08x, 0x%08x\n", err
, buf1
[0], buf2
[0]); 
 764                 assert(0x11111111 == buf1
[0]); 
 765                 assert(0x22222222 == buf2
[0]); 
 773 //    result = IODMACommandLocalMappedNonContig(newValue); 
 774 //    if (result) return (result); 
 776         result 
= IODMACommandForceDoubleBufferTest(newValue
); 
 781         result 
= AllocationNameTest(newValue
); 
 786         result 
= IOMemoryMapCopyOnWriteTest(newValue
); 
 791         result 
= IOMultMemoryDescriptorTest(newValue
); 
 796         result 
= ZeroLengthTest(newValue
); 
 801         result 
= IODirectionPrepareNoZeroFillTest(newValue
); 
 806         result 
= BadFixedAllocTest(newValue
); 
 811         result 
= IOMemoryRemoteTest(newValue
); 
 816         result 
= IOMemoryPrefaultTest(newValue
); 
 821         IOGeneralMemoryDescriptor 
* md
; 
 823         vm_size_t  bsize 
= 16 * 1024 * 1024; 
 824         vm_size_t  srcsize
, srcoffset
, mapoffset
, size
; 
 827         data
[0] = data
[1] = 0; 
 828         kr 
= vm_allocate_kernel(kernel_map
, &data
[0], bsize
, VM_FLAGS_ANYWHERE
, VM_KERN_MEMORY_IOKIT
); 
 829         assert(KERN_SUCCESS 
== kr
); 
 831         vm_inherit(kernel_map
, data
[0] + ptoa(1), ptoa(1), VM_INHERIT_NONE
); 
 832         vm_inherit(kernel_map
, data
[0] + ptoa(16), ptoa(4), VM_INHERIT_NONE
); 
 834         IOLog("data 0x%lx, 0x%lx\n", (long)data
[0], (long)data
[1]); 
 836         uint32_t idx
, offidx
; 
 837         for (idx 
= 0; idx 
< (bsize 
/ sizeof(uint32_t)); idx
++) { 
 838                 ((uint32_t*)data
[0])[idx
] = idx
; 
 841         for (srcoffset 
= 0; srcoffset 
< bsize
; srcoffset 
= ((srcoffset 
<< 2) + 0x40c)) { 
 842                 for (srcsize 
= 4; srcsize 
< (bsize 
- srcoffset 
- 1); srcsize 
= ((srcsize 
<< 2) + 0x3fc)) { 
 843                         IOAddressRange ranges
[3]; 
 844                         uint32_t rangeCount 
= 1; 
 846                         bzero(&ranges
[0], sizeof(ranges
)); 
 847                         ranges
[0].address 
= data
[0] + srcoffset
; 
 848                         ranges
[0].length  
= srcsize
; 
 849                         ranges
[1].address 
= ranges
[2].address 
= data
[0]; 
 851                         if (srcsize 
> ptoa(5)) { 
 852                                 ranges
[0].length  
= 7634; 
 853                                 ranges
[1].length  
= 9870; 
 854                                 ranges
[2].length  
= srcsize 
- ranges
[0].length 
- ranges
[1].length
; 
 855                                 ranges
[1].address 
= ranges
[0].address 
+ ranges
[0].length
; 
 856                                 ranges
[2].address 
= ranges
[1].address 
+ ranges
[1].length
; 
 858                         } else if ((srcsize 
> ptoa(2)) && !(page_mask 
& srcoffset
)) { 
 859                                 ranges
[0].length  
= ptoa(1); 
 860                                 ranges
[1].length  
= ptoa(1); 
 861                                 ranges
[2].length  
= srcsize 
- ranges
[0].length 
- ranges
[1].length
; 
 862                                 ranges
[0].address 
= data
[0] + srcoffset 
+ ptoa(1); 
 863                                 ranges
[1].address 
= data
[0] + srcoffset
; 
 864                                 ranges
[2].address 
= ranges
[0].address 
+ ranges
[0].length
; 
 868                         md 
= OSDynamicCast(IOGeneralMemoryDescriptor
, 
 869                             IOMemoryDescriptor::withAddressRanges(&ranges
[0], rangeCount
, kIODirectionInOut
, kernel_task
)); 
 872                         IOLog("IOMemoryDescriptor::withAddressRanges [0x%lx @ 0x%lx]\n[0x%llx, 0x%llx],\n[0x%llx, 0x%llx],\n[0x%llx, 0x%llx]\n", 
 873                             (long) srcsize
, (long) srcoffset
, 
 874                             (long long) ranges
[0].address 
- data
[0], (long long) ranges
[0].length
, 
 875                             (long long) ranges
[1].address 
- data
[0], (long long) ranges
[1].length
, 
 876                             (long long) ranges
[2].address 
- data
[0], (long long) ranges
[2].length
); 
 878                         if (kIOReturnSuccess 
== kr
) { 
 879                                 for (mapoffset 
= 0; mapoffset 
< srcsize
; mapoffset 
= ((mapoffset 
<< 1) + 0xf00)) { 
 880                                         for (size 
= 4; size 
< (srcsize 
- mapoffset 
- 1); size 
= ((size 
<< 2) + 0x200)) { 
 882                                                 mach_vm_address_t addr 
= 0; 
 885 //                      IOLog("<mapRef [0x%lx @ 0x%lx]\n", (long) size, (long) mapoffset); 
 887                                                 map 
= md
->createMappingInTask(kernel_task
, 0, kIOMapAnywhere
, mapoffset
, size
); 
 889                                                         addr 
= map
->getAddress(); 
 894 //                      IOLog(">mapRef 0x%x %llx\n", kr, addr); 
 896                                                 if (kIOReturnSuccess 
!= kr
) { 
 900                                                 if (kIOReturnSuccess 
!= kr
) { 
 901                                                         panic("prepare() fail 0x%x\n", kr
); 
 904                                                 for (idx 
= 0; idx 
< size
; idx 
+= sizeof(uint32_t)) { 
 905                                                         offidx 
= (idx 
+ mapoffset 
+ srcoffset
); 
 906                                                         if ((srcsize 
<= ptoa(5)) && (srcsize 
> ptoa(2)) && !(page_mask 
& srcoffset
)) { 
 907                                                                 if (offidx 
< ptoa(2)) { 
 911                                                         offidx 
/= sizeof(uint32_t); 
 913                                                         if (offidx 
!= ((uint32_t*)addr
)[idx 
/ sizeof(uint32_t)]) { 
 914                                                                 panic("vm mismatch md %p map %p, @ 0x%x, 0x%lx, 0x%lx, \n", md
, map
, idx
, (long) srcoffset
, (long) mapoffset
); 
 915                                                                 kr 
= kIOReturnBadMedia
; 
 917                                                                 if (sizeof(data
) != md
->readBytes(mapoffset 
+ idx
, &data
, sizeof(data
))) { 
 920                                                                 if (offidx 
!= data
) { 
 921                                                                         panic("phys mismatch md %p map %p, @ 0x%x, 0x%lx, 0x%lx, \n", md
, map
, idx
, (long) srcoffset
, (long) mapoffset
); 
 922                                                                         kr 
= kIOReturnBadMedia
; 
 928 //                      IOLog("unmapRef %llx\n", addr); 
 930                                         if (kIOReturnSuccess 
!= kr
) { 
 936                         if (kIOReturnSuccess 
!= kr
) { 
 940                 if (kIOReturnSuccess 
!= kr
) { 
 945         if (kIOReturnSuccess 
!= kr
) { 
 946                 IOLog("FAIL: src 0x%lx @ 0x%lx, map 0x%lx @ 0x%lx\n", 
 947                     (long) srcsize
, (long) srcoffset
, (long) size
, (long) mapoffset
); 
 950         assert(kr 
== kIOReturnSuccess
); 
 952         vm_deallocate(kernel_map
, data
[0], bsize
); 
 953 //    vm_deallocate(kernel_map, data[1], size); 
 955         IOLog("IOMemoryDescriptorTest/ %d\n", (int) gIOMemoryReferenceCount
); 
 960 #endif  /* DEVELOPMENT || DEBUG */