xref: /xnu-12377.41.6/iokit/IOKit/perfcontrol/IOPerfControl.h (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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