1*8d741a5dSApple OSS Distributions /* 2*8d741a5dSApple OSS Distributions * Copyright (c) 2017 Apple Inc. All rights reserved. 3*8d741a5dSApple OSS Distributions */ 4*8d741a5dSApple OSS Distributions 5*8d741a5dSApple OSS Distributions #pragma once 6*8d741a5dSApple OSS Distributions 7*8d741a5dSApple OSS Distributions #ifdef KERNEL_PRIVATE 8*8d741a5dSApple OSS Distributions #ifdef __cplusplus 9*8d741a5dSApple OSS Distributions 10*8d741a5dSApple OSS Distributions #include <IOKit/IOService.h> 11*8d741a5dSApple OSS Distributions #include <stdatomic.h> 12*8d741a5dSApple OSS Distributions #include <kern/bits.h> 13*8d741a5dSApple OSS Distributions #include <libkern/c++/OSPtr.h> 14*8d741a5dSApple OSS Distributions 15*8d741a5dSApple OSS Distributions struct thread_group; 16*8d741a5dSApple OSS Distributions 17*8d741a5dSApple OSS Distributions enum{ 18*8d741a5dSApple OSS Distributions kIOPerfControlClientWorkUntracked = 0, 19*8d741a5dSApple OSS Distributions }; 20*8d741a5dSApple OSS Distributions 21*8d741a5dSApple OSS Distributions /*! 22*8d741a5dSApple OSS Distributions * @class IOPerfControlClient : public OSObject 23*8d741a5dSApple OSS Distributions * @abstract Class which implements an interface allowing device drivers to participate in performance control. 24*8d741a5dSApple OSS Distributions * @discussion TODO 25*8d741a5dSApple OSS Distributions */ 26*8d741a5dSApple OSS Distributions class IOPerfControlClient final : public OSObject 27*8d741a5dSApple OSS Distributions { 28*8d741a5dSApple OSS Distributions OSDeclareDefaultStructors(IOPerfControlClient); 29*8d741a5dSApple OSS Distributions 30*8d741a5dSApple OSS Distributions protected: 31*8d741a5dSApple OSS Distributions virtual bool init(IOService *driver, uint64_t maxWorkCapacity); 32*8d741a5dSApple OSS Distributions virtual void free() APPLE_KEXT_OVERRIDE; 33*8d741a5dSApple OSS Distributions 34*8d741a5dSApple OSS Distributions public: 35*8d741a5dSApple OSS Distributions /*! 36*8d741a5dSApple OSS Distributions * @function copyClient 37*8d741a5dSApple OSS Distributions * @abstract Return a retained reference to a client object, to be released by the driver. It may be 38*8d741a5dSApple OSS Distributions * shared with other drivers in the system. 39*8d741a5dSApple OSS Distributions * @param driver The device driver that will be using this interface. 40*8d741a5dSApple OSS Distributions * @param maxWorkCapacity The maximum number of concurrent work items supported by the device driver. 41*8d741a5dSApple OSS Distributions * @returns An instance of IOPerfControlClient. 42*8d741a5dSApple OSS Distributions */ 43*8d741a5dSApple OSS Distributions static IOPerfControlClient *copyClient(IOService *driver, uint64_t maxWorkCapacity); 44*8d741a5dSApple OSS Distributions 45*8d741a5dSApple OSS Distributions /*! 46*8d741a5dSApple OSS Distributions * @function registerDevice 47*8d741a5dSApple OSS Distributions * @abstract Inform the system that work will be dispatched to a device in the future. 48*8d741a5dSApple OSS Distributions * @discussion The system will do some one-time setup work associated with the device, and may block the 49*8d741a5dSApple OSS Distributions * current thread during the setup. Devices should not be passed to work workSubmit, workSubmitAndBegin, 50*8d741a5dSApple OSS Distributions * workBegin, or workEnd until they have been successfully registered. The unregistration process happens 51*8d741a5dSApple OSS Distributions * automatically when the device object is deallocated. 52*8d741a5dSApple OSS Distributions * @param device The device object. Some platforms require device to be a specific subclass of IOService. 53*8d741a5dSApple OSS Distributions * @returns kIOReturnSuccess or an IOReturn error code 54*8d741a5dSApple OSS Distributions */ 55*8d741a5dSApple OSS Distributions virtual IOReturn registerDevice(IOService *driver, IOService *device); 56*8d741a5dSApple OSS Distributions 57*8d741a5dSApple OSS Distributions /*! 58*8d741a5dSApple OSS Distributions * @function unregisterDevice 59*8d741a5dSApple OSS Distributions * @abstract Inform the system that work will be no longer be dispatched to a device in the future. 60*8d741a5dSApple OSS Distributions * @discussion This call is optional as the unregistration process happens automatically when the device 61*8d741a5dSApple OSS Distributions * object is deallocated. This call may block the current thread and/or acquire locks. It should not be 62*8d741a5dSApple OSS Distributions * called until after all submitted work has been ended using workEnd. 63*8d741a5dSApple OSS Distributions * @param device The device object. Some platforms require device to be a specific subclass of IOService. 64*8d741a5dSApple OSS Distributions */ 65*8d741a5dSApple OSS Distributions virtual void unregisterDevice(IOService *driver, IOService *device); 66*8d741a5dSApple OSS Distributions 67*8d741a5dSApple OSS Distributions /*! 68*8d741a5dSApple OSS Distributions * @struct WorkSubmitArgs 69*8d741a5dSApple OSS Distributions * @discussion Drivers may submit additional device-specific arguments related to the submission of a work item 70*8d741a5dSApple OSS Distributions * by passing a struct with WorkSubmitArgs as its first member. Note: Drivers are responsible for publishing 71*8d741a5dSApple OSS Distributions * a header file describing these arguments. 72*8d741a5dSApple OSS Distributions */ 73*8d741a5dSApple OSS Distributions struct WorkSubmitArgs { 74*8d741a5dSApple OSS Distributions uint32_t version; 75*8d741a5dSApple OSS Distributions uint32_t size; 76*8d741a5dSApple OSS Distributions uint64_t submit_time; 77*8d741a5dSApple OSS Distributions uint64_t reserved[4]; 78*8d741a5dSApple OSS Distributions void *driver_data; 79*8d741a5dSApple OSS Distributions }; 80*8d741a5dSApple OSS Distributions 81*8d741a5dSApple OSS Distributions /*! 82*8d741a5dSApple OSS Distributions * @function workSubmit 83*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that work was submitted. 84*8d741a5dSApple OSS Distributions * @param device The device that will execute the work. Some platforms require device to be a 85*8d741a5dSApple OSS Distributions * specific subclass of IOService. 86*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments related to the submission of this work item. 87*8d741a5dSApple OSS Distributions * @returns A token representing this work item, which must be passed to workEnd when the work is finished 88*8d741a5dSApple OSS Distributions * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks 89*8d741a5dSApple OSS Distributions * and a degradation of system performance. 90*8d741a5dSApple OSS Distributions */ 91*8d741a5dSApple OSS Distributions virtual uint64_t workSubmit(IOService *device, WorkSubmitArgs *args = nullptr); 92*8d741a5dSApple OSS Distributions 93*8d741a5dSApple OSS Distributions /*! 94*8d741a5dSApple OSS Distributions * @struct WorkBeginArgs 95*8d741a5dSApple OSS Distributions * @discussion Drivers may submit additional device-specific arguments related to the start of a work item 96*8d741a5dSApple OSS Distributions * by passing a struct with WorkBeginArgs as its first member. Note: Drivers are responsible for publishing 97*8d741a5dSApple OSS Distributions * a header file describing these arguments. 98*8d741a5dSApple OSS Distributions */ 99*8d741a5dSApple OSS Distributions struct WorkBeginArgs { 100*8d741a5dSApple OSS Distributions uint32_t version; 101*8d741a5dSApple OSS Distributions uint32_t size; 102*8d741a5dSApple OSS Distributions uint64_t begin_time; 103*8d741a5dSApple OSS Distributions uint64_t reserved[4]; 104*8d741a5dSApple OSS Distributions void *driver_data; 105*8d741a5dSApple OSS Distributions }; 106*8d741a5dSApple OSS Distributions 107*8d741a5dSApple OSS Distributions /*! 108*8d741a5dSApple OSS Distributions * @function workSubmitAndBegin 109*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that work was submitted and immediately began executing. 110*8d741a5dSApple OSS Distributions * @param device The device that is executing the work. Some platforms require device to be a 111*8d741a5dSApple OSS Distributions * specific subclass of IOService. 112*8d741a5dSApple OSS Distributions * @param submitArgs Optional device-specific arguments related to the submission of this work item. 113*8d741a5dSApple OSS Distributions * @param beginArgs Optional device-specific arguments related to the start of this work item. 114*8d741a5dSApple OSS Distributions * @returns A token representing this work item, which must be passed to workEnd when the work is finished 115*8d741a5dSApple OSS Distributions * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks 116*8d741a5dSApple OSS Distributions * and a degradation of system performance. 117*8d741a5dSApple OSS Distributions */ 118*8d741a5dSApple OSS Distributions virtual uint64_t workSubmitAndBegin(IOService *device, WorkSubmitArgs *submitArgs = nullptr, 119*8d741a5dSApple OSS Distributions WorkBeginArgs *beginArgs = nullptr); 120*8d741a5dSApple OSS Distributions 121*8d741a5dSApple OSS Distributions /*! 122*8d741a5dSApple OSS Distributions * @function workBegin 123*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that previously submitted work began executing. 124*8d741a5dSApple OSS Distributions * @param device The device that is executing the work. Some platforms require device to be a 125*8d741a5dSApple OSS Distributions * specific subclass of IOService. 126*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments related to the start of this work item. 127*8d741a5dSApple OSS Distributions */ 128*8d741a5dSApple OSS Distributions virtual void workBegin(IOService *device, uint64_t token, WorkBeginArgs *args = nullptr); 129*8d741a5dSApple OSS Distributions 130*8d741a5dSApple OSS Distributions /*! 131*8d741a5dSApple OSS Distributions * @struct WorkEndArgs 132*8d741a5dSApple OSS Distributions * @discussion Drivers may submit additional device-specific arguments related to the end of a work item 133*8d741a5dSApple OSS Distributions * by passing a struct with WorkEndArgs as its first member. Note: Drivers are responsible for publishing 134*8d741a5dSApple OSS Distributions * a header file describing these arguments. 135*8d741a5dSApple OSS Distributions */ 136*8d741a5dSApple OSS Distributions struct WorkEndArgs { 137*8d741a5dSApple OSS Distributions uint32_t version; 138*8d741a5dSApple OSS Distributions uint32_t size; 139*8d741a5dSApple OSS Distributions uint64_t end_time; 140*8d741a5dSApple OSS Distributions uint64_t reserved[4]; 141*8d741a5dSApple OSS Distributions void *driver_data; 142*8d741a5dSApple OSS Distributions }; 143*8d741a5dSApple OSS Distributions 144*8d741a5dSApple OSS Distributions /*! 145*8d741a5dSApple OSS Distributions * @function workEnd 146*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that previously started work finished executing. 147*8d741a5dSApple OSS Distributions * @param device The device that executed the work. Some platforms require device to be a 148*8d741a5dSApple OSS Distributions * specific subclass of IOService. 149*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments related to the end of this work item. 150*8d741a5dSApple OSS Distributions * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for 151*8d741a5dSApple OSS Distributions * calling workBegin when the work resumes and workEnd with done set to True when it has completed. A workEnd() call 152*8d741a5dSApple OSS Distributions * without a corresponding workBegin() call is a way to cancel a work item and return token to IOPerfControl. 153*8d741a5dSApple OSS Distributions */ 154*8d741a5dSApple OSS Distributions virtual void workEnd(IOService *device, uint64_t token, WorkEndArgs *args = nullptr, bool done = true); 155*8d741a5dSApple OSS Distributions 156*8d741a5dSApple OSS Distributions /*! 157*8d741a5dSApple OSS Distributions * @function copyWorkContext 158*8d741a5dSApple OSS Distributions * @abstract Return a retained reference to an opaque OSObject, to be released by the driver. This object can 159*8d741a5dSApple OSS Distributions * be used by IOPerfControl to track a work item. This may perform dynamic memory allocation. 160*8d741a5dSApple OSS Distributions * @returns A pointer to an OSObject 161*8d741a5dSApple OSS Distributions */ 162*8d741a5dSApple OSS Distributions OSPtr<OSObject> copyWorkContext(); 163*8d741a5dSApple OSS Distributions 164*8d741a5dSApple OSS Distributions /*! 165*8d741a5dSApple OSS Distributions * @function workSubmitAndBeginWithContext 166*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that work was submitted and immediately began executing 167*8d741a5dSApple OSS Distributions * @param device The device that is executing the work. Some platforms require device to be a 168*8d741a5dSApple OSS Distributions * specific subclass of IOService. 169*8d741a5dSApple OSS Distributions * @param context An OSObject returned by copyWorkContext(). The context object will be used by IOPerfControl to track 170*8d741a5dSApple OSS Distributions * this work item. 171*8d741a5dSApple OSS Distributions * @param submitArgs Optional device-specific arguments related to the submission of this work item. 172*8d741a5dSApple OSS Distributions * @param beginArgs Optional device-specific arguments related to the start of this work item. 173*8d741a5dSApple OSS Distributions * @returns true if IOPerfControl is tracking this work item, else false. 174*8d741a5dSApple OSS Distributions * @note The workEndWithContext() call is optional if the corresponding workSubmitWithContext() call returned false. 175*8d741a5dSApple OSS Distributions */ 176*8d741a5dSApple OSS Distributions bool workSubmitAndBeginWithContext(IOService *device, OSObject *context, WorkSubmitArgs *submitArgs = nullptr, 177*8d741a5dSApple OSS Distributions WorkBeginArgs *beginArgs = nullptr); 178*8d741a5dSApple OSS Distributions 179*8d741a5dSApple OSS Distributions /*! 180*8d741a5dSApple OSS Distributions * @function workSubmitWithContext 181*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that work was submitted. 182*8d741a5dSApple OSS Distributions * @param device The device that will execute the work. Some platforms require device to be a 183*8d741a5dSApple OSS Distributions * specific subclass of IOService. 184*8d741a5dSApple OSS Distributions * @param context An OSObject returned by copyWorkContext(). The context object will be used by IOPerfControl to track 185*8d741a5dSApple OSS Distributions * this work item. 186*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments related to the submission of this work item. 187*8d741a5dSApple OSS Distributions * @returns true if IOPerfControl is tracking this work item, else false. 188*8d741a5dSApple OSS Distributions */ 189*8d741a5dSApple OSS Distributions bool workSubmitWithContext(IOService *device, OSObject *context, WorkSubmitArgs *args = nullptr); 190*8d741a5dSApple OSS Distributions 191*8d741a5dSApple OSS Distributions /*! 192*8d741a5dSApple OSS Distributions * @function workBeginWithContext 193*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that previously submitted work began executing. 194*8d741a5dSApple OSS Distributions * @param device The device that is executing the work. Some platforms require device to be a 195*8d741a5dSApple OSS Distributions * specific subclass of IOService. 196*8d741a5dSApple OSS Distributions * @param context An OSObject returned by copyWorkContext() and provided to the previous call to workSubmitWithContext(). 197*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments related to the start of this work item. 198*8d741a5dSApple OSS Distributions * @note The workBeginWithContext() and workEndWithContext() calls are optional if the corresponding workSubmitWithContext() call returned false. 199*8d741a5dSApple OSS Distributions */ 200*8d741a5dSApple OSS Distributions void workBeginWithContext(IOService *device, OSObject *context, WorkBeginArgs *args = nullptr); 201*8d741a5dSApple OSS Distributions 202*8d741a5dSApple OSS Distributions /*! 203*8d741a5dSApple OSS Distributions * @function workEndWithContext 204*8d741a5dSApple OSS Distributions * @abstract Tell the performance controller that previously started work finished executing. 205*8d741a5dSApple OSS Distributions * @param device The device that executed the work. Some platforms require device to be a 206*8d741a5dSApple OSS Distributions * specific subclass of IOService. 207*8d741a5dSApple OSS Distributions * @param context An OSObject returned by copyWorkContext() and provided to the previous call to workSubmitWithContext(). 208*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments related to the end of this work item. 209*8d741a5dSApple OSS Distributions * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for 210*8d741a5dSApple OSS Distributions * calling workBegin when the work resumes and workEnd with done set to True when it has completed. 211*8d741a5dSApple OSS Distributions * @note The workEndWithContext() call is optional if the corresponding workSubmitWithContext() call returned false. A workEndWithContext() 212*8d741a5dSApple OSS Distributions * call without a corresponding workBeginWithContext() call is a way to cancel a work item. 213*8d741a5dSApple OSS Distributions */ 214*8d741a5dSApple OSS Distributions void workEndWithContext(IOService *device, OSObject *context, WorkEndArgs *args = nullptr, bool done = true); 215*8d741a5dSApple OSS Distributions 216*8d741a5dSApple OSS Distributions /*! 217*8d741a5dSApple OSS Distributions * @struct WorkUpdateArgs 218*8d741a5dSApple OSS Distributions * @discussion Drivers may submit additional device-specific arguments related to a work item by passing a 219*8d741a5dSApple OSS Distributions * struct with WorkUpdateArgs as its first member. Note: Drivers are responsible for publishing 220*8d741a5dSApple OSS Distributions * a header file describing these arguments. 221*8d741a5dSApple OSS Distributions */ 222*8d741a5dSApple OSS Distributions struct WorkUpdateArgs { 223*8d741a5dSApple OSS Distributions uint32_t version; 224*8d741a5dSApple OSS Distributions uint32_t size; 225*8d741a5dSApple OSS Distributions uint64_t update_time; 226*8d741a5dSApple OSS Distributions uint64_t reserved[4]; 227*8d741a5dSApple OSS Distributions void *driver_data; 228*8d741a5dSApple OSS Distributions }; 229*8d741a5dSApple OSS Distributions 230*8d741a5dSApple OSS Distributions /*! 231*8d741a5dSApple OSS Distributions * @function workUpdateWithContext 232*8d741a5dSApple OSS Distributions * @abstract Provide and receive additional information from the performance controller. If this call is 233*8d741a5dSApple OSS Distributions * made at all, it should be between workSubmit and workEnd. The purpose and implementation of this call are 234*8d741a5dSApple OSS Distributions * device specific, and may do nothing on some devices. 235*8d741a5dSApple OSS Distributions * @param device The device that submitted the work. Some platforms require device to be a 236*8d741a5dSApple OSS Distributions * specific subclass of IOService. 237*8d741a5dSApple OSS Distributions * @param context An OSObject returned by copyWorkContext() and provided to the previous call to workSubmitWithContext(). 238*8d741a5dSApple OSS Distributions * @param args Optional device-specific arguments. 239*8d741a5dSApple OSS Distributions */ 240*8d741a5dSApple OSS Distributions void workUpdateWithContext(IOService *device, OSObject *context, WorkUpdateArgs *args = nullptr); 241*8d741a5dSApple OSS Distributions 242*8d741a5dSApple OSS Distributions /* 243*8d741a5dSApple OSS Distributions * Callers should always use the CURRENT version so that the kernel can detect both older 244*8d741a5dSApple OSS Distributions * and newer structure layouts. New callbacks should always be added at the end of the 245*8d741a5dSApple OSS Distributions * structure, and xnu should expect existing source recompiled against newer headers 246*8d741a5dSApple OSS Distributions * to pass NULL for unimplemented callbacks. 247*8d741a5dSApple OSS Distributions */ 248*8d741a5dSApple OSS Distributions 249*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_NONE (0) /* no interface */ 250*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_1 (1) /* up-to workEnd */ 251*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_2 (2) /* up-to workUpdate */ 252*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_3 (3) /* up-to (un)registerDriverDevice */ 253*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_4 (4) /* up-to workEndWithResources */ 254*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_CURRENT PERFCONTROL_INTERFACE_VERSION_4 255*8d741a5dSApple OSS Distributions 256*8d741a5dSApple OSS Distributions /*! 257*8d741a5dSApple OSS Distributions * @struct PerfControllerInterface 258*8d741a5dSApple OSS Distributions * @discussion Function pointers necessary to register a performance controller. Not for general driver use. 259*8d741a5dSApple OSS Distributions */ 260*8d741a5dSApple OSS Distributions struct PerfControllerInterface { 261*8d741a5dSApple OSS Distributions enum struct PerfDeviceID : uint32_t{ 262*8d741a5dSApple OSS Distributions kInvalid = 0, 263*8d741a5dSApple OSS Distributions kCPU = 0, 264*8d741a5dSApple OSS Distributions kANE = 0x4, 265*8d741a5dSApple OSS Distributions kGPU, 266*8d741a5dSApple OSS Distributions kMSR, 267*8d741a5dSApple OSS Distributions kStorage, 268*8d741a5dSApple OSS Distributions }; 269*8d741a5dSApple OSS Distributions 270*8d741a5dSApple OSS Distributions struct DriverState { 271*8d741a5dSApple OSS Distributions uint32_t has_target_thread_group : 1; 272*8d741a5dSApple OSS Distributions uint32_t has_device_info : 1; 273*8d741a5dSApple OSS Distributions uint32_t reserved : 30; 274*8d741a5dSApple OSS Distributions 275*8d741a5dSApple OSS Distributions uint64_t target_thread_group_id; 276*8d741a5dSApple OSS Distributions void *target_thread_group_data; 277*8d741a5dSApple OSS Distributions 278*8d741a5dSApple OSS Distributions PerfDeviceID device_type; 279*8d741a5dSApple OSS Distributions uint32_t instance_id; 280*8d741a5dSApple OSS Distributions bool resource_accounting; 281*8d741a5dSApple OSS Distributions }; 282*8d741a5dSApple OSS Distributions 283*8d741a5dSApple OSS Distributions struct WorkState { 284*8d741a5dSApple OSS Distributions uint64_t thread_group_id; 285*8d741a5dSApple OSS Distributions void *thread_group_data; 286*8d741a5dSApple OSS Distributions void *work_data; 287*8d741a5dSApple OSS Distributions uint32_t work_data_size; 288*8d741a5dSApple OSS Distributions uint32_t started : 1; 289*8d741a5dSApple OSS Distributions uint32_t reserved : 31; 290*8d741a5dSApple OSS Distributions const DriverState* driver_state; 291*8d741a5dSApple OSS Distributions }; 292*8d741a5dSApple OSS Distributions 293*8d741a5dSApple OSS Distributions struct ResourceAccounting { 294*8d741a5dSApple OSS Distributions uint64_t mach_time_delta; 295*8d741a5dSApple OSS Distributions uint64_t energy_nj_delta; 296*8d741a5dSApple OSS Distributions }; 297*8d741a5dSApple OSS Distributions 298*8d741a5dSApple OSS Distributions using RegisterDeviceFunction = IOReturn (*)(IOService *); 299*8d741a5dSApple OSS Distributions using RegisterDriverDeviceFunction = IOReturn (*)(IOService *, IOService *, DriverState *); 300*8d741a5dSApple OSS Distributions using WorkCanSubmitFunction = bool (*)(IOService *, WorkState *, WorkSubmitArgs *); 301*8d741a5dSApple OSS Distributions using WorkSubmitFunction = void (*)(IOService *, uint64_t, WorkState *, WorkSubmitArgs *); 302*8d741a5dSApple OSS Distributions using WorkBeginFunction = void (*)(IOService *, uint64_t, WorkState *, WorkBeginArgs *); 303*8d741a5dSApple OSS Distributions using WorkEndFunction = void (*)(IOService *, uint64_t, WorkState *, WorkEndArgs *, bool); 304*8d741a5dSApple OSS Distributions using WorkEndWithResourcesFunction = void (*)(IOService *, uint64_t, WorkState *, WorkEndArgs *, ResourceAccounting *, bool); 305*8d741a5dSApple OSS Distributions using WorkUpdateFunction = void (*)(IOService *, uint64_t, WorkState *, WorkUpdateArgs *); 306*8d741a5dSApple OSS Distributions 307*8d741a5dSApple OSS Distributions uint64_t version; 308*8d741a5dSApple OSS Distributions RegisterDeviceFunction registerDevice; 309*8d741a5dSApple OSS Distributions RegisterDeviceFunction unregisterDevice; 310*8d741a5dSApple OSS Distributions WorkCanSubmitFunction workCanSubmit; 311*8d741a5dSApple OSS Distributions WorkSubmitFunction workSubmit; 312*8d741a5dSApple OSS Distributions WorkBeginFunction workBegin; 313*8d741a5dSApple OSS Distributions WorkEndFunction workEnd; 314*8d741a5dSApple OSS Distributions WorkUpdateFunction workUpdate; 315*8d741a5dSApple OSS Distributions RegisterDriverDeviceFunction registerDriverDevice; 316*8d741a5dSApple OSS Distributions RegisterDriverDeviceFunction unregisterDriverDevice; 317*8d741a5dSApple OSS Distributions WorkEndWithResourcesFunction workEndWithResources; 318*8d741a5dSApple OSS Distributions }; 319*8d741a5dSApple OSS Distributions 320*8d741a5dSApple OSS Distributions struct IOPerfControlClientShared { 321*8d741a5dSApple OSS Distributions atomic_uint_fast8_t maxDriverIndex; 322*8d741a5dSApple OSS Distributions PerfControllerInterface interface; 323*8d741a5dSApple OSS Distributions IOLock *interfaceLock; 324*8d741a5dSApple OSS Distributions OSSet *deviceRegistrationList; 325*8d741a5dSApple OSS Distributions }; 326*8d741a5dSApple OSS Distributions 327*8d741a5dSApple OSS Distributions struct IOPerfControlClientData { 328*8d741a5dSApple OSS Distributions struct thread_group *target_thread_group; 329*8d741a5dSApple OSS Distributions PerfControllerInterface::DriverState driverState; 330*8d741a5dSApple OSS Distributions IOService* device; 331*8d741a5dSApple OSS Distributions }; 332*8d741a5dSApple OSS Distributions /*! 333*8d741a5dSApple OSS Distributions * @function registerPerformanceController 334*8d741a5dSApple OSS Distributions * @abstract Register a performance controller to receive callbacks. Not for general driver use. 335*8d741a5dSApple OSS Distributions * @param interface Struct containing callback functions implemented by the performance controller. 336*8d741a5dSApple OSS Distributions * @returns kIOReturnSuccess or kIOReturnError if the interface was already registered. 337*8d741a5dSApple OSS Distributions */ 338*8d741a5dSApple OSS Distributions virtual IOReturn registerPerformanceController(PerfControllerInterface *interface); 339*8d741a5dSApple OSS Distributions 340*8d741a5dSApple OSS Distributions /*! 341*8d741a5dSApple OSS Distributions * @function getClientData 342*8d741a5dSApple OSS Distributions * @abstract Not for general driver use. Only used by registerPerformanceController(). Allows performanceController to register existing IOPerfControlClient. 343*8d741a5dSApple OSS Distributions * @returns IOPerfControlData associated with a IOPerfControlClient 344*8d741a5dSApple OSS Distributions */ 345*8d741a5dSApple OSS Distributions IOPerfControlClientData * getClientData()346*8d741a5dSApple OSS Distributions getClientData() 347*8d741a5dSApple OSS Distributions { 348*8d741a5dSApple OSS Distributions return &clientData; 349*8d741a5dSApple OSS Distributions } 350*8d741a5dSApple OSS Distributions 351*8d741a5dSApple OSS Distributions private: 352*8d741a5dSApple OSS Distributions struct WorkTableEntry { 353*8d741a5dSApple OSS Distributions struct thread_group *thread_group; 354*8d741a5dSApple OSS Distributions coalition_t coal; 355*8d741a5dSApple OSS Distributions bool started; 356*8d741a5dSApple OSS Distributions uint8_t perfcontrol_data[32]; 357*8d741a5dSApple OSS Distributions }; 358*8d741a5dSApple OSS Distributions 359*8d741a5dSApple OSS Distributions static constexpr size_t kMaxWorkTableNumEntries = 1024; 360*8d741a5dSApple OSS Distributions static constexpr size_t kWorkTableIndexBits = 24; 361*8d741a5dSApple OSS Distributions static constexpr size_t kWorkTableMaxSize = (1 << kWorkTableIndexBits) - 1; // - 1 since 362*8d741a5dSApple OSS Distributions // kIOPerfControlClientWorkUntracked takes number 0 363*8d741a5dSApple OSS Distributions static constexpr size_t kWorkTableIndexMask = (const size_t)mask(kWorkTableIndexBits); 364*8d741a5dSApple OSS Distributions 365*8d741a5dSApple OSS Distributions uint64_t allocateToken(thread_group *thread_group); 366*8d741a5dSApple OSS Distributions void deallocateToken(uint64_t token); 367*8d741a5dSApple OSS Distributions WorkTableEntry *getEntryForToken(uint64_t token); 368*8d741a5dSApple OSS Distributions void markEntryStarted(uint64_t token, bool started); 369*8d741a5dSApple OSS Distributions inline uint64_t tokenToGlobalUniqueToken(uint64_t token); 370*8d741a5dSApple OSS Distributions void accountResources(coalition_t coal, PerfControllerInterface::PerfDeviceID device_type, PerfControllerInterface::ResourceAccounting *resources); 371*8d741a5dSApple OSS Distributions 372*8d741a5dSApple OSS Distributions uint8_t driverIndex; 373*8d741a5dSApple OSS Distributions IOPerfControlClientShared *shared; 374*8d741a5dSApple OSS Distributions WorkTableEntry *workTable; 375*8d741a5dSApple OSS Distributions size_t workTableLength; 376*8d741a5dSApple OSS Distributions size_t workTableNextIndex; 377*8d741a5dSApple OSS Distributions IOSimpleLock *workTableLock; 378*8d741a5dSApple OSS Distributions 379*8d741a5dSApple OSS Distributions IOPerfControlClientData clientData; 380*8d741a5dSApple OSS Distributions }; 381*8d741a5dSApple OSS Distributions 382*8d741a5dSApple OSS Distributions #endif /* __cplusplus */ 383*8d741a5dSApple OSS Distributions #endif /* KERNEL_PRIVATE */ 384