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