]> git.saurik.com Git - apple/xnu.git/blob - osfmk/pmc/pmc.h
xnu-2050.9.2.tar.gz
[apple/xnu.git] / osfmk / pmc / pmc.h
1 /*
2 * Copyright (c) 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef _MACH_PMC_H_
25 #define _MACH_PMC_H_
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 #include <stdint.h>
32 #include <kern/queue.h>
33 #include <mach/boolean.h>
34 #include <mach/mach_time.h>
35 #include <mach/mach_types.h>
36
37 /****************************************************************************
38 * The four main object types
39 *
40 * 1. Performance monitors (perf_monitor_t) - represent the hardware that
41 * encapsulates a set of performance counters
42 * 2. Performance Counters (pmc_t) - represents each individual counter
43 * 3. Performance Counter Configs (pmc_config_t) - represents the settings
44 * applied to a performance counter (e.g., what to count)
45 * 4. Performance Counter Reservations (pmc_reservation_t) - represents a config along
46 * with it's saved counter value, and the context underwhich it will count.
47 *
48 ****************************************************************************/
49
50 /*
51 * The following objects are in-kernel stand-ins for objects that will be implemented
52 * in the driver kexts. They are generally instances of C++ objects. We make opaque
53 * handles for each distinct type for a little bit of type safety when used from the
54 * kernel layer. These objects are not to be introspected by the kernel at any time,
55 * only used as arguments in the registered driver methods.
56 */
57
58 // IOPerformanceMonitor instances
59 typedef void * perf_monitor_object_t;
60
61 // IOPerformanceCounter instances
62 typedef void * pmc_object_t;
63
64 // IOPerformanceCounterConfig instances
65 typedef void * pmc_config_object_t;
66
67 // END Kext-implemented objects
68
69 // Forward declations
70 struct pmc_reservation;
71 typedef struct pmc_reservation *pmc_reservation_t;
72
73 struct pmc_config;
74 typedef struct pmc_config *pmc_config_t;
75
76 /****************************************************************************
77 * Method types for performance monitor driver registration
78 *
79 * Driver registration happens with no intervention from the driver writers -
80 * it is handled automatically by the IOProfileFamily kext. Registration
81 * happens whenever any IOPerformanceMonitor subclass attaches to the registry.
82 * Failure to successfully register with the kernel will prevent successful attachment
83 * to the IORegistry (this way only usable PMCs and Perf Monitors will be shown.)
84 ****************************************************************************/
85
86 typedef kern_return_t (*perfmon_get_accessible_cores_method_t)(pmc_object_t pmc, uint32_t **cores, size_t *coreCt);
87
88 /*!typedef
89 * @abstract A pointer to a method that enables a set of counters.
90 * @discussion Implementations of this method type must be safe to call at interrupt context.
91 * @param pmcs An array of pmc_object_t instances (non-NULL).
92 * @param pmcCount The number of elements in the @pmcs array.
93 * @result KERN_SUCCESS upon successful global enable of the given counters (may return IOKit error codes).
94 */
95 typedef kern_return_t (*perfmon_enable_counters_method_t)(perf_monitor_object_t pm, pmc_object_t *pmcs, uint32_t pmcCount);
96
97 /*!typedef
98 * @abstract A pointer to a method that disables a set of counters.
99 * @discussion Implementations of this method type must be safe to call at interrupt context.
100 * See <link>perfmon_enable_counters_method_t</link>
101 * @result See <link>perfmon_enable_counters_method_t</link>
102 */
103 typedef kern_return_t (*perfmon_disable_counters_method_t)(perf_monitor_object_t pm, pmc_object_t *pmcs, uint32_t pmcCount);
104
105 typedef void (*perfmon_on_idle_method_t)(perf_monitor_object_t pm);
106 typedef void (*perfmon_on_idle_exit_method_t)(perf_monitor_object_t pm);
107
108 #define MACH_PERFMON_METHODS_VERSION 1
109
110 #define PERFMON_FLAG_SUPPORTS_CONTEXT_SWITCHING 0x1
111 #define PERFMON_FLAG_REQUIRES_IDLE_NOTIFICATIONS 0x2
112 #define PERFMON_FLAG_ALWAYS_ACTIVE 0x4
113
114 /*!struct perf_monitor_methods
115 * @abstract A set of method pointers to be used when interacting with a performance monitor object
116 * @discussion This structure is the set of driver-implemented callback methods to be used when
117 * interacting with a new performance monitor from the kernel.
118 */
119 typedef struct perf_monitor_methods {
120 uint32_t perf_monitor_methods_version; // Always set to MACH_PERFMON_METHODS_VERSION when writing driver kexts
121
122 uint32_t flags;
123
124 perfmon_get_accessible_cores_method_t accessible_cores;
125
126 perfmon_enable_counters_method_t enable_counters;
127 perfmon_disable_counters_method_t disable_counters;
128
129 perfmon_on_idle_method_t on_idle;
130 perfmon_on_idle_exit_method_t on_idle_exit;
131 } perf_monitor_methods_t;
132
133 /****************************************************************************
134 * Method types for performance counter registration
135 *
136 * Registration of individual Performance Counters happens after the
137 * encapsulating Performance Monitor has been registered. This, too, happens
138 * with no intervention of driver-writers. It happens automatically whenever
139 * any IOPerformanceCounter subclass attaches to IORegistry. Failure to register
140 * with the kernel will prevent the IOPerformanceCounter instance from attaching
141 * to IORegistry.
142 ****************************************************************************/
143
144 /*!typedef
145 * @abstract A pointer to a method that creates a configuration object for a counter
146 * @discussion Configuration objects create and hold the hardware representation for a set of driver-defined key-value pairs.
147 * Corresponds to IOPerformanceCounter::createConfiguration() method.
148 * @param pmc A valid pmc object
149 * @result NULL on failure, or a pmc_config_t on success.
150 */
151 typedef pmc_config_object_t (*pmc_create_config_method_t)(pmc_object_t pmc);
152
153 /*!typedef
154 * @abstract A pointer to a method to free a configuration object for a pmc
155 * @discussion Method should free a pmc config object created with a pmc_create_config_method_t above
156 * @param pmc The pmc object used to create the config
157 * @param config The config object to release
158 */
159 typedef void (*pmc_free_config_method_t)(pmc_object_t pmc, pmc_config_object_t config);
160
161 /*!typedef
162 * @abstract A pointer to a method to set a key-value pair on a config object.
163 * @discussion Configuration objects take key-value pairs for setting various bits in the pmc configs
164 * Corresponds to IOPerformanceCounterConfiguration::setValueForId() method.
165 * @param config Pointer to config object.
166 * @param id 8-bit integer ID (determined by the driver).
167 * @param value 64-bit integer value (interpretted by the driver).
168 * @result KERN_SUCCESS on success, KERN_FAILURE on bad value, KERN_INVALID_ARGUMENT on bad id
169 */
170 typedef kern_return_t (*pmc_config_set_value_method_t)(pmc_config_object_t config, uint8_t id, uint64_t value);
171
172 /*!typedef
173 * @abstract A pointer to a method that will be called when a Performance Counter causes a PMI interrupt
174 * @discussion Implementations of this method type must be safe to call at interrupt context.
175 * @param target The pmc_reservation_t that caused the interrupt
176 * @param refCon Any value as defined by the end-user who called <link>pmc_config_set_interrupt_threshold</link>
177 */
178 typedef void (*pmc_interrupt_method_t)(void *target, void *refCon);
179
180 /*!typedef
181 * @abstract A pointer to a method that will set the counter PMI threshold.
182 * @param config A configuration object
183 * @param threshold The number of events after which to cause an interrupt
184 * callback.
185 */
186 typedef kern_return_t (*pmc_config_set_interrupt_threshold_method_t)(pmc_config_object_t config, uint64_t threshold);
187
188 /*!typedef
189 * @abstract A pointer to a method that will set the method to be called when the counter threshold is reached.
190 * @param config A configuration object.
191 * @param target A reference pointer used as the first argument to the callback method.
192 * @param method A pointer to the method to be called.
193 * @param refCon A reference pointer to be used as the second argument to the callback method (may be NULL).
194 */
195 typedef kern_return_t (*pmc_config_set_interrupt_threshold_handler_method_t)(pmc_config_object_t config, void *target, pmc_interrupt_method_t method, void *refCon);
196
197 /*!typedef
198 * @abstract A pointer to a method that will configure a pmc's control registers according to the given configuration object.
199 * @discussion Implementations of this method type must be safe to call at interrupt context.
200 * @param pmc The pmc reference object.
201 * @param config A configuration object.
202 */
203 typedef kern_return_t (*pmc_set_config_method_t)(pmc_object_t pmc, pmc_config_object_t config);
204
205 /*!typedef
206 * @abstract A pointer to a method that returns the Performance Monitor Object for a counter
207 * @discussion A pointer to a method that returns the Performance Monitor Object for a counter.
208 * Implementations of this method type must be safe to call at interrupt context.
209 * Corresponds to IOPerformanceCounter::getMonitor() method.
210 * @param pmc A valid pmc object
211 * @result NULL on failure, or a perf_monitor_object_t on success.
212 */
213 typedef perf_monitor_object_t (*pmc_get_monitor_method_t)(pmc_object_t pmc);
214
215 /*!typedef
216 * @abstract A pointer to a method that returns the registered name of the PMC.
217 * @discussion A pointer to a method that returns the registered name of the PMC.
218 * Corresponds to IOPerformanceCounter::getRegisteredName() method.
219 *
220 * NOTE: Driver authors must not allocate or copy the string during this method:
221 * it may be called from interrupt context or with spin locks held.
222 *
223 * @param pmc A valid pmc object.
224 * @result NULL on failure, or a pointer to the registered name of the pmc.
225 */
226 typedef const char *(*pmc_get_name_method_t)(pmc_object_t pmc);
227
228 /*!typedef
229 * @abstract A pointer to a method that returns if a pmc is accessible from a given logical core.
230 * @discussion A pointer to a method that returns if a pmc is accessible from a given logical core.
231 * Implementations of this method type must be safe to call at interrupt context.
232 * @param pmc A valid pmc object.
233 * @param core The logical core number.
234 * @result TRUE if the pmc can be read in the execution context of the given logical core, FALSE otherwise.
235 */
236 typedef boolean_t (*pmc_is_accessible_from_logical_core_method_t)(pmc_object_t pmc, uint32_t core);
237
238 /*!typedef
239 * @abstract A pointer to a method that returns an array of the logical cores from which a PMC can be accessed.
240 * @discussion A pointer to a method that returns an array of the logical cores from which a PMC can be accessed.
241 * Resulting array of cores should not be released by xnu.
242 * Implementations of this method type must be safe to call at interrupt context.
243 * @param pmc A valid pmc object
244 * @param cores A value-returned array of logical cores that can access the given PMC.
245 * @param coreCt A value-return count of the number of entries in the @cores array.
246 * @result KERN_SUCCESS on success, KERN_FAILURE otherwise.
247 */
248 typedef kern_return_t (*pmc_get_accessible_cores_method_t)(pmc_object_t pmc, uint32_t **cores, size_t *coreCt);
249
250 /*!typedef
251 * @abstract A pointer to a method that attempts to read the count from the given counter hardware.
252 * @discussion Implementations of this method type must be safe to call from interrupt context. * @param pmc The counter from which to read
253 * @param value Storage for the counter's hardware value.
254 */
255 typedef kern_return_t (*pmc_get_count_method_t)(pmc_object_t pmc, uint64_t *value);
256
257 /*!typedef
258 * @abstract A pointer to a method that attempts to write the count to the given counter hardware.
259 * @discussion Implementations of this method type must be safe to call from interrupt context.
260 * @param pmc The counter to which to write.
261 * @param value The value to write to the hardware.
262 */
263 typedef kern_return_t (*pmc_set_count_method_t)(pmc_object_t pmc, uint64_t value);
264
265
266 /*!typedef
267 * @abstract A pointer to a method that disables the counter hardware for a given PMC.
268 * @discussion A pointer to a method that disables the counter hardware for
269 * a given PMC.
270 * Implementations of this method type must be safe to call at interrupt context.
271 * @param pmc A valid pmc object.
272 * @result KERN_SUCCESS on successful disable
273 */
274 typedef kern_return_t (*pmc_disable_method_t)(pmc_object_t pmc);
275
276 /*!typedef
277 * @abstract A pointer to a method that enables the counter hardware for a given PMC.
278 * @discussion A pointer to a method that enables the counter hardware for a given PMC.
279 * Implementations of this method type must be safe to call at interrupt context.
280 * @param pmc A valid pmc object.
281 * @result KERN_SUCCESS on successful enable
282 */
283 typedef kern_return_t (*pmc_enable_method_t)(pmc_object_t pmc);
284
285 typedef kern_return_t (*pmc_open_method_t)(pmc_object_t pmc, void *object);
286 typedef kern_return_t (*pmc_close_method_t)(pmc_object_t pmc, void *object);
287
288 #define MACH_PMC_METHODS_VERSION 0
289
290 /*!
291 * @struct pmc_methods
292 * @abstract Performance Counter Registration methods.
293 * @discussion This structure represents a set of driver-implemented methods to be used by the kernel
294 * when interacting with the associated performance counter. Since a Performance Monitor may
295 * implement any number of distinct types of Performance Counters, each counter registers with
296 * its own set of callback methods.
297 */
298 typedef struct pmc_methods {
299 uint32_t pmc_methods_version; // Always set to MACH_PMC_METHODS_VERSION in your driver.
300
301 // All methods are required.
302 pmc_create_config_method_t create_config;
303 pmc_free_config_method_t free_config;
304 pmc_config_set_value_method_t config_set_value;
305 pmc_config_set_interrupt_threshold_method_t config_set_threshold;
306 pmc_config_set_interrupt_threshold_handler_method_t config_set_handler;
307 pmc_set_config_method_t set_config;
308
309 pmc_get_monitor_method_t get_monitor;
310 pmc_get_name_method_t get_name;
311 pmc_is_accessible_from_logical_core_method_t accessible_from_core;
312 pmc_get_accessible_cores_method_t accessible_cores;
313 pmc_get_count_method_t get_count;
314 pmc_set_count_method_t set_count;
315 pmc_disable_method_t disable;
316 pmc_enable_method_t enable;
317 pmc_open_method_t open;
318 pmc_close_method_t close;
319 } pmc_methods_t;
320
321 /*
322 * Kext interface Methods
323 *
324 * These methods would be exported to apple-internal kexts, but not to 3rd-party kexts, and
325 * definitely not to user space.
326 *
327 * All Performance Monitor and Performance Counter registration (accomplished via the following methods)
328 * is handled automatically via IOProfileFamily's base classes. However, we'd need to export these
329 * methods to apple-private KPI so that IOProfileFamily can call these methods when new objects attach
330 * to the IORegistry.
331 *
332 */
333
334 /*!fn
335 * @abstract Registers a new performance monitor driver and its associated pointers.
336 * @discussion Kexts that implement performance monitor drivers will call this method with a
337 * filled-in perf_monitor_methods_t structure (with version set to MACH_PERFMON_METHODS_VERSION).
338 * The PMC interface will then register the new driver internally.
339 * @param monitor A handle to the performance monitor driver instance you are registering. Must not be NULL.
340 * @param methods A filled-in perf_monitor_methods_t structure with version set to MACH_PERFMON_METHODS_VERSION.
341 * @result KERN_SUCCESS if the new driver was successfully registered, KERN_INVALID_VALUE if the
342 * version of the passed-in perf_monitor_methods_t structure does not match that which is expected,
343 * KERN_RESOURCE_SHORTAGE if the kernel lacks the resources to register another performance monitor
344 * driver, KERN_INVALID_ARGUMENT if one or both of the arguments is null
345 */
346 kern_return_t perf_monitor_register(perf_monitor_object_t monitor, perf_monitor_methods_t *methods);
347
348 /*!fn
349 * @abstract Unregisters a performance monitor driver and frees space associated with its pointers.
350 * @discussion Kexts that implement performance monitor drivers will call this method just before they unload
351 * to cause the performance monitor they implement to be removed from the kernel's PMC system.
352 * @param monitor A handle to a performance monitor driver instance that was previously registered with <link>perf_monitor_register</link>
353 * @result KERN_SUCCESS if the new driver was successfully unregistered, KERN_INVALID_VALUE if the
354 * passed-in perf_monitor_object_t does not match any registered performance monitor, KERN_INVALID_ARGUMENT if
355 * the argument is null, KERN_FAILURE if the performance monitor is currently in use.
356 */
357 kern_return_t perf_monitor_unregister(perf_monitor_object_t monitor);
358
359 /*!fn
360 * @abstract Register a new Performance Counter, and attach it to the given Performance Monitor
361 * @discussion This method takes a Performance Monitor driver instance that was previously registered
362 * with <link>perf_monitor_register</link>, and attaches an instance of a Performance Counter
363 * that will be accessed with the given set of pmc methods.
364 * @param monitor A handle to a Performance Monitor that was previously registered.
365 * @param pmc A handle to the Performance Counter instance to be attached to the monitor object
366 * @param methods A filled-in pmc_methods_t structure with version set to MACH_PMC_METHODS_VERSION
367 * @param object an Object to be used during the open() and close() methods. Must be a subclass of IOService, cannot be NULL.
368 * @result KERN_SUCCESS if the new counter was successfully registered and attached, KERN_INVALID_VALUE if the
369 * version of the passed-in pmc_methods_t structure does not match that which is expected,
370 * KERN_RESOURCE_SHORTAGE if the kernel lacks the resources to register another performance counter
371 * instance, KERN_INVALID_ARGUMENT if any of the arguments is null
372 */
373 kern_return_t pmc_register(perf_monitor_object_t monitor, pmc_object_t pmc,
374 pmc_methods_t *methods, void *object);
375
376 /*!fn
377 * @abstract Unregisters a Performance Counter
378 * @discussion Does the reverse of <link>pmc_register</link>.
379 * @param monitor The registered Performance Monitor from which to remove a pmc.
380 * @param pmc The Performance Counter to unregister.
381 * @result KERN_SUCCESS if the counter was successfully unregistered, KERN_INVALID_VALUE if the
382 * passed-in pmc_object_t does not match any registered performance counter, KERN_INVALID_ARGUMENT if
383 * any argument is null, KERN_FAILURE if the performance counter is currently in use.
384 */
385 kern_return_t pmc_unregister(perf_monitor_object_t monitor, pmc_object_t pmc);
386
387 /*
388 * Here begins the interface in-kernel and in-kext users will use to interact with PMCs and
389 * Performance Monitors.
390 *
391 * Basic usage is as follows: find your target counter, create a config for it, setup the config,
392 * reserve the counter using that config in a given execution context (system, or 1 task, or 1 thread),
393 * start the counter via the reservation object, stop the counter, and read the counter value similarly from the
394 * reservation object. When done, release the reservation object.
395 */
396
397 /*!struct perf_monitor
398 * @abstract In-kernel object to track a driver-implemented performance monitor.
399 */
400 typedef struct perf_monitor {
401 /*
402 * A reference-pointer used as the first argument to all callback methods
403 * (to seamlessly work with C++ objects). This is the same value that was
404 * used in the perf_monitor_register() method.
405 */
406 perf_monitor_object_t object;
407
408 // Copy of the pointers used to interact with the above instance
409 perf_monitor_methods_t methods;
410
411 // reference counted
412 uint32_t useCount;
413
414 uint32_t reservedCounters;
415
416 // A value of -1 here indicates independence from a particular core
417 int cpu;
418
419 // links to other perf monitors
420 queue_chain_t link;
421 queue_chain_t cpu_link;
422 }*perf_monitor_t;
423
424 /*!struct pmc
425 * @abstract In-kernel object to track an individual driver-implemented performance counter
426 */
427 typedef struct pmc {
428 /*
429 * A reference-pointer used as the first argument to all callback methods
430 * (to seamlessly work with C++ objects). This is the same value that was
431 * used in the pmc_register() method.
432 */
433 pmc_object_t object;
434
435 /* Copy of the pointers used to interact with the above instance */
436 pmc_methods_t methods;
437
438 /* Object to be used during open/close methods */
439 void *open_object;
440
441 /* reference counted */
442 uint32_t useCount;
443
444 /* link to parent */
445 perf_monitor_t monitor;
446
447 /* link to other PMCs */
448 queue_chain_t link;
449 }*pmc_t;
450
451 // Scope flags (highest order bits)
452 #define PMC_FLAG_SCOPE_SYSTEM 0x80000000U
453 #define PMC_FLAG_SCOPE_TASK 0x40000000U
454 #define PMC_FLAG_SCOPE_THREAD 0x20000000U
455 #define PMC_SCOPE_MASK 0xE0000000U
456
457 #define PMC_FLAG_IS_SYSTEM_SCOPE(x) \
458 ((x & PMC_FLAG_SCOPE_SYSTEM) == PMC_FLAG_SCOPE_SYSTEM)
459
460 #define PMC_FLAG_IS_TASK_SCOPE(x) \
461 ((x & PMC_FLAG_SCOPE_TASK) == PMC_FLAG_SCOPE_TASK)
462
463 #define PMC_FLAG_IS_THREAD_SCOPE(x) \
464 ((x & PMC_FLAG_SCOPE_THREAD) == PMC_FLAG_SCOPE_THREAD)
465
466 #define PMC_FLAG_SCOPE(x) (x & PMC_SCOPE_MASK)
467
468 /*
469 * Reservation state
470 *
471 * The state of a reservation is actually a 3-tuple of the current state, an active context count,
472 * and a set of modifier flags. To avoid using locks, these are combined into a single uint32_t
473 * that can be modified with OSCompareAndSwap.
474 *
475 */
476
477 typedef uint32_t pmc_state_t;
478
479 #define PMC_STATE_STATE_INVALID 0x00000000U
480 #define PMC_STATE_STATE_STOP 0x10000000U
481 #define PMC_STATE_STATE_CAN_RUN 0x20000000U
482 #define PMC_STATE_STATE_LOAD 0x30000000U
483 #define PMC_STATE_STATE_RUN 0x40000000U
484 #define PMC_STATE_STATE_STORE 0x50000000U
485 #define PMC_STATE_STATE_INTERRUPT 0x60000000U
486 #define PMC_STATE_STATE_DEALLOC 0x70000000U
487
488 #define PMC_STATE_STATE_MASK 0xF0000000U
489
490 #define PMC_STATE_STATE(x) ((x) & PMC_STATE_STATE_MASK)
491 #define PMC_STATE_STATE_SET(x, state) (((x) & ~(PMC_STATE_STATE_MASK)) | state)
492
493 #define PMC_STATE_FLAGS_STOPPING 0x08000000U
494 #define PMC_STATE_FLAGS_DEALLOCING 0x04000000U
495 #define PMC_STATE_FLAGS_INTERRUPTING 0x02000000U
496
497 #define PMC_STATE_FLAGS_MASK 0x0F000000U
498
499 #define PMC_STATE_FLAGS(x) ((x) & PMC_STATE_FLAGS_MASK)
500 #define PMC_STATE_FLAGS_MODIFY(x, set, clear) (((x) & ~(clear)) | set)
501
502 #define PMC_STATE_CONTEXT_COUNT_MASK 0x0000FFFFU
503
504 #define PMC_STATE_CONTEXT_COUNT(x) ((x) & PMC_STATE_CONTEXT_COUNT_MASK)
505 #define PMC_STATE_CONTEXT_COUNT_MODIFY(x, mod) (((PMC_STATE_CONTEXT_COUNT(x) + (mod)) < PMC_STATE_CONTEXT_COUNT_MASK) ? (x) + (mod) : PMC_STATE_CONTEXT_COUNT_MASK)
506
507 #define PMC_STATE(state, context_count, flags) (PMC_STATE_STATE(state) | PMC_STATE_FLAGS(flags) | PMC_STATE_CONTEXT_COUNT(context_count))
508 #define PMC_STATE_MODIFY(x, context_count_mod, flags_set, flags_clear) (PMC_STATE_FLAGS_MODIFY(PMC_STATE_CONTEXT_COUNT_MODIFY(x, context_count_mod), flags_set, flags_clear))
509 #define PMC_STATE_MOVE(x, state, context_count_mod, flags_set, flags_clear) (PMC_STATE_STATE_SET(PMC_STATE_MODIFY(x, context_count_mod, flags_set, flags_clear), state))
510
511 #define PMC_STATE_INVALID PMC_STATE(PMC_STATE_STATE_INVALID, 0, 0)
512
513 /*!struct pmc_reservation
514 * @abstract In-kernel object to track an individual reservation
515 */
516 struct pmc_reservation {
517 pmc_t pmc; // Pointer to in-kernel pmc which is reserved
518 pmc_config_t config; // counter configuration
519
520 // stored counter value
521 uint64_t value;
522
523 // TODO: Add mach-port (user-export object?)
524
525 volatile uint32_t flags __attribute__((aligned(4)));
526 volatile pmc_state_t state __attribute__((aligned(4)));
527 volatile uint32_t active_last_context_in __attribute__((aligned(4)));
528
529 union {
530 task_t task; // not retained
531 thread_t thread; // not retained
532 };
533
534 queue_chain_t link;
535 };
536
537 // END Kernel-objects
538
539
540 // Methods exported to kernel (and kext) consumers
541
542 /*!fn
543 * @abstract Creates a new configuration object for the given pmc.
544 * @discussion This method is not interrupt safe.
545 * @param pmc The Perf Counter for which to create a configuration.
546 * @param config A value-return configuration object.
547 */
548 kern_return_t pmc_create_config(pmc_t pmc, pmc_config_t *config);
549
550 /*!fn
551 * @abstract Releases a configuration object for the given pmc.
552 * @discussion This method is not interrupt safe.
553 * @param pmc The Perf Counter for which to release a configuration.
554 * @param config A configuration object to be released.
555 */
556 void pmc_free_config(pmc_t pmc, pmc_config_t config);
557
558 /*!fn
559 * @abstract Setup the configuration
560 * @discussion Configurations for counter are architecture-neutral key-value pairs (8bit key, 64bit value). Meanings of the keys and values are defined
561 * by the driver-writer and are listed in XML form available for interrogation via the CoreProfile framework. This method is not interrupt safe.
562 * @result KERN_SUCCESS on success.
563 */
564 kern_return_t pmc_config_set_value(pmc_t pmc, pmc_config_t config, uint8_t id, uint64_t value);
565
566 /*!fn
567 * @abstract Interrupt Threshold Setup
568 * @discussion In order to configure a PMC to use PMI (cause an interrupt after so-many events occur), use this method, and provide a function to be
569 * called after the interrupt occurs, along with a reference context. PMC Threshold handler methods will have the pmc that generated the interrupt as
570 * the first argument when the interrupt handler is invoked, and the given @refCon (which may be NULL) as the second. This method is not interrupt safe.
571 */
572 kern_return_t pmc_config_set_interrupt_threshold(pmc_t pmc, pmc_config_t config, uint64_t threshold, pmc_interrupt_method_t method, void *refCon);
573
574 /*!fn
575 * @abstract Returns an allocated list of all pmc_t's known to the kernel.
576 * @discussion Callers should free the resultant list via <link>pmc_free_pmc_list</link>. This method is not interrupt safe.
577 * @param pmcs Storage for the resultant pmc_t array pointer.
578 * @param pmcCount Storage for the resultant count of pmc_t's.
579 */
580 kern_return_t pmc_get_pmc_list(pmc_t **pmcs, size_t *pmcCount);
581
582 /*!fn
583 * @abstract Free a previously allocated list of pmcs.
584 * @discussion This method is not interrupt safe.
585 * @param pmcs PMC list to free.
586 * @param pmcCount Number of pmc_t's in list.
587 */
588 void pmc_free_pmc_list(pmc_t *pmcs, size_t pmcCount);
589
590 /*!fn
591 * @abstract Finds pmcs by partial string matching.
592 * @discussion This method returns a list of pmcs (similar to <link>pmc_get_pmc_list</link>) whose names match the given string up to it's length.
593 * For example, searching for "ia32" would return pmcs "ia32gp0" and "ia32gp1". Results should be released by the caller using <link>pmc_free_pmc_list</link>
594 * @param name Partial string to search for.
595 * @param pmcs Storage for the resultant pmc_t array pointer.
596 * @param pmcCount Storage for the resultant count of pmc_t's.
597 */
598 kern_return_t pmc_find_by_name(const char *name, pmc_t **pmcs, size_t *pmcCount);
599
600 /*!fn
601 * @abstract Returns a pointer to the human-readable name of the given pmc.
602 * @discussion The returned pointer is not a copy, and does not need to be freed. This method is interrupt safe.
603 * @param pmc The PMC whose name should be returned.
604 */
605 const char *pmc_get_name(pmc_t pmc);
606
607 /*!fn
608 * @abstract Returns a list of logical cores from which the given pmc can be read from or written to.
609 * @discussion This method can return a NULL list with count of 0 -- this indicates any core can read the given pmc. This method does not allocate the list,
610 * therefore callers should take care not to mutate or free the resultant list. This method is interrupt safe.
611 * @param pmc The PMC for which to return the cores that can read/write it.
612 * @param logicalCores Storage for the pointer to the list.
613 * @param logicalCoreCt Value-return number of elements in the returned list. 0 indicates all cores can read/write the given pmc.
614 */
615 kern_return_t pmc_get_accessible_core_list(pmc_t pmc, uint32_t **logicalCores, size_t *logicalCoreCt);
616
617 /*
618 * BEGIN PMC Reservations
619 *
620 * These are how you reserve a PMC, start and stop it counting, and read and write
621 * its value.
622 */
623
624 /*!fn
625 * @abstract Reserve a PMC for System-wide counting.
626 * @discussion This method will attempt to reserve the given pmc at system-scope. It will configure the given pmc to count the event indicated by the given
627 * configuration object. This method consumes the given configuration object if the return value is KERN_SUCCESS - any other return value indicates the caller
628 * should free the configuration object via <link>pmc_free_config</link>. This method is not interrupt safe.
629 * @param pmc The PMC to reserve.
630 * @param config The configuration object to use with the given pmc.
631 * @param reservation A value-return reservation object to be used in pmc_reservation_* methods.
632 * @result This method will return one of the following values:
633 * KERN_SUCCESS: The given pmc was successfully reserved in system-scope; the given config object has been consumed and should not be freed by the caller,
634 * KERN_FAILURE: The given pmc is already reserved in a conflicting scope,
635 * KERN_INVALID_ARGUMENT: All three arguments are required to be non-NULL, but at least one is NULL,
636 * KERN_RESOURCE_SHORTAGE: Could not allocate a new reservation object.
637 */
638 kern_return_t pmc_reserve(pmc_t pmc, pmc_config_t config, pmc_reservation_t *reservation);
639
640
641 /*!fn
642 * @abstract Reserve a PMC for task-wide counting.
643 * @discussion This method will attempt to reserve the given pmc for task-wide counting. The resulting reservation will only count when the task is running
644 * on one of the logical cores that can read the given pmc. The semantics of this method are the same as <link>pmc_reserve</link> in all other respects.
645 * @param pmc The PMC to reserve
646 * @param config The configuration object to use.
647 * @param task The task for which to enable the counter.
648 * @param reservation A value-return reservation object.
649 * @result See <link>pmc_reserve</link>
650 */
651 kern_return_t pmc_reserve_task(pmc_t pmc, pmc_config_t config, task_t task, pmc_reservation_t *reservation);
652
653 /*!fn
654 * @abstract Reserve a PMC for thread-wide counting.
655 * @discussion This method will attempt to reserve the given pmc for thread-wide counting. The resulting reservation will only count when the thread is
656 * running on one of the logical cores that can read the given pmc. The semantics of this method are the same as <link>pmc_reserve_task</link> in all other respects.
657 * @param pmc The PMC to reserve
658 * @param config The configuration object to use.
659 * @param thread The thread for which to enable the counter.
660 * @param reservation A value-return reservation object.
661 * @result See <link>pmc_reserve</link>
662 */
663 kern_return_t pmc_reserve_thread(pmc_t pmc, pmc_config_t config, thread_t thread, pmc_reservation_t *reservation);
664
665 /*!fn
666 * @abstract Start counting
667 * @discussion This method instructs the given reservation to start counting as soon as possible. If the reservation is for a thread (or task) other than the
668 * current thread, or for a pmc that is not accessible from the current logical core, the reservation will start counting the next time the thread (or task)
669 * runs on a logical core than can access the pmc. This method is interrupt safe. If this method is called from outside of interrupt context, it may block.
670 * @param reservation The reservation to start counting
671 */
672 kern_return_t pmc_reservation_start(pmc_reservation_t reservation);
673
674 /*!fn
675 * @abstract Stop counting
676 * @discussion This method instructs the given reservation to stop counting as soon as possible. If the reservation is for a thread (or task) other than the
677 * current thread, or for a pmc that is not accessible from the current logical core, the reservation will stop counting the next time the thread (or task) c
678 * eases to run on a logical core than can access the pmc. This method is interrupt safe. If called form outside of interrupt context, this method may block.
679 * @param reservation The reservation to stop counting
680 */
681 kern_return_t pmc_reservation_stop(pmc_reservation_t reservation);
682
683 /*!fn
684 * @abstract Read the counter value
685 * @discussion This method will read the event count associated with the given reservation. If the pmc is currently on hardware, and the caller is currently ]
686 * executing in a context that both a) matches the reservation's context, and b) can access the reservation's pmc directly, the value will be read directly
687 * from the hardware. Otherwise, the value stored in the reservation is returned. This method is interrupt safe. If the caller is calling from outside of
688 * interrupt context, this method may block.
689 * @param reservation The reservation whose value to read.
690 * @param value Value-return event count
691 */
692 kern_return_t pmc_reservation_read(pmc_reservation_t reservation, uint64_t *value);
693
694 /*!fn
695 * @abstract Write the counter value
696 * @discussion This method will write the event count associated with the given reservation. If the pmc is currently on hardware, and the caller is currently
697 * executing in a context that both a) matches the reservation's context, and b) can access the reservation's pmc directly, the value will be written directly
698 * to the hardware. Otherwise, the value stored in the reservation is overwritten. This method is interrupt safe. If the caller is calling from outside of
699 * interrupt context, this method may block.
700 * @param reservation The reservation to write.
701 * @param value The event count to write
702 */
703 kern_return_t pmc_reservation_write(pmc_reservation_t reservation, uint64_t value);
704
705 /*!fn
706 * @abstract Free a reservation and all associated resources.
707 * @discussion This method will free the resources associated with the given reservation and release the associated PMC back to general availability.
708 * If the reservation is currently counting, it will be stopped prior to release. This method is not interrupt safe.
709 * @param reservation The reservation to free
710 */
711 kern_return_t pmc_reservation_free(pmc_reservation_t reservation);
712
713 #if XNU_KERNEL_PRIVATE
714
715 /*!fn
716 * @abstract Brings up all the necessary infrastructure required to use the pmc sub-system.
717 * @discussion For xnu-internal startup routines only.
718 */
719 void pmc_bootstrap(void);
720
721 /*!fn
722 * @abstract Performs a pmc context switch.
723 * @discussion This method will save all PMCs reserved for oldThread (and the task associated with oldThread), as well as restore all PMCs reserved
724 * for newThread (and the task associated with newThread). This method is for xnu-internal context switching routines only.
725 */
726 boolean_t pmc_context_switch(thread_t oldThread, thread_t newThread);
727
728 /*!fn
729 * @abstract Called on per-core idle.
730 * @discussion This method notifies registered performance monitors of impending cpu idle, and can be used to save counter state.
731 */
732 boolean_t pmc_idle(void);
733
734 /*!fn
735 * @abstract Called on per-core wake from idle.
736 * @discussion This method notifies registered performance monitors of wake-up from the prior idle, and can be used to restore
737 * previously saved counter configuration.
738 */
739 boolean_t pmc_idle_exit(void);
740
741 #if defined(THREAD_PMC_FLAG)
742 /* Allow inclusion from outside of MACH_KERNEL_PRIVATE scope. */
743
744 /*!fn
745 * @abstract Returns true if thread has been marked for counting.
746 * @discussion Task-level reservations are propagated to child threads via thread_create_internal. Any mutation of task reservations forces a recalculate
747 * of t_chud (for the pmc flag) for all threads in that task. Consequently, we can simply check the current thread's flag against THREAD_PMC_FLAG.
748 */
749 static inline boolean_t pmc_thread_eligible(thread_t t) {
750 return (t != NULL) ? ((t->t_chud & THREAD_PMC_FLAG) ? TRUE : FALSE) : FALSE;
751 }
752
753 #endif /* THREAD_PMC_FLAG*/
754
755 #endif // XNU_KERNEL_PRIVATE
756
757 #ifdef __cplusplus
758 };
759 #endif
760
761 #endif // _MACH_PMC_H_
762