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