4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2009, Intel Corporation.
23 * All rights reserved.
26 #ifndef _SYS_CPU_EVENT_H
27 #define _SYS_CPU_EVENT_H
28 #include <sys/types.h>
37 * CPU idle notification callbacks are divided into three priority classes:
38 * 1. Statically assigned high priority callbacks.
39 * 2. Dynamically allocated normal priority callbacks.
40 * 3. Statically assigned low priority callbacks.
42 * All registered callbacks will be called in priority order from high
43 * to low just before CPU enters hardware idle state and from low to
44 * high just after CPU wakes from idle state.
46 * The high and low priority classes are designed to support hardware
47 * ordering requirements. A dynamically assigned priority allows the
48 * framework to choose the order in which the callback is processed.
49 * If a callback has no dependency on other callbacks, it should use
50 * dynamic priority to avoid priority conflicts.
52 * Note that the priority doesn't describe how important a callback
53 * is, but just the order in which they are processed. If a callback
54 * needs processing early in the idle notification cycle, it should
55 * have a higher priority. If it needs to be at the end, or early on
56 * the exit, then it should have a lower priority.
59 #define CPU_IDLE_CB_PRIO_LOW_BASE 0x20000000U
60 #define CPU_IDLE_CB_PRIO_DYN_BASE 0x40000000U
61 #define CPU_IDLE_CB_PRIO_HIGH_BASE 0x40000001U
62 #define CPU_IDLE_CB_PRIO_RESV_BASE 0x80000000U
65 * Indicating dynamic priority to cpu_idle_{un}register_callback().
67 #define CPU_IDLE_CB_PRIO_DYNAMIC CPU_IDLE_CB_PRIO_DYN_BASE
68 /* Priority assigned to dtrace probe callback. */
69 #define CPU_IDLE_CB_PRIO_DTRACE (CPU_IDLE_CB_PRIO_LOW_BASE + 0xC000000)
73 /* Priority assigned to TLB flush callback. */
74 #define CPU_IDLE_CB_PRIO_TLB (CPU_IDLE_CB_PRIO_LOW_BASE + 0x100000)
77 /* Name of properties supported by CPU idle notification. */
78 #define CPU_IDLE_PROP_IDLE_STATE "idle-state"
79 #define CPU_IDLE_PROP_ENTER_TIMESTAMP "enter-ts"
80 #define CPU_IDLE_PROP_EXIT_TIMESTAMP "exit-ts"
81 #define CPU_IDLE_PROP_LAST_IDLE_TIME "last-idle-time"
82 #define CPU_IDLE_PROP_LAST_BUSY_TIME "last-busy-time"
83 #define CPU_IDLE_PROP_TOTAL_IDLE_TIME "total-idle-time"
84 #define CPU_IDLE_PROP_TOTAL_BUSY_TIME "total-busy-time"
85 #define CPU_IDLE_PROP_INTERRUPT_COUNT "interupt-count"
88 * sizeof(cpu_idle_prop_value_t) should be power of 2 to align on cache line.
90 typedef union cpu_idle_prop_value
{
95 } cpu_idle_prop_value_t
;
97 typedef enum cpu_idle_prop_type
{
98 CPU_IDLE_PROP_TYPE_INTPTR
,
99 CPU_IDLE_PROP_TYPE_UINT32
,
100 CPU_IDLE_PROP_TYPE_UINT64
,
101 CPU_IDLE_PROP_TYPE_HRTIME
,
102 } cpu_idle_prop_type_t
;
104 typedef void *cpu_idle_callback_handle_t
;
105 typedef void *cpu_idle_callback_context_t
;
106 typedef void *cpu_idle_prop_handle_t
;
109 * Function prototype for checking CPU wakeup events.
110 * If CPU has already been awakened, check_wakeup callback should call
111 * cpu_idle_exit() to notify CPU idle framework if it has been called yet.
113 typedef void (* cpu_idle_check_wakeup_t
)(void *arg
);
116 * Function prototype for entering idle state notification callback.
117 * Callback for entering idle state notification must obey all constraints
118 * which apply to idle thread because it will be called in idle thread context.
119 * The callback will be called with interrupt disabled. The callback may enable
120 * interrupt if it can cooperate with corresponding idle_exit callback to
121 * handle interrupt happening after enabling interrupt. If idle_enter callback
122 * enables interrupt, the corresponding idle_exit callback may be called before
123 * returning from idle_enter callback.
125 typedef void (* cpu_idle_enter_cbfn_t
)(void *arg
,
126 cpu_idle_callback_context_t ctx
,
127 cpu_idle_check_wakeup_t check_func
, void *check_arg
);
130 * Function prototype for exiting idle state notification callback.
131 * Callback for exiting idle state notification will be called in idle thread
132 * context or interrupt context with interrupt disabled.
133 * There is a flag to distinguish the calling context.
134 * The callback must not try to enable interrupts.
136 typedef void (* cpu_idle_exit_cbfn_t
)(void *arg
,
137 cpu_idle_callback_context_t ctx
, int flag
);
139 #define CPU_IDLE_CB_FLAG_INTR 0x1 /* Called in interrupt context. */
140 #define CPU_IDLE_CB_FLAG_IDLE 0x2 /* Called in idle thread context. */
142 typedef struct cpu_idle_callback
{
144 cpu_idle_enter_cbfn_t idle_enter
;
145 cpu_idle_exit_cbfn_t idle_exit
;
146 } cpu_idle_callback_t
;
148 #define CPU_IDLE_CALLBACK_VER0 0
149 #define CPU_IDLE_CALLBACK_VERS CPU_IDLE_CALLBACK_VER0
152 * Register a callback to be called when CPU idle state changes.
153 * All registered callbacks will be called in priority order from high to low
154 * when CPU enters idle state and from low to high when CPU leaves idle state.
155 * If CPU is predicted to sleep for a short time or be under heavy load,
156 * framework may skip calling registered callbacks when idle state changes to
157 * avoid overhead and reduce performance penalties.
158 * It's guaranteed that each exiting notification will be paired with each
159 * entering notification.
160 * Return zero on success and error code on failure.
161 * N.B.: this interface shouldn't be called from following conditions:
164 extern int cpu_idle_register_callback(uint_t prio
, cpu_idle_callback_t
*cbp
,
165 void *arg
, cpu_idle_callback_handle_t
*hdlp
);
168 * Un-register a registered callback.
169 * Return zero on success and error code on failure.
170 * N.B.: this interface shouldn't be called from following cases:
173 extern int cpu_idle_unregister_callback(cpu_idle_callback_handle_t hdl
);
176 * Called by CPU idle handler to notify entering idle state.
177 * It should be called with interrupt disabled.
178 * state: platform specific information of idle state to enter.
179 * On x86, it's CPU C state.
180 * Idle thread should cancel entering hardware idle state if cpu_idle_enter
181 * returns non-zero value.
183 extern int cpu_idle_enter(int state
, int flag
,
184 cpu_idle_check_wakeup_t check_func
, void *check_arg
);
187 * Called by CPU idle handler to notify exiting idle state.
188 * It should be called with interrupt disabled.
190 extern void cpu_idle_exit(int flag
);
193 * Get CPU idle notification context corresponding to current CPU.
195 extern cpu_idle_callback_context_t
cpu_idle_get_context(void);
198 * Prototype of function called to update property value on demand.
199 * The callback should update property value corresponding to current CPU.
201 typedef int (* cpu_idle_prop_update_t
)(void *arg
, uint64_t seqnum
,
202 cpu_idle_prop_value_t
*valp
);
205 * Create a property with name and type.
206 * If parameter update is not NULL, it will be called on demand to update
207 * value of property corresponding to current CPU.
208 * If parameter update is NULL, provider should call cpu_idle_property_set
209 * to update property value for each CPU.
210 * Return zero on success with handle stored in hdlp, otherwise error code.
212 extern int cpu_idle_prop_create_property(const char *name
,
213 cpu_idle_prop_type_t type
, cpu_idle_prop_update_t update
, void *arg
,
214 cpu_idle_prop_handle_t
*hdlp
);
217 * Destroy property corresponding to hdl.
218 * Return zero on success, otherwise error code.
220 extern int cpu_idle_prop_destroy_property(cpu_idle_prop_handle_t hdl
);
223 * Create handle for property with name 'name'.
224 * Return zero on success with handle stored in hdlp, otherwise error code.
226 extern int cpu_idle_prop_create_handle(const char *name
,
227 cpu_idle_prop_handle_t
*hdlp
);
230 * Destroy property handle.
231 * Return zero on success, otherwise error code.
233 extern int cpu_idle_prop_destroy_handle(cpu_idle_prop_handle_t hdl
);
236 * CPU idle property manipulation functions.
237 * All cpu_idle_prop_get/set_xxx functions with argument ctx should only be used
238 * to manipulate properties associated with current CPU.
239 * Context ctx shouldn't be passed to other CPUs to manipulate properties.
241 extern cpu_idle_prop_type_t
cpu_idle_prop_get_type(cpu_idle_prop_handle_t hdl
);
242 extern const char *cpu_idle_prop_get_name(cpu_idle_prop_handle_t hdl
);
243 extern int cpu_idle_prop_get_value(cpu_idle_prop_handle_t hdl
,
244 cpu_idle_callback_context_t ctx
, cpu_idle_prop_value_t
*valp
);
245 extern uint32_t cpu_idle_prop_get_uint32(cpu_idle_prop_handle_t hdl
,
246 cpu_idle_callback_context_t ctx
);
247 extern uint64_t cpu_idle_prop_get_uint64(cpu_idle_prop_handle_t hdl
,
248 cpu_idle_callback_context_t ctx
);
249 extern intptr_t cpu_idle_prop_get_intptr(cpu_idle_prop_handle_t hdl
,
250 cpu_idle_callback_context_t ctx
);
251 extern hrtime_t
cpu_idle_prop_get_hrtime(cpu_idle_prop_handle_t hdl
,
252 cpu_idle_callback_context_t ctx
);
253 extern void cpu_idle_prop_set_value(cpu_idle_prop_handle_t hdl
,
254 cpu_idle_callback_context_t ctx
, cpu_idle_prop_value_t val
);
255 extern void cpu_idle_prop_set_all(cpu_idle_prop_handle_t hdl
,
256 cpu_idle_prop_value_t val
);
258 extern uint_t
cpu_idle_get_cpu_state(cpu_t
*cp
);
260 extern void cpu_event_init(void);
261 extern void cpu_event_init_cpu(cpu_t
*cp
);
262 extern void cpu_event_fini_cpu(cpu_t
*cp
);
270 #endif /* _SYS_CPU_EVENT_H */