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