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