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