2 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
32 #include <kern/queue.h>
33 #include <mach/boolean.h>
34 #include <mach/mach_time.h>
35 #include <mach/mach_types.h>
37 #include <libkern/version.h>
39 /****************************************************************************
40 * The four main object types
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.
50 ****************************************************************************/
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.
60 // IOPerformanceMonitor instances
61 typedef void * perf_monitor_object_t
;
63 // IOPerformanceCounter instances
64 typedef void * pmc_object_t
;
66 // IOPerformanceCounterConfig instances
67 typedef void * pmc_config_object_t
;
69 // END Kext-implemented objects
72 struct pmc_reservation
;
73 typedef struct pmc_reservation
*pmc_reservation_t
;
76 typedef struct pmc_config
*pmc_config_t
;
78 /****************************************************************************
79 * Method types for performance monitor driver registration
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 ****************************************************************************/
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.
93 typedef boolean_t (*perfmon_supports_context_switch_method_t
)(perf_monitor_object_t pm
);
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).
102 typedef kern_return_t (*perfmon_enable_counters_method_t
)(perf_monitor_object_t pm
, pmc_object_t
*pmcs
, uint32_t pmcCount
);
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>
110 typedef kern_return_t (*perfmon_disable_counters_method_t
)(perf_monitor_object_t pm
, pmc_object_t
*pmcs
, uint32_t pmcCount
);
112 #define MACH_PERFMON_METHODS_VERSION 0
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.
119 typedef struct perf_monitor_methods
{
120 uint32_t perf_monitor_methods_version
; // Always set to MACH_PERFMON_METHODS_VERSION when writing driver kexts
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
;
129 /****************************************************************************
130 * Method types for performance counter registration
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
138 ****************************************************************************/
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.
147 typedef pmc_config_object_t (*pmc_create_config_method_t
)(pmc_object_t pmc
);
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
155 typedef void (*pmc_free_config_method_t
)(pmc_object_t pmc
, pmc_config_object_t config
);
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
166 typedef kern_return_t (*pmc_config_set_value_method_t
)(pmc_config_object_t config
, uint8_t id
, uint64_t value
);
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>
174 typedef void (*pmc_interrupt_method_t
)(void *target
, void *refCon
);
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
182 typedef kern_return_t (*pmc_config_set_interrupt_threshold_method_t
)(pmc_config_object_t config
, uint64_t threshold
);
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).
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
);
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.
199 typedef kern_return_t (*pmc_set_config_method_t
)(pmc_object_t pmc
, pmc_config_object_t config
);
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.
209 typedef perf_monitor_object_t (*pmc_get_monitor_method_t
)(pmc_object_t pmc
);
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.
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.
219 * @param pmc A valid pmc object.
220 * @result NULL on failure, or a pointer to the registered name of the pmc.
222 typedef const char *(*pmc_get_name_method_t
)(pmc_object_t pmc
);
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.
232 typedef boolean_t (*pmc_is_accessible_from_logical_core_method_t
)(pmc_object_t pmc
, uint32_t core
);
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.
243 typedef kern_return_t (*pmc_get_accessible_cores_method_t
)(pmc_object_t pmc
, uint32_t **cores
, size_t *coreCt
);
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.
250 typedef kern_return_t (*pmc_get_count_method_t
)(pmc_object_t pmc
, uint64_t *value
);
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.
258 typedef kern_return_t (*pmc_set_count_method_t
)(pmc_object_t pmc
, uint64_t value
);
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
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
269 typedef kern_return_t (*pmc_disable_method_t
)(pmc_object_t pmc
);
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
278 typedef kern_return_t (*pmc_enable_method_t
)(pmc_object_t pmc
);
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
);
283 #define MACH_PMC_METHODS_VERSION 0
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.
293 typedef struct pmc_methods
{
294 uint32_t pmc_methods_version
; // Always set to MACH_PMC_METHODS_VERSION in your driver.
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
;
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
;
317 * Kext interface Methods
319 * These methods would be exported to apple-internal kexts, but not to 3rd-party kexts, and
320 * definitely not to user space.
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
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
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
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)
349 kern_return_t
perf_monitor_register(perf_monitor_object_t monitor
, perf_monitor_methods_t
*methods
);
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.
360 kern_return_t
perf_monitor_unregister(perf_monitor_object_t monitor
);
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
376 kern_return_t
pmc_register(perf_monitor_object_t monitor
, pmc_object_t pmc
,
377 pmc_methods_t
*methods
, void *object
);
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.
388 kern_return_t
pmc_unregister(perf_monitor_object_t monitor
, pmc_object_t pmc
);
391 * Here begins the interface in-kernel and in-kext users will use to interact with PMCs and
392 * Performance Monitors.
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.
400 /*!struct perf_monitor
401 * @abstract In-kernel object to track a driver-implemented performance monitor.
403 typedef struct perf_monitor
{
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.
409 perf_monitor_object_t object
;
411 // Copy of the pointers used to interact with the above instance
412 perf_monitor_methods_t methods
;
417 // link to other perf monitors
422 * @abstract In-kernel object to track an individual driver-implemented performance counter
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.
432 /* Copy of the pointers used to interact with the above instance */
433 pmc_methods_t methods
;
435 /* Object to be used during open/close methods */
438 /* reference counted */
442 perf_monitor_t monitor
;
444 /* link to other PMCs */
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
454 #define PMC_FLAG_IS_SYSTEM_SCOPE(x) \
455 ((x & PMC_FLAG_SCOPE_SYSTEM) == PMC_FLAG_SCOPE_SYSTEM)
457 #define PMC_FLAG_IS_TASK_SCOPE(x) \
458 ((x & PMC_FLAG_SCOPE_TASK) == PMC_FLAG_SCOPE_TASK)
460 #define PMC_FLAG_IS_THREAD_SCOPE(x) \
461 ((x & PMC_FLAG_SCOPE_THREAD) == PMC_FLAG_SCOPE_THREAD)
463 #define PMC_FLAG_SCOPE(x) (x & PMC_SCOPE_MASK)
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.
474 typedef uint32_t pmc_state_t
;
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
485 #define PMC_STATE_STATE_MASK 0xF0000000U
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)
490 #define PMC_STATE_FLAGS_STOPPING 0x08000000U
491 #define PMC_STATE_FLAGS_DEALLOCING 0x04000000U
492 #define PMC_STATE_FLAGS_INTERRUPTING 0x02000000U
494 #define PMC_STATE_FLAGS_MASK 0x0F000000U
496 #define PMC_STATE_FLAGS(x) ((x) & PMC_STATE_FLAGS_MASK)
497 #define PMC_STATE_FLAGS_MODIFY(x, set, clear) (((x) & ~(clear)) | set)
499 #define PMC_STATE_CONTEXT_COUNT_MASK 0x0000FFFFU
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)
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))
508 #define PMC_STATE_INVALID PMC_STATE(PMC_STATE_STATE_INVALID, 0, 0)
510 /*!struct pmc_reservation
511 * @abstract In-kernel object to track an individual reservation
513 struct pmc_reservation
{
514 pmc_t pmc
; // Pointer to in-kernel pmc which is reserved
515 pmc_config_t config
; // counter configuration
517 // stored counter value
520 // TODO: Add mach-port (user-export object?)
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)));
527 task_t task
; // not retained
528 thread_t thread
; // not retained
534 // END Kernel-objects
537 // Methods exported to kernel (and kext) consumers
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.
545 kern_return_t
pmc_create_config(pmc_t pmc
, pmc_config_t
*config
);
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.
553 void pmc_free_config(pmc_t pmc
, pmc_config_t config
);
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.
560 kern_return_t
pmc_config_set_value(pmc_t pmc
, pmc_config_t config
, uint8_t id
, uint64_t value
);
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.
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
);
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.
574 kern_return_t
pmc_get_pmc_list(pmc_t
**pmcs
, size_t *pmcCount
);
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.
582 void pmc_free_pmc_list(pmc_t
*pmcs
, size_t pmcCount
);
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.
591 kern_return_t
pmc_find_by_name(const char *name
, pmc_t
**pmcs
, size_t *pmcCount
);
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.
598 const char *pmc_get_name(pmc_t pmc
);
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.
607 kern_return_t
pmc_get_accessible_core_list(pmc_t pmc
, uint32_t **logicalCores
, size_t *logicalCoreCt
);
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.
615 boolean_t
pmc_accessible_from_core(pmc_t pmc
, uint32_t logicalCore
);
618 * BEGIN PMC Reservations
620 * These are how you reserve a PMC, start and stop it counting, and read and write
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.
636 kern_return_t
pmc_reserve(pmc_t pmc
, pmc_config_t config
, pmc_reservation_t
*reservation
);
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>
648 kern_return_t
pmc_reserve_task(pmc_t pmc
, pmc_config_t config
, task_t task
, pmc_reservation_t
*reservation
);
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>
659 kern_return_t
pmc_reserve_thread(pmc_t pmc
, pmc_config_t config
, thread_t thread
, pmc_reservation_t
*reservation
);
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
666 kern_return_t
pmc_reservation_start(pmc_reservation_t reservation
);
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
673 kern_return_t
pmc_reservation_stop(pmc_reservation_t reservation
);
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
681 kern_return_t
pmc_reservation_read(pmc_reservation_t reservation
, uint64_t *value
);
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
689 kern_return_t
pmc_reservation_write(pmc_reservation_t reservation
, uint64_t value
);
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
696 kern_return_t
pmc_reservation_free(pmc_reservation_t reservation
);
698 #if XNU_KERNEL_PRIVATE
701 * @abstract Brings up all the necessary infrastructure required to use the pmc sub-system.
702 * @discussion For xnu-internal startup routines only.
704 void pmc_bootstrap(void);
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.
710 boolean_t
pmc_context_switch(thread_t oldThread
, thread_t newThread
);
712 #endif // XNU_KERNEL_PRIVATE
718 #endif // _MACH_PMC_H_