1c1dac77fSApple OSS Distributions /* 2a3bb9fccSApple OSS Distributions * Copyright (c) 1998-2014 Apple Inc. All rights reserved. 3c1dac77fSApple OSS Distributions * 4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5c1dac77fSApple OSS Distributions * 6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement. 14c1dac77fSApple OSS Distributions * 15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at 16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17e13b1fa5SApple OSS Distributions * 18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are 19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and 24e13b1fa5SApple OSS Distributions * limitations under the License. 25c1dac77fSApple OSS Distributions * 26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27c1dac77fSApple OSS Distributions */ 28c1dac77fSApple OSS Distributions 29*bb611c8fSApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR 30*bb611c8fSApple OSS Distributions 31*bb611c8fSApple OSS Distributions #include <ptrauth.h> 32c1dac77fSApple OSS Distributions #include <IOKit/IOInterruptEventSource.h> 33855239e5SApple OSS Distributions #include <IOKit/IOKitDebug.h> 34c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h> 35c1dac77fSApple OSS Distributions #include <IOKit/IOService.h> 36c1dac77fSApple OSS Distributions #include <IOKit/IOInterrupts.h> 37c1dac77fSApple OSS Distributions #include <IOKit/IOTimeStamp.h> 38c1dac77fSApple OSS Distributions #include <IOKit/IOWorkLoop.h> 39a3bb9fccSApple OSS Distributions #include <IOKit/IOInterruptAccountingPrivate.h> 40*bb611c8fSApple OSS Distributions #include <libkern/Block_private.h> 41c1dac77fSApple OSS Distributions 42855239e5SApple OSS Distributions #if IOKITSTATS 43c1dac77fSApple OSS Distributions 44855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() \ 45c1dac77fSApple OSS Distributions do { \ 46855239e5SApple OSS Distributions IOStatistics::setCounterType(IOEventSource::reserved->counter, kIOStatisticsInterruptEventSourceCounter); \ 47c1dac77fSApple OSS Distributions } while (0) 48c1dac77fSApple OSS Distributions 49855239e5SApple OSS Distributions #define IOStatisticsCheckForWork() \ 50c1dac77fSApple OSS Distributions do { \ 51855239e5SApple OSS Distributions IOStatistics::countInterruptCheckForWork(IOEventSource::reserved->counter); \ 52c1dac77fSApple OSS Distributions } while (0) 53c1dac77fSApple OSS Distributions 54855239e5SApple OSS Distributions #define IOStatisticsInterrupt() \ 55c1dac77fSApple OSS Distributions do { \ 56855239e5SApple OSS Distributions IOStatistics::countInterrupt(IOEventSource::reserved->counter); \ 57c1dac77fSApple OSS Distributions } while (0) 58c1dac77fSApple OSS Distributions 59855239e5SApple OSS Distributions #else 60855239e5SApple OSS Distributions 61855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() 62855239e5SApple OSS Distributions #define IOStatisticsCheckForWork() 63855239e5SApple OSS Distributions #define IOStatisticsInterrupt() 64855239e5SApple OSS Distributions 65855239e5SApple OSS Distributions #endif // IOKITSTATS 66c1dac77fSApple OSS Distributions 67c1dac77fSApple OSS Distributions #define super IOEventSource 68c1dac77fSApple OSS Distributions 69c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOInterruptEventSource, IOEventSource) 70c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 0); 71c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 1); 72c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 2); 73c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 3); 74c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 4); 75c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 5); 76c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 6); 77c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 7); 78c1dac77fSApple OSS Distributions 79a5e72196SApple OSS Distributions bool 80a5e72196SApple OSS Distributions IOInterruptEventSource::init(OSObject *inOwner, 81368ad365SApple OSS Distributions Action inAction, 82368ad365SApple OSS Distributions IOService *inProvider, 83368ad365SApple OSS Distributions int inIntIndex) 84c1dac77fSApple OSS Distributions { 85c1dac77fSApple OSS Distributions bool res = true; 86c1dac77fSApple OSS Distributions 87a5e72196SApple OSS Distributions if (!super::init(inOwner, (IOEventSourceAction) inAction)) { 88c1dac77fSApple OSS Distributions return false; 89a5e72196SApple OSS Distributions } 90c1dac77fSApple OSS Distributions 91a3bb9fccSApple OSS Distributions reserved = IONew(ExpansionData, 1); 92a3bb9fccSApple OSS Distributions 93a3bb9fccSApple OSS Distributions if (!reserved) { 94a3bb9fccSApple OSS Distributions return false; 95a3bb9fccSApple OSS Distributions } 96a3bb9fccSApple OSS Distributions 97a3bb9fccSApple OSS Distributions bzero(reserved, sizeof(ExpansionData)); 98a3bb9fccSApple OSS Distributions 99c1dac77fSApple OSS Distributions provider = inProvider; 100c1dac77fSApple OSS Distributions producerCount = consumerCount = 0; 101c1dac77fSApple OSS Distributions autoDisable = explicitDisable = false; 102855239e5SApple OSS Distributions intIndex = ~inIntIndex; 103c1dac77fSApple OSS Distributions 104c1dac77fSApple OSS Distributions // Assumes inOwner holds a reference(retain) on the provider 105c1dac77fSApple OSS Distributions if (inProvider) { 106a3bb9fccSApple OSS Distributions if (IA_ANY_STATISTICS_ENABLED) { 107a3bb9fccSApple OSS Distributions /* 108a3bb9fccSApple OSS Distributions * We only treat this as an "interrupt" if it has a provider; if it does, 109a3bb9fccSApple OSS Distributions * set up the objects necessary to track interrupt statistics. Interrupt 110a3bb9fccSApple OSS Distributions * event sources without providers are most likely being used as simple 111a3bb9fccSApple OSS Distributions * event source in order to poke at workloops and kick off work. 112a3bb9fccSApple OSS Distributions * 113a3bb9fccSApple OSS Distributions * We also avoid try to avoid interrupt accounting overhead if none of 114a3bb9fccSApple OSS Distributions * the statistics are enabled. 115a3bb9fccSApple OSS Distributions */ 116a3bb9fccSApple OSS Distributions reserved->statistics = IONew(IOInterruptAccountingData, 1); 117a3bb9fccSApple OSS Distributions 118a3bb9fccSApple OSS Distributions if (!reserved->statistics) { 119a3bb9fccSApple OSS Distributions /* 120a3bb9fccSApple OSS Distributions * We rely on the free() routine to clean up after us if init fails 121a3bb9fccSApple OSS Distributions * midway. 122a3bb9fccSApple OSS Distributions */ 123a3bb9fccSApple OSS Distributions return false; 124a3bb9fccSApple OSS Distributions } 125a3bb9fccSApple OSS Distributions 126a3bb9fccSApple OSS Distributions bzero(reserved->statistics, sizeof(IOInterruptAccountingData)); 127a3bb9fccSApple OSS Distributions 128a3bb9fccSApple OSS Distributions reserved->statistics->owner = this; 129a3bb9fccSApple OSS Distributions } 130a3bb9fccSApple OSS Distributions 131855239e5SApple OSS Distributions res = (kIOReturnSuccess == registerInterruptHandler(inProvider, inIntIndex)); 132a3bb9fccSApple OSS Distributions 133a3bb9fccSApple OSS Distributions if (res) { 134855239e5SApple OSS Distributions intIndex = inIntIndex; 135855239e5SApple OSS Distributions } 136a3bb9fccSApple OSS Distributions } 137c1dac77fSApple OSS Distributions 138855239e5SApple OSS Distributions IOStatisticsInitializeCounter(); 139855239e5SApple OSS Distributions 140855239e5SApple OSS Distributions return res; 141855239e5SApple OSS Distributions } 142855239e5SApple OSS Distributions 143a5e72196SApple OSS Distributions IOReturn 144a5e72196SApple OSS Distributions IOInterruptEventSource::registerInterruptHandler(IOService *inProvider, 145855239e5SApple OSS Distributions int inIntIndex) 146855239e5SApple OSS Distributions { 147855239e5SApple OSS Distributions IOReturn ret; 148855239e5SApple OSS Distributions int intType; 149c1dac77fSApple OSS Distributions IOInterruptAction intHandler; 150c1dac77fSApple OSS Distributions 151855239e5SApple OSS Distributions ret = inProvider->getInterruptType(inIntIndex, &intType); 152a5e72196SApple OSS Distributions if (kIOReturnSuccess != ret) { 153a5e72196SApple OSS Distributions return ret; 154a5e72196SApple OSS Distributions } 155855239e5SApple OSS Distributions 156c1dac77fSApple OSS Distributions autoDisable = (intType == kIOInterruptTypeLevel); 157c1dac77fSApple OSS Distributions if (autoDisable) { 15814e3d835SApple OSS Distributions intHandler = OSMemberFunctionCast(IOInterruptAction, 15914e3d835SApple OSS Distributions this, &IOInterruptEventSource::disableInterruptOccurred); 160a5e72196SApple OSS Distributions } else { 16114e3d835SApple OSS Distributions intHandler = OSMemberFunctionCast(IOInterruptAction, 16214e3d835SApple OSS Distributions this, &IOInterruptEventSource::normalInterruptOccurred); 163a5e72196SApple OSS Distributions } 164c1dac77fSApple OSS Distributions 165855239e5SApple OSS Distributions ret = provider->registerInterrupt(inIntIndex, this, intHandler); 166c1dac77fSApple OSS Distributions 167a3bb9fccSApple OSS Distributions /* 168a3bb9fccSApple OSS Distributions * Add statistics to the provider. The setWorkLoop convention should ensure 169a3bb9fccSApple OSS Distributions * that we always go down the unregister path before we register (outside of 170a3bb9fccSApple OSS Distributions * init()), so we don't have to worry that we will invoke addInterruptStatistics 171a3bb9fccSApple OSS Distributions * erroneously. 172a3bb9fccSApple OSS Distributions */ 173a3bb9fccSApple OSS Distributions if ((ret == kIOReturnSuccess) && (reserved->statistics)) { 174a3bb9fccSApple OSS Distributions /* 175a3bb9fccSApple OSS Distributions * Stash the normal index value, for the sake of debugging. 176a3bb9fccSApple OSS Distributions */ 177a3bb9fccSApple OSS Distributions reserved->statistics->interruptIndex = inIntIndex; 178a3bb9fccSApple OSS Distributions 179a3bb9fccSApple OSS Distributions /* 180a3bb9fccSApple OSS Distributions * We need to hook the interrupt information up to the provider so that it 181a3bb9fccSApple OSS Distributions * can find the statistics for this interrupt when desired. The provider is 182a3bb9fccSApple OSS Distributions * responsible for maintaining the reporter for a particular interrupt, and 183a3bb9fccSApple OSS Distributions * needs a handle on the statistics so that it can request that the reporter 184a3bb9fccSApple OSS Distributions * be updated as needed. Errors are considered "soft" for the moment (it 185a3bb9fccSApple OSS Distributions * will either panic, or fail in a way such that we can still service the 186a3bb9fccSApple OSS Distributions * interrupt). 187a3bb9fccSApple OSS Distributions */ 188a3bb9fccSApple OSS Distributions provider->addInterruptStatistics(reserved->statistics, inIntIndex); 189a3bb9fccSApple OSS Distributions 190a3bb9fccSApple OSS Distributions /* 191a3bb9fccSApple OSS Distributions * Add the statistics object to the global list of statistics objects; this 192a3bb9fccSApple OSS Distributions * is an aid to debugging (we can trivially find statistics for all eligible 193a3bb9fccSApple OSS Distributions * interrupts, and dump them; potentially helpful if the system is wedged 194a3bb9fccSApple OSS Distributions * due to interrupt activity). 195a3bb9fccSApple OSS Distributions */ 196a3bb9fccSApple OSS Distributions interruptAccountingDataAddToList(reserved->statistics); 197a3bb9fccSApple OSS Distributions } 198a3bb9fccSApple OSS Distributions 199a5e72196SApple OSS Distributions return ret; 200c1dac77fSApple OSS Distributions } 201c1dac77fSApple OSS Distributions 202a3bb9fccSApple OSS Distributions void 203a3bb9fccSApple OSS Distributions IOInterruptEventSource::unregisterInterruptHandler(IOService *inProvider, 204a3bb9fccSApple OSS Distributions int inIntIndex) 205a3bb9fccSApple OSS Distributions { 206a3bb9fccSApple OSS Distributions if (reserved->statistics) { 207a3bb9fccSApple OSS Distributions interruptAccountingDataRemoveFromList(reserved->statistics); 208a3bb9fccSApple OSS Distributions provider->removeInterruptStatistics(reserved->statistics->interruptIndex); 209a3bb9fccSApple OSS Distributions } 210a3bb9fccSApple OSS Distributions 211a3bb9fccSApple OSS Distributions provider->unregisterInterrupt(inIntIndex); 212a3bb9fccSApple OSS Distributions } 213a3bb9fccSApple OSS Distributions 214a3bb9fccSApple OSS Distributions 215*bb611c8fSApple OSS Distributions OSSharedPtr<IOInterruptEventSource> 216c1dac77fSApple OSS Distributions IOInterruptEventSource::interruptEventSource(OSObject *inOwner, 217c1dac77fSApple OSS Distributions Action inAction, 218c1dac77fSApple OSS Distributions IOService *inProvider, 219c1dac77fSApple OSS Distributions int inIntIndex) 220c1dac77fSApple OSS Distributions { 221*bb611c8fSApple OSS Distributions OSSharedPtr<IOInterruptEventSource> me = OSMakeShared<IOInterruptEventSource>(); 222c1dac77fSApple OSS Distributions 223c1dac77fSApple OSS Distributions if (me && !me->init(inOwner, inAction, inProvider, inIntIndex)) { 224*bb611c8fSApple OSS Distributions return nullptr; 225c1dac77fSApple OSS Distributions } 226c1dac77fSApple OSS Distributions 227c1dac77fSApple OSS Distributions return me; 228c1dac77fSApple OSS Distributions } 229c1dac77fSApple OSS Distributions 230*bb611c8fSApple OSS Distributions OSSharedPtr<IOInterruptEventSource> 231cc9a6355SApple OSS Distributions IOInterruptEventSource::interruptEventSource(OSObject *inOwner, 232cc9a6355SApple OSS Distributions IOService *inProvider, 233cc9a6355SApple OSS Distributions int inIntIndex, 234cc9a6355SApple OSS Distributions ActionBlock inAction) 235cc9a6355SApple OSS Distributions { 236*bb611c8fSApple OSS Distributions OSSharedPtr<IOInterruptEventSource> ies; 237cc9a6355SApple OSS Distributions ies = IOInterruptEventSource::interruptEventSource(inOwner, (Action) NULL, inProvider, inIntIndex); 238a5e72196SApple OSS Distributions if (ies) { 239a5e72196SApple OSS Distributions ies->setActionBlock((IOEventSource::ActionBlock) inAction); 240a5e72196SApple OSS Distributions } 241cc9a6355SApple OSS Distributions 242cc9a6355SApple OSS Distributions return ies; 243cc9a6355SApple OSS Distributions } 244cc9a6355SApple OSS Distributions 245a5e72196SApple OSS Distributions void 246a5e72196SApple OSS Distributions IOInterruptEventSource::free() 247c1dac77fSApple OSS Distributions { 248a5e72196SApple OSS Distributions if (provider && intIndex >= 0) { 249a3bb9fccSApple OSS Distributions unregisterInterruptHandler(provider, intIndex); 250a5e72196SApple OSS Distributions } 251a3bb9fccSApple OSS Distributions 252a3bb9fccSApple OSS Distributions if (reserved) { 253a3bb9fccSApple OSS Distributions if (reserved->statistics) { 254a3bb9fccSApple OSS Distributions IODelete(reserved->statistics, IOInterruptAccountingData, 1); 255a3bb9fccSApple OSS Distributions } 256a3bb9fccSApple OSS Distributions 257a3bb9fccSApple OSS Distributions IODelete(reserved, ExpansionData, 1); 258a3bb9fccSApple OSS Distributions } 259c1dac77fSApple OSS Distributions 260c1dac77fSApple OSS Distributions super::free(); 261c1dac77fSApple OSS Distributions } 262c1dac77fSApple OSS Distributions 263a5e72196SApple OSS Distributions void 264a5e72196SApple OSS Distributions IOInterruptEventSource::enable() 265c1dac77fSApple OSS Distributions { 266855239e5SApple OSS Distributions if (provider && intIndex >= 0) { 267c1dac77fSApple OSS Distributions provider->enableInterrupt(intIndex); 268c1dac77fSApple OSS Distributions explicitDisable = false; 269e13b1fa5SApple OSS Distributions enabled = true; 270c1dac77fSApple OSS Distributions } 271c1dac77fSApple OSS Distributions } 272c1dac77fSApple OSS Distributions 273a5e72196SApple OSS Distributions void 274a5e72196SApple OSS Distributions IOInterruptEventSource::disable() 275c1dac77fSApple OSS Distributions { 276855239e5SApple OSS Distributions if (provider && intIndex >= 0) { 277c1dac77fSApple OSS Distributions provider->disableInterrupt(intIndex); 278c1dac77fSApple OSS Distributions explicitDisable = true; 279e13b1fa5SApple OSS Distributions enabled = false; 280c1dac77fSApple OSS Distributions } 281c1dac77fSApple OSS Distributions } 282c1dac77fSApple OSS Distributions 283a5e72196SApple OSS Distributions void 284a5e72196SApple OSS Distributions IOInterruptEventSource::setWorkLoop(IOWorkLoop *inWorkLoop) 285855239e5SApple OSS Distributions { 286a5e72196SApple OSS Distributions if (inWorkLoop) { 287a5e72196SApple OSS Distributions super::setWorkLoop(inWorkLoop); 288a5e72196SApple OSS Distributions } 289855239e5SApple OSS Distributions 290186b8fceSApple OSS Distributions if (provider) { 291855239e5SApple OSS Distributions if (!inWorkLoop) { 292855239e5SApple OSS Distributions if (intIndex >= 0) { 293a3bb9fccSApple OSS Distributions /* 294a3bb9fccSApple OSS Distributions * It isn't necessarily safe to wait until free() to unregister the interrupt; 295a3bb9fccSApple OSS Distributions * our provider may disappear. 296a3bb9fccSApple OSS Distributions */ 297a3bb9fccSApple OSS Distributions unregisterInterruptHandler(provider, intIndex); 298855239e5SApple OSS Distributions intIndex = ~intIndex; 299855239e5SApple OSS Distributions } 300855239e5SApple OSS Distributions } else if ((intIndex < 0) && (kIOReturnSuccess == registerInterruptHandler(provider, ~intIndex))) { 301855239e5SApple OSS Distributions intIndex = ~intIndex; 302855239e5SApple OSS Distributions } 303855239e5SApple OSS Distributions } 304855239e5SApple OSS Distributions 305a5e72196SApple OSS Distributions if (!inWorkLoop) { 306a5e72196SApple OSS Distributions super::setWorkLoop(inWorkLoop); 307a5e72196SApple OSS Distributions } 308186b8fceSApple OSS Distributions } 309186b8fceSApple OSS Distributions 310a5e72196SApple OSS Distributions const IOService * 311a5e72196SApple OSS Distributions IOInterruptEventSource::getProvider() const 312c1dac77fSApple OSS Distributions { 313c1dac77fSApple OSS Distributions return provider; 314c1dac77fSApple OSS Distributions } 315c1dac77fSApple OSS Distributions 316a5e72196SApple OSS Distributions int 317a5e72196SApple OSS Distributions IOInterruptEventSource::getIntIndex() const 318c1dac77fSApple OSS Distributions { 319c1dac77fSApple OSS Distributions return intIndex; 320c1dac77fSApple OSS Distributions } 321c1dac77fSApple OSS Distributions 322a5e72196SApple OSS Distributions bool 323a5e72196SApple OSS Distributions IOInterruptEventSource::getAutoDisable() const 324c1dac77fSApple OSS Distributions { 325c1dac77fSApple OSS Distributions return autoDisable; 326c1dac77fSApple OSS Distributions } 327c1dac77fSApple OSS Distributions 328a5e72196SApple OSS Distributions bool 329a5e72196SApple OSS Distributions IOInterruptEventSource::checkForWork() 330c1dac77fSApple OSS Distributions { 331a3bb9fccSApple OSS Distributions uint64_t startSystemTime = 0; 332a3bb9fccSApple OSS Distributions uint64_t endSystemTime = 0; 333a3bb9fccSApple OSS Distributions uint64_t startCPUTime = 0; 334a3bb9fccSApple OSS Distributions uint64_t endCPUTime = 0; 335c1dac77fSApple OSS Distributions unsigned int cacheProdCount = producerCount; 336c1dac77fSApple OSS Distributions int numInts = cacheProdCount - consumerCount; 337*bb611c8fSApple OSS Distributions IOEventSource::Action intAction = action; 338cc9a6355SApple OSS Distributions ActionBlock intActionBlock = (ActionBlock) actionBlock; 339*bb611c8fSApple OSS Distributions void *address; 340855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false; 341c1dac77fSApple OSS Distributions 342*bb611c8fSApple OSS Distributions if (kActionBlock & flags) { 343*bb611c8fSApple OSS Distributions address = ptrauth_nop_cast(void *, _Block_get_invoke_fn((struct Block_layout *)intActionBlock)); 344*bb611c8fSApple OSS Distributions } else { 345*bb611c8fSApple OSS Distributions address = ptrauth_nop_cast(void *, intAction); 346*bb611c8fSApple OSS Distributions } 347*bb611c8fSApple OSS Distributions 348855239e5SApple OSS Distributions IOStatisticsCheckForWork(); 349c1dac77fSApple OSS Distributions 350a5e72196SApple OSS Distributions if (numInts > 0) { 351a5e72196SApple OSS Distributions if (trace) { 352855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION), 353*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(address), 354*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(owner), 35576e12aa3SApple OSS Distributions VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop)); 356a5e72196SApple OSS Distributions } 357855239e5SApple OSS Distributions 358a3bb9fccSApple OSS Distributions if (reserved->statistics) { 359a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 360a3bb9fccSApple OSS Distributions startSystemTime = mach_absolute_time(); 361a3bb9fccSApple OSS Distributions } 362a3bb9fccSApple OSS Distributions 363a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 364a3bb9fccSApple OSS Distributions startCPUTime = thread_get_runtime_self(); 365a3bb9fccSApple OSS Distributions } 366a3bb9fccSApple OSS Distributions } 367a3bb9fccSApple OSS Distributions 368855239e5SApple OSS Distributions // Call the handler 369a5e72196SApple OSS Distributions if (kActionBlock & flags) { 370a5e72196SApple OSS Distributions (intActionBlock)(this, numInts); 371a5e72196SApple OSS Distributions } else { 372*bb611c8fSApple OSS Distributions ((IOInterruptEventAction)intAction)(owner, this, numInts); 373a5e72196SApple OSS Distributions } 374855239e5SApple OSS Distributions 375a3bb9fccSApple OSS Distributions if (reserved->statistics) { 376a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) { 377a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1); 378a3bb9fccSApple OSS Distributions } 379a3bb9fccSApple OSS Distributions 380a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 381a3bb9fccSApple OSS Distributions endCPUTime = thread_get_runtime_self(); 382a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime); 383a3bb9fccSApple OSS Distributions } 384a3bb9fccSApple OSS Distributions 385a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 386a3bb9fccSApple OSS Distributions endSystemTime = mach_absolute_time(); 387a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime); 388a3bb9fccSApple OSS Distributions } 389a3bb9fccSApple OSS Distributions } 390a3bb9fccSApple OSS Distributions 391a5e72196SApple OSS Distributions if (trace) { 392855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION), 393*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(address), 394*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(owner), 39576e12aa3SApple OSS Distributions VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop)); 396c1dac77fSApple OSS Distributions } 397855239e5SApple OSS Distributions 398a5e72196SApple OSS Distributions consumerCount = cacheProdCount; 399a5e72196SApple OSS Distributions if (autoDisable && !explicitDisable) { 400a5e72196SApple OSS Distributions enable(); 401a5e72196SApple OSS Distributions } 402a5e72196SApple OSS Distributions } else if (numInts < 0) { 403a5e72196SApple OSS Distributions if (trace) { 404855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION), 405*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(address), 406*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(owner), 40776e12aa3SApple OSS Distributions VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop)); 408a5e72196SApple OSS Distributions } 409855239e5SApple OSS Distributions 410a3bb9fccSApple OSS Distributions if (reserved->statistics) { 411a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 412a3bb9fccSApple OSS Distributions startSystemTime = mach_absolute_time(); 413a3bb9fccSApple OSS Distributions } 414a3bb9fccSApple OSS Distributions 415a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 416a3bb9fccSApple OSS Distributions startCPUTime = thread_get_runtime_self(); 417a3bb9fccSApple OSS Distributions } 418a3bb9fccSApple OSS Distributions } 419a3bb9fccSApple OSS Distributions 420855239e5SApple OSS Distributions // Call the handler 421a5e72196SApple OSS Distributions if (kActionBlock & flags) { 422a5e72196SApple OSS Distributions (intActionBlock)(this, numInts); 423a5e72196SApple OSS Distributions } else { 424*bb611c8fSApple OSS Distributions ((IOInterruptEventAction)intAction)(owner, this, numInts); 425a5e72196SApple OSS Distributions } 426855239e5SApple OSS Distributions 427a3bb9fccSApple OSS Distributions if (reserved->statistics) { 428a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) { 429a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1); 430a3bb9fccSApple OSS Distributions } 431a3bb9fccSApple OSS Distributions 432a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 433a3bb9fccSApple OSS Distributions endCPUTime = thread_get_runtime_self(); 434a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime); 435a3bb9fccSApple OSS Distributions } 436a3bb9fccSApple OSS Distributions 437a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 438a3bb9fccSApple OSS Distributions endSystemTime = mach_absolute_time(); 439a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime); 440a3bb9fccSApple OSS Distributions } 441a3bb9fccSApple OSS Distributions } 442a3bb9fccSApple OSS Distributions 443a5e72196SApple OSS Distributions if (trace) { 444855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION), 445*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(address), 446*bb611c8fSApple OSS Distributions VM_KERNEL_ADDRHIDE(owner), 44776e12aa3SApple OSS Distributions VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop)); 448a5e72196SApple OSS Distributions } 449c1dac77fSApple OSS Distributions 450c1dac77fSApple OSS Distributions consumerCount = cacheProdCount; 451a5e72196SApple OSS Distributions if (autoDisable && !explicitDisable) { 452c1dac77fSApple OSS Distributions enable(); 453c1dac77fSApple OSS Distributions } 454a5e72196SApple OSS Distributions } 455c1dac77fSApple OSS Distributions 456c1dac77fSApple OSS Distributions return false; 457c1dac77fSApple OSS Distributions } 458c1dac77fSApple OSS Distributions 459a5e72196SApple OSS Distributions void 460a5e72196SApple OSS Distributions IOInterruptEventSource::normalInterruptOccurred 461c1dac77fSApple OSS Distributions (void */*refcon*/, IOService */*prov*/, int /*source*/) 462c1dac77fSApple OSS Distributions { 463855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false; 464c1dac77fSApple OSS Distributions 465855239e5SApple OSS Distributions IOStatisticsInterrupt(); 466c1dac77fSApple OSS Distributions producerCount++; 467c1dac77fSApple OSS Distributions 468a5e72196SApple OSS Distributions if (trace) { 46976e12aa3SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner)); 470a5e72196SApple OSS Distributions } 471c1dac77fSApple OSS Distributions 472a3bb9fccSApple OSS Distributions if (reserved->statistics) { 473a5e72196SApple OSS Distributions if (reserved->statistics->enablePrimaryTimestamp) { 474a5e72196SApple OSS Distributions reserved->statistics->primaryTimestamp = mach_absolute_time(); 475a5e72196SApple OSS Distributions } 476a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) { 477a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1); 478a3bb9fccSApple OSS Distributions } 479a3bb9fccSApple OSS Distributions } 480a3bb9fccSApple OSS Distributions 481855239e5SApple OSS Distributions signalWorkAvailable(); 482855239e5SApple OSS Distributions 483a5e72196SApple OSS Distributions if (trace) { 48476e12aa3SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner)); 485c1dac77fSApple OSS Distributions } 486a5e72196SApple OSS Distributions } 487c1dac77fSApple OSS Distributions 488a5e72196SApple OSS Distributions void 489a5e72196SApple OSS Distributions IOInterruptEventSource::disableInterruptOccurred 490c1dac77fSApple OSS Distributions (void */*refcon*/, IOService *prov, int source) 491c1dac77fSApple OSS Distributions { 492855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false; 493c1dac77fSApple OSS Distributions 494c1dac77fSApple OSS Distributions prov->disableInterrupt(source); /* disable the interrupt */ 495c1dac77fSApple OSS Distributions 496855239e5SApple OSS Distributions IOStatisticsInterrupt(); 497c1dac77fSApple OSS Distributions producerCount++; 498c1dac77fSApple OSS Distributions 499a5e72196SApple OSS Distributions if (trace) { 50076e12aa3SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner)); 501a5e72196SApple OSS Distributions } 502c1dac77fSApple OSS Distributions 503a3bb9fccSApple OSS Distributions if (reserved->statistics) { 504a5e72196SApple OSS Distributions if (reserved->statistics->enablePrimaryTimestamp) { 505a5e72196SApple OSS Distributions reserved->statistics->primaryTimestamp = mach_absolute_time(); 506a5e72196SApple OSS Distributions } 507a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) { 508a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1); 509a3bb9fccSApple OSS Distributions } 510a3bb9fccSApple OSS Distributions } 511a3bb9fccSApple OSS Distributions 512855239e5SApple OSS Distributions signalWorkAvailable(); 513855239e5SApple OSS Distributions 514a5e72196SApple OSS Distributions if (trace) { 51576e12aa3SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner)); 516c1dac77fSApple OSS Distributions } 517c1dac77fSApple OSS Distributions } 518855239e5SApple OSS Distributions 519a5e72196SApple OSS Distributions void 520a5e72196SApple OSS Distributions IOInterruptEventSource::interruptOccurred 521a5e72196SApple OSS Distributions (void *_refcon, IOService *prov, int source) 522a5e72196SApple OSS Distributions { 523a5e72196SApple OSS Distributions if (autoDisable && prov) { 524a5e72196SApple OSS Distributions disableInterruptOccurred(_refcon, prov, source); 525a5e72196SApple OSS Distributions } else { 526a5e72196SApple OSS Distributions normalInterruptOccurred(_refcon, prov, source); 527a5e72196SApple OSS Distributions } 528a5e72196SApple OSS Distributions } 529a5e72196SApple OSS Distributions 530a5e72196SApple OSS Distributions IOReturn 531a5e72196SApple OSS Distributions IOInterruptEventSource::warmCPU 532855239e5SApple OSS Distributions (uint64_t abstime) 533855239e5SApple OSS Distributions { 534855239e5SApple OSS Distributions return ml_interrupt_prewarm(abstime); 535855239e5SApple OSS Distributions } 536a5e72196SApple OSS Distributions 537a5e72196SApple OSS Distributions void 538a5e72196SApple OSS Distributions IOInterruptEventSource::enablePrimaryInterruptTimestamp(bool enable) 539a5e72196SApple OSS Distributions { 540a5e72196SApple OSS Distributions if (reserved->statistics) { 541a5e72196SApple OSS Distributions reserved->statistics->enablePrimaryTimestamp = enable; 542a5e72196SApple OSS Distributions } 543a5e72196SApple OSS Distributions } 544a5e72196SApple OSS Distributions 545a5e72196SApple OSS Distributions uint64_t 546*bb611c8fSApple OSS Distributions IOInterruptEventSource::getPrimaryInterruptTimestamp() 547a5e72196SApple OSS Distributions { 548a5e72196SApple OSS Distributions if (reserved->statistics && reserved->statistics->enablePrimaryTimestamp) { 549a5e72196SApple OSS Distributions return reserved->statistics->primaryTimestamp; 550a5e72196SApple OSS Distributions } 551a5e72196SApple OSS Distributions return -1ULL; 552a5e72196SApple OSS Distributions } 553