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