1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2009, Intel Corporation. 27 * All Rights Reserved. 28 */ 29 30 #ifndef _CPUPM_MACH_H 31 #define _CPUPM_MACH_H 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #include <sys/ddi.h> 38 #include <sys/sunddi.h> 39 #include <sys/cpuvar.h> 40 #include <sys/ksynch.h> 41 #include <sys/cpu_pm.h> 42 43 /* 44 * CPU power domains 45 */ 46 typedef struct cpupm_state_domains { 47 struct cpupm_state_domains *pm_next; 48 uint32_t pm_domain; 49 uint32_t pm_type; 50 cpuset_t pm_cpus; 51 kmutex_t pm_lock; 52 } cpupm_state_domains_t; 53 54 extern cpupm_state_domains_t *cpupm_pstate_domains; 55 extern cpupm_state_domains_t *cpupm_tstate_domains; 56 extern cpupm_state_domains_t *cpupm_cstate_domains; 57 58 /* 59 * Different processor families have their own technologies for supporting 60 * CPU power management (i.e., Intel has Enhanced SpeedStep for some of its 61 * processors and AMD has PowerNow! for some of its processors). We support 62 * these different technologies via modules that export the interfaces 63 * described below. 64 * 65 * If a module implements the technology that should be used to manage 66 * the current CPU device, then the cpus_init() module should return 67 * succesfully (i.e., return code of 0) and perform any initialization 68 * such that future power transistions can be performed by calling 69 * the cpus_change() interface. And the cpups_fini() interface can be 70 * used to free any resources allocated by cpus_init(). 71 */ 72 typedef struct cpupm_state_ops { 73 char *cpups_label; 74 int (*cpus_init)(cpu_t *); 75 void (*cpus_fini)(cpu_t *); 76 void (*cpus_change)(cpuset_t, uint32_t); 77 void (*cpus_stop)(cpu_t *); 78 } cpupm_state_ops_t; 79 80 /* 81 * Data kept for each C-state power-domain. 82 */ 83 typedef struct cma_c_state { 84 uint32_t cs_next_cstate; /* computed best C-state */ 85 86 uint32_t cs_cnt; /* times accessed */ 87 uint32_t cs_type; /* current ACPI idle type */ 88 89 hrtime_t cs_idle_enter; /* entered idle */ 90 hrtime_t cs_idle_exit; /* left idle */ 91 92 hrtime_t cs_smpl_start; /* accounting sample began */ 93 hrtime_t cs_idle; /* time idle */ 94 hrtime_t cs_smpl_len; /* sample duration */ 95 hrtime_t cs_smpl_idle; /* idle time in last sample */ 96 uint64_t cs_smpl_idle_pct; /* % idle time in last smpl */ 97 } cma_c_state_t; 98 99 typedef union cma_state { 100 cma_c_state_t *cstate; 101 uint32_t pstate; 102 } cma_state_t; 103 104 typedef struct cpupm_mach_acpi_state { 105 cpupm_state_ops_t *cma_ops; 106 cpupm_state_domains_t *cma_domain; 107 cma_state_t cma_state; 108 } cpupm_mach_acpi_state_t; 109 110 typedef struct cpupm_mach_turbo_info { 111 kstat_t *turbo_ksp; /* turbo kstat */ 112 int in_turbo; /* in turbo? */ 113 int turbo_supported; /* turbo flag */ 114 uint64_t t_mcnt; /* turbo mcnt */ 115 uint64_t t_acnt; /* turbo acnt */ 116 } cpupm_mach_turbo_info_t; 117 118 typedef struct cpupm_mach_state { 119 void *ms_acpi_handle; 120 cpupm_mach_acpi_state_t ms_pstate; 121 cpupm_mach_acpi_state_t ms_cstate; 122 cpupm_mach_acpi_state_t ms_tstate; 123 uint32_t ms_caps; 124 dev_info_t *ms_dip; 125 kmutex_t ms_lock; 126 cpupm_mach_turbo_info_t *ms_turbo; 127 struct cpupm_notification *ms_handlers; 128 } cpupm_mach_state_t; 129 130 /* 131 * Constants used by the Processor Device Notification handler 132 * that identify what kind of change has occurred. 133 */ 134 #define CPUPM_PPC_CHANGE_NOTIFICATION 0x80 135 #define CPUPM_CST_CHANGE_NOTIFICATION 0x81 136 #define CPUPM_TPC_CHANGE_NOTIFICATION 0x82 137 138 typedef void (*CPUPM_NOTIFY_HANDLER)(void *handle, uint32_t val, 139 void *ctx); 140 141 typedef struct cpupm_notification { 142 struct cpupm_notification *nq_next; 143 CPUPM_NOTIFY_HANDLER nq_handler; 144 void *nq_ctx; 145 } cpupm_notification_t; 146 147 /* 148 * If any states are added, then make sure to add them to 149 * CPUPM_ALL_STATES. 150 */ 151 #define CPUPM_NO_STATES 0x00 152 #define CPUPM_P_STATES 0x01 153 #define CPUPM_T_STATES 0x02 154 #define CPUPM_C_STATES 0x04 155 #define CPUPM_ALL_STATES (CPUPM_P_STATES \ 156 | CPUPM_T_STATES \ 157 | CPUPM_C_STATES) 158 159 /* 160 * An error in initializing any of the CPU PM results in disabling 161 * CPU power management. 162 */ 163 #define CPUPM_DISABLE() cpupm_disable(CPUPM_ALL_STATES) 164 165 #define CPUPM_SPEED_HZ(unused, mhz) ((uint64_t)mhz * 1000000) 166 167 /* 168 * Callbacks used for CPU power management. 169 */ 170 extern void (*cpupm_ppm_alloc_pstate_domains)(cpu_t *); 171 extern void (*cpupm_ppm_free_pstate_domains)(cpu_t *); 172 extern void (*cpupm_redefine_topspeed)(void *); 173 extern int (*cpupm_get_topspeed_callb)(void *); 174 extern void (*cpupm_set_topspeed_callb)(void *, int); 175 176 extern void cpupm_init(cpu_t *); 177 extern void cpupm_fini(cpu_t *); 178 extern void cpupm_start(cpu_t *); 179 extern void cpupm_stop(cpu_t *); 180 extern boolean_t cpupm_is_ready(cpu_t *); 181 extern boolean_t cpupm_is_enabled(uint32_t); 182 extern void cpupm_disable(uint32_t); 183 extern void cpupm_alloc_domains(cpu_t *, int); 184 extern void cpupm_free_domains(cpupm_state_domains_t **); 185 extern void cpupm_remove_domains(cpu_t *, int, cpupm_state_domains_t **); 186 extern void cpupm_alloc_ms_cstate(cpu_t *cp); 187 extern void cpupm_free_ms_cstate(cpu_t *cp); 188 extern void cpupm_state_change(cpu_t *, int, int); 189 extern id_t cpupm_plat_domain_id(cpu_t *cp, cpupm_dtype_t type); 190 extern uint_t cpupm_plat_state_enumerate(cpu_t *, cpupm_dtype_t, 191 cpupm_state_t *); 192 extern int cpupm_plat_change_state(cpu_t *, cpupm_state_t *); 193 extern uint_t cpupm_get_speeds(cpu_t *, int **); 194 extern void cpupm_free_speeds(int *, uint_t); 195 extern boolean_t cpupm_power_ready(cpu_t *); 196 extern boolean_t cpupm_throttle_ready(cpu_t *); 197 extern boolean_t cpupm_cstate_ready(cpu_t *); 198 extern void cpupm_add_notify_handler(cpu_t *, CPUPM_NOTIFY_HANDLER, void *); 199 extern int cpupm_get_top_speed(cpu_t *); 200 extern void cpupm_idle_cstate_data(cma_c_state_t *, int); 201 extern void cpupm_wakeup_cstate_data(cma_c_state_t *, hrtime_t); 202 extern void cpupm_record_turbo_info(cpupm_mach_turbo_info_t *, uint32_t, 203 uint32_t); 204 extern cpupm_mach_turbo_info_t *cpupm_turbo_init(cpu_t *); 205 extern void cpupm_turbo_fini(cpupm_mach_turbo_info_t *); 206 207 #ifdef __cplusplus 208 } 209 #endif 210 211 #endif /* _CPUPM_MACH_H */ 212