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