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