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