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