X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8ad349bb6ed4a0be06e34c92be0d98b92e078db4..813fb2f63a553c957e917ede5f119b021d6ce391:/iokit/Kernel/IOMultiMemoryDescriptor.cpp diff --git a/iokit/Kernel/IOMultiMemoryDescriptor.cpp b/iokit/Kernel/IOMultiMemoryDescriptor.cpp index 9132f518d..13a5a39a6 100644 --- a/iokit/Kernel/IOMultiMemoryDescriptor.cpp +++ b/iokit/Kernel/IOMultiMemoryDescriptor.cpp @@ -1,31 +1,29 @@ /* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the - * License may not be used to create, or enable the creation or - * redistribution of, unlawful or unlicensed copies of an Apple operating - * system, or to circumvent, violate, or enable the circumvention or - * violation of, any terms of an Apple operating system software license - * agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and * limitations under the License. - * - * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include @@ -34,63 +32,6 @@ #define super IOMemoryDescriptor OSDefineMetaClassAndStructors(IOMultiMemoryDescriptor, IOMemoryDescriptor) -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMultiMemoryDescriptor::initWithAddress( - void * /* address */ , - IOByteCount /* withLength */ , - IODirection /* withDirection */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMultiMemoryDescriptor::initWithAddress( - vm_address_t /* address */ , - IOByteCount /* withLength */ , - IODirection /* withDirection */ , - task_t /* withTask */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMultiMemoryDescriptor::initWithPhysicalAddress( - IOPhysicalAddress /* address */ , - IOByteCount /* withLength */ , - IODirection /* withDirection */ ) -{ - return false; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMultiMemoryDescriptor::initWithPhysicalRanges( - IOPhysicalRange * /* ranges */ , - UInt32 /* withCount */ , - IODirection /* withDirection */ , - bool /* asReference */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMultiMemoryDescriptor::initWithRanges( - IOVirtualRange * /* ranges */ , - UInt32 /* withCount */ , - IODirection /* withDirection */ , - task_t /* withTask */ , - bool /* asReference */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IOMultiMemoryDescriptor * IOMultiMemoryDescriptor::withDescriptors( IOMemoryDescriptor ** descriptors, UInt32 withCount, @@ -120,14 +61,14 @@ IOMultiMemoryDescriptor * IOMultiMemoryDescriptor::withDescriptors( return me; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool IOMultiMemoryDescriptor::initWithDescriptors( IOMemoryDescriptor ** descriptors, UInt32 withCount, IODirection withDirection, bool asReference ) { + unsigned index; + IOOptionBits copyFlags; // // Initialize an IOMultiMemoryDescriptor. The "buffer" is made up of several // memory descriptors, that are to be chained end-to-end to make up a single @@ -137,7 +78,6 @@ bool IOMultiMemoryDescriptor::initWithDescriptors( // assert(descriptors); - assert(withCount); // Release existing descriptors, if any if ( _descriptors ) @@ -157,7 +97,10 @@ bool IOMultiMemoryDescriptor::initWithDescriptors( _descriptors = 0; _descriptorsCount = withCount; _descriptorsIsAllocated = asReference ? false : true; - _direction = withDirection; + _flags = withDirection; +#ifndef __LP64__ + _direction = (IODirection) (_flags & kIOMemoryDirectionMask); +#endif /* !__LP64__ */ _length = 0; _mappings = 0; _tag = 0; @@ -176,19 +119,28 @@ bool IOMultiMemoryDescriptor::initWithDescriptors( /* bytes */ withCount * sizeof(IOMemoryDescriptor *) ); } - for ( unsigned index = 0; index < withCount; index++ ) + for ( index = 0; index < withCount; index++ ) { descriptors[index]->retain(); _length += descriptors[index]->getLength(); if ( _tag == 0 ) _tag = descriptors[index]->getTag(); - assert(descriptors[index]->getDirection() == withDirection); + assert(descriptors[index]->getDirection() == + (withDirection & kIOMemoryDirectionMask)); } + enum { kCopyFlags = kIOMemoryBufferPageable }; + copyFlags = 0; + for ( index = 0; index < withCount; index++ ) + { + if (!index) copyFlags = (kCopyFlags & descriptors[index]->_flags); + else if (copyFlags != (kCopyFlags & descriptors[index]->_flags)) break; + } + if (index < withCount) return (false); + _flags |= copyFlags; + return true; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void IOMultiMemoryDescriptor::free() { // @@ -207,8 +159,6 @@ void IOMultiMemoryDescriptor::free() super::free(); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection) { // @@ -225,7 +175,7 @@ IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection) if ( forDirection == kIODirectionNone ) { - forDirection = _direction; + forDirection = getDirection(); } for ( index = 0; index < _descriptorsCount; index++ ) @@ -236,9 +186,9 @@ IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection) if ( status != kIOReturnSuccess ) { - for ( unsigned indexUndo = 0; indexUndo <= index; indexUndo++ ) + for ( unsigned indexUndo = 0; indexUndo < index; indexUndo++ ) { - statusUndo = _descriptors[index]->complete(forDirection); + statusUndo = _descriptors[indexUndo]->complete(forDirection); assert(statusUndo == kIOReturnSuccess); } } @@ -246,8 +196,6 @@ IOReturn IOMultiMemoryDescriptor::prepare(IODirection forDirection) return status; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IOReturn IOMultiMemoryDescriptor::complete(IODirection forDirection) { // @@ -263,7 +211,7 @@ IOReturn IOMultiMemoryDescriptor::complete(IODirection forDirection) if ( forDirection == kIODirectionNone ) { - forDirection = _direction; + forDirection = getDirection(); } for ( unsigned index = 0; index < _descriptorsCount; index++ ) @@ -276,11 +224,9 @@ IOReturn IOMultiMemoryDescriptor::complete(IODirection forDirection) return statusFinal; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment( - IOByteCount offset, - IOByteCount * length ) +addr64_t IOMultiMemoryDescriptor::getPhysicalSegment(IOByteCount offset, + IOByteCount * length, + IOOptionBits options) { // // This method returns the physical address of the byte at the given offset @@ -294,7 +240,7 @@ IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment( { if ( offset < _descriptors[index]->getLength() ) { - return _descriptors[index]->getPhysicalSegment(offset, length); + return _descriptors[index]->getPhysicalSegment(offset, length, options); } offset -= _descriptors[index]->getLength(); } @@ -304,110 +250,147 @@ IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment( return 0; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#include "IOKitKernelInternal.h" -IOPhysicalAddress IOMultiMemoryDescriptor::getSourceSegment( - IOByteCount offset, - IOByteCount * length ) +IOReturn IOMultiMemoryDescriptor::doMap(vm_map_t __addressMap, + IOVirtualAddress * __address, + IOOptionBits options, + IOByteCount __offset, + IOByteCount __length) { - // - // This method returns the physical address of the byte at the given offset - // into the memory, and optionally the length of the physically contiguous - // segment from that offset. - // - - assert(offset <= _length); - - for ( unsigned index = 0; index < _descriptorsCount; index++ ) + IOMemoryMap * mapping = (IOMemoryMap *) *__address; + vm_map_t map = mapping->fAddressMap; + mach_vm_size_t offset = mapping->fOffset; + mach_vm_size_t length = mapping->fLength; + mach_vm_address_t address = mapping->fAddress; + + kern_return_t err; + IOOptionBits subOptions; + mach_vm_size_t mapOffset; + mach_vm_size_t bytesRemaining, chunk; + mach_vm_address_t nextAddress; + IOMemoryDescriptorMapAllocRef ref; + vm_prot_t prot; + + do { - if ( offset < _descriptors[index]->getLength() ) + prot = VM_PROT_READ; + if (!(kIOMapReadOnly & options)) prot |= VM_PROT_WRITE; + + if (kIOMapOverwrite & options) + { + if ((map == kernel_map) && (kIOMemoryBufferPageable & _flags)) + { + map = IOPageableMapForAddress(address); + } + err = KERN_SUCCESS; + } + else + { + ref.map = map; + ref.tag = IOMemoryTag(map); + ref.options = options; + ref.size = length; + ref.prot = prot; + if (options & kIOMapAnywhere) + // vm_map looks for addresses above here, even when VM_FLAGS_ANYWHERE + ref.mapped = 0; + else + ref.mapped = mapping->fAddress; + + if ((ref.map == kernel_map) && (kIOMemoryBufferPageable & _flags)) + err = IOIteratePageableMaps(ref.size, &IOMemoryDescriptorMapAlloc, &ref); + else + err = IOMemoryDescriptorMapAlloc(ref.map, &ref); + + if (KERN_SUCCESS != err) break; + + address = ref.mapped; + mapping->fAddress = address; + } + + mapOffset = offset; + bytesRemaining = length; + nextAddress = address; + assert(mapOffset <= _length); + subOptions = (options & ~kIOMapAnywhere) | kIOMapOverwrite; + + for (unsigned index = 0; bytesRemaining && (index < _descriptorsCount); index++) { - return _descriptors[index]->getSourceSegment(offset, length); + chunk = _descriptors[index]->getLength(); + if (mapOffset >= chunk) + { + mapOffset -= chunk; + continue; + } + chunk -= mapOffset; + if (chunk > bytesRemaining) chunk = bytesRemaining; + IOMemoryMap * subMap; + subMap = _descriptors[index]->createMappingInTask(mapping->fAddressTask, nextAddress, subOptions, mapOffset, chunk ); + if (!subMap) break; + subMap->release(); // kIOMapOverwrite means it will not deallocate + + bytesRemaining -= chunk; + nextAddress += chunk; + mapOffset = 0; } - offset -= _descriptors[index]->getLength(); + if (bytesRemaining) err = kIOReturnUnderrun; } + while (false); - if ( length ) *length = 0; + if (kIOReturnSuccess == err) + { +#if IOTRACKING + IOTrackingAddUser(gIOMapTracking, &mapping->fTracking, mapping->fLength); +#endif + } - return 0; + return (err); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount /* offset */ , - IOByteCount * /* length */ ) +IOReturn IOMultiMemoryDescriptor::setPurgeable( IOOptionBits newState, + IOOptionBits * oldState ) { - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + IOReturn err; + IOOptionBits totalState, state; -IOByteCount IOMultiMemoryDescriptor::readBytes( IOByteCount offset, - void * bytes, - IOByteCount withLength ) -{ - // - // Copies data from the memory descriptor's buffer at the given offset, to - // the specified buffer. Returns the number of bytes copied. - // - - IOByteCount bytesCopied = 0; - unsigned index; - - for ( index = 0; index < _descriptorsCount; index++ ) - { - if ( offset < _descriptors[index]->getLength() ) break; - offset -= _descriptors[index]->getLength(); - } - - for ( ; index < _descriptorsCount && withLength; index++) + totalState = kIOMemoryPurgeableNonVolatile; + err = kIOReturnSuccess; + for (unsigned index = 0; index < _descriptorsCount; index++) { - IOByteCount copy = min(_descriptors[index]->getLength(), withLength); - IOByteCount copied = _descriptors[index]->readBytes(offset,bytes,copy); - - bytesCopied += copied; - if ( copied != copy ) break; - - bytes = ((UInt8 *) bytes) + copied; - withLength -= copied; - offset = 0; + err = _descriptors[index]->setPurgeable(newState, &state); + if (kIOReturnSuccess != err) break; + + if (kIOMemoryPurgeableEmpty == state) totalState = kIOMemoryPurgeableEmpty; + else if (kIOMemoryPurgeableEmpty == totalState) continue; + else if (kIOMemoryPurgeableVolatile == totalState) continue; + else if (kIOMemoryPurgeableVolatile == state) totalState = kIOMemoryPurgeableVolatile; + else totalState = kIOMemoryPurgeableNonVolatile; } + if (oldState) *oldState = totalState; - return bytesCopied; + return (err); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOByteCount IOMultiMemoryDescriptor::writeBytes( IOByteCount offset, - const void * bytes, - IOByteCount withLength ) +IOReturn IOMultiMemoryDescriptor::getPageCounts(IOByteCount * pResidentPageCount, + IOByteCount * pDirtyPageCount) { - // - // Copies data to the memory descriptor's buffer at the given offset, from - // the specified buffer. Returns the number of bytes copied. - // - - IOByteCount bytesCopied = 0; - unsigned index; + IOReturn err; + IOByteCount totalResidentPageCount, totalDirtyPageCount; + IOByteCount residentPageCount, dirtyPageCount; - for ( index = 0; index < _descriptorsCount; index++ ) + err = kIOReturnSuccess; + totalResidentPageCount = totalDirtyPageCount = 0; + for (unsigned index = 0; index < _descriptorsCount; index++) { - if ( offset < _descriptors[index]->getLength() ) break; - offset -= _descriptors[index]->getLength(); + err = _descriptors[index]->getPageCounts(&residentPageCount, &dirtyPageCount); + if (kIOReturnSuccess != err) break; + totalResidentPageCount += residentPageCount; + totalDirtyPageCount += dirtyPageCount; } - for ( ; index < _descriptorsCount && withLength; index++) - { - IOByteCount copy = min(_descriptors[index]->getLength(), withLength); - IOByteCount copied = _descriptors[index]->writeBytes(offset,bytes,copy); - - bytesCopied += copied; - if ( copied != copy ) break; - - bytes = ((UInt8 *) bytes) + copied; - withLength -= copied; - offset = 0; - } + if (pResidentPageCount) *pResidentPageCount = totalResidentPageCount; + if (pDirtyPageCount) *pDirtyPageCount = totalDirtyPageCount; - return bytesCopied; + return (err); }