xref: /illumos-gate/usr/src/uts/i86pc/sys/cpupm_mach.h (revision 5951ced0)
10e751525SEric Saxe /*
20e751525SEric Saxe  * CDDL HEADER START
30e751525SEric Saxe  *
40e751525SEric Saxe  * The contents of this file are subject to the terms of the
50e751525SEric Saxe  * Common Development and Distribution License (the "License").
60e751525SEric Saxe  * You may not use this file except in compliance with the License.
70e751525SEric Saxe  *
80e751525SEric Saxe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90e751525SEric Saxe  * or http://www.opensolaris.org/os/licensing.
100e751525SEric Saxe  * See the License for the specific language governing permissions
110e751525SEric Saxe  * and limitations under the License.
120e751525SEric Saxe  *
130e751525SEric Saxe  * When distributing Covered Code, include this CDDL HEADER in each
140e751525SEric Saxe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150e751525SEric Saxe  * If applicable, add the following below this CDDL HEADER, with the
160e751525SEric Saxe  * fields enclosed by brackets "[]" replaced with your own identifying
170e751525SEric Saxe  * information: Portions Copyright [yyyy] [name of copyright owner]
180e751525SEric Saxe  *
190e751525SEric Saxe  * CDDL HEADER END
200e751525SEric Saxe  */
210e751525SEric Saxe /*
220e751525SEric Saxe  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230e751525SEric Saxe  * Use is subject to license terms.
240e751525SEric Saxe  */
25444f66e7SMark Haywood /*
26444f66e7SMark Haywood  * Copyright (c) 2009,  Intel Corporation.
27444f66e7SMark Haywood  * All Rights Reserved.
28444f66e7SMark Haywood  */
290e751525SEric Saxe 
300e751525SEric Saxe #ifndef	_CPUPM_MACH_H
310e751525SEric Saxe #define	_CPUPM_MACH_H
320e751525SEric Saxe 
330e751525SEric Saxe #ifdef __cplusplus
340e751525SEric Saxe extern "C" {
350e751525SEric Saxe #endif
360e751525SEric Saxe 
370e751525SEric Saxe #include <sys/ddi.h>
380e751525SEric Saxe #include <sys/sunddi.h>
390e751525SEric Saxe #include <sys/cpuvar.h>
400e751525SEric Saxe #include <sys/ksynch.h>
410e751525SEric Saxe #include <sys/cpu_pm.h>
420e751525SEric Saxe 
430e751525SEric Saxe /*
440e751525SEric Saxe  * CPU power domains
450e751525SEric Saxe  */
460e751525SEric Saxe typedef struct cpupm_state_domains {
470e751525SEric Saxe 	struct cpupm_state_domains	*pm_next;
480e751525SEric Saxe 	uint32_t			pm_domain;
490e751525SEric Saxe 	uint32_t			pm_type;
500e751525SEric Saxe 	cpuset_t			pm_cpus;
510e751525SEric Saxe 	kmutex_t			pm_lock;
520e751525SEric Saxe } cpupm_state_domains_t;
530e751525SEric Saxe 
540e751525SEric Saxe extern cpupm_state_domains_t *cpupm_pstate_domains;
550e751525SEric Saxe extern cpupm_state_domains_t *cpupm_tstate_domains;
560e751525SEric Saxe extern cpupm_state_domains_t *cpupm_cstate_domains;
570e751525SEric Saxe 
580e751525SEric Saxe /*
590e751525SEric Saxe  * Different processor families have their own technologies for supporting
600e751525SEric Saxe  * CPU power management (i.e., Intel has Enhanced SpeedStep for some of its
610e751525SEric Saxe  * processors and AMD has PowerNow! for some of its processors). We support
620e751525SEric Saxe  * these different technologies via modules that export the interfaces
630e751525SEric Saxe  * described below.
640e751525SEric Saxe  *
650e751525SEric Saxe  * If a module implements the technology that should be used to manage
660e751525SEric Saxe  * the current CPU device, then the cpus_init() module should return
670e751525SEric Saxe  * succesfully (i.e., return code of 0) and perform any initialization
680e751525SEric Saxe  * such that future power transistions can be performed by calling
690e751525SEric Saxe  * the cpus_change() interface. And the cpups_fini() interface can be
700e751525SEric Saxe  * used to free any resources allocated by cpus_init().
710e751525SEric Saxe  */
720e751525SEric Saxe typedef struct cpupm_state_ops {
730e751525SEric Saxe 	char	*cpups_label;
740e751525SEric Saxe 	int	(*cpus_init)(cpu_t *);
750e751525SEric Saxe 	void	(*cpus_fini)(cpu_t *);
760e751525SEric Saxe 	void	(*cpus_change)(cpuset_t, uint32_t);
77444f66e7SMark Haywood 	void	(*cpus_stop)(cpu_t *);
780e751525SEric Saxe } cpupm_state_ops_t;
790e751525SEric Saxe 
800e751525SEric Saxe /*
810e751525SEric Saxe  * Data kept for each C-state power-domain.
820e751525SEric Saxe  */
830e751525SEric Saxe typedef struct cma_c_state {
840e751525SEric Saxe 	uint32_t	cs_next_cstate;	/* computed best C-state */
850e751525SEric Saxe 
860e751525SEric Saxe 	uint32_t	cs_cnt;		/* times accessed */
870e751525SEric Saxe 	uint32_t	cs_type;	/* current ACPI idle type */
880e751525SEric Saxe 
890e751525SEric Saxe 	hrtime_t	cs_idle_enter;	/* entered idle */
900e751525SEric Saxe 	hrtime_t	cs_idle_exit;	/* left idle */
910e751525SEric Saxe 
920e751525SEric Saxe 	hrtime_t	cs_smpl_start;	/* accounting sample began */
930e751525SEric Saxe 	hrtime_t	cs_idle;	/* time idle */
940e751525SEric Saxe 	hrtime_t	cs_smpl_len;	/* sample duration */
950e751525SEric Saxe 	hrtime_t	cs_smpl_idle;	/* idle time in last sample */
960e751525SEric Saxe 	uint64_t	cs_smpl_idle_pct;	/* % idle time in last smpl */
970e751525SEric Saxe } cma_c_state_t;
980e751525SEric Saxe 
990e751525SEric Saxe typedef union cma_state {
1000e751525SEric Saxe 	cma_c_state_t	*cstate;
1010e751525SEric Saxe 	uint32_t	pstate;
1020e751525SEric Saxe } cma_state_t;
1030e751525SEric Saxe 
1040e751525SEric Saxe typedef struct cpupm_mach_acpi_state {
1050e751525SEric Saxe 	cpupm_state_ops_t	*cma_ops;
1060e751525SEric Saxe 	cpupm_state_domains_t   *cma_domain;
1070e751525SEric Saxe 	cma_state_t		cma_state;
1080e751525SEric Saxe } cpupm_mach_acpi_state_t;
1090e751525SEric Saxe 
110*5951ced0SHans Rosenfeld typedef struct cpupm_mach_turbo_info {
111*5951ced0SHans Rosenfeld 	kstat_t		*turbo_ksp;		/* turbo kstat */
112*5951ced0SHans Rosenfeld 	int		in_turbo;		/* in turbo? */
113*5951ced0SHans Rosenfeld 	int		turbo_supported;	/* turbo flag */
114*5951ced0SHans Rosenfeld 	uint64_t	t_mcnt;			/* turbo mcnt */
115*5951ced0SHans Rosenfeld 	uint64_t	t_acnt;			/* turbo acnt */
116*5951ced0SHans Rosenfeld } cpupm_mach_turbo_info_t;
117*5951ced0SHans Rosenfeld 
1180e751525SEric Saxe typedef struct cpupm_mach_state {
1190e751525SEric Saxe 	void			*ms_acpi_handle;
1200e751525SEric Saxe 	cpupm_mach_acpi_state_t	ms_pstate;
1210e751525SEric Saxe 	cpupm_mach_acpi_state_t	ms_cstate;
1220e751525SEric Saxe 	cpupm_mach_acpi_state_t	ms_tstate;
1230e751525SEric Saxe 	uint32_t		ms_caps;
1240e751525SEric Saxe 	dev_info_t		*ms_dip;
1250e751525SEric Saxe 	kmutex_t		ms_lock;
126*5951ced0SHans Rosenfeld 	cpupm_mach_turbo_info_t	*ms_turbo;
1270e751525SEric Saxe 	struct cpupm_notification *ms_handlers;
1280e751525SEric Saxe } cpupm_mach_state_t;
1290e751525SEric Saxe 
1300e751525SEric Saxe /*
1310e751525SEric Saxe  * Constants used by the Processor Device Notification handler
1320e751525SEric Saxe  * that identify what kind of change has occurred.
1330e751525SEric Saxe  */
1340e751525SEric Saxe #define	CPUPM_PPC_CHANGE_NOTIFICATION 0x80
1350e751525SEric Saxe #define	CPUPM_CST_CHANGE_NOTIFICATION 0x81
1360e751525SEric Saxe #define	CPUPM_TPC_CHANGE_NOTIFICATION 0x82
1370e751525SEric Saxe 
1380e751525SEric Saxe typedef void (*CPUPM_NOTIFY_HANDLER)(void *handle, uint32_t val,
1390e751525SEric Saxe     void *ctx);
1400e751525SEric Saxe 
1410e751525SEric Saxe typedef struct cpupm_notification {
1420e751525SEric Saxe 	struct cpupm_notification	*nq_next;
1430e751525SEric Saxe 	CPUPM_NOTIFY_HANDLER		nq_handler;
1440e751525SEric Saxe 	void				*nq_ctx;
1450e751525SEric Saxe } cpupm_notification_t;
1460e751525SEric Saxe 
1470e751525SEric Saxe /*
1480e751525SEric Saxe  * If any states are added, then make sure to add them to
1490e751525SEric Saxe  * CPUPM_ALL_STATES.
1500e751525SEric Saxe  */
1510e751525SEric Saxe #define	CPUPM_NO_STATES		0x00
1520e751525SEric Saxe #define	CPUPM_P_STATES		0x01
1530e751525SEric Saxe #define	CPUPM_T_STATES		0x02
1540e751525SEric Saxe #define	CPUPM_C_STATES		0x04
1550e751525SEric Saxe #define	CPUPM_ALL_STATES	(CPUPM_P_STATES \
1560e751525SEric Saxe 				| CPUPM_T_STATES \
1570e751525SEric Saxe 				| CPUPM_C_STATES)
1580e751525SEric Saxe 
1590e751525SEric Saxe /*
1600e751525SEric Saxe  * An error in initializing any of the CPU PM results in disabling
1610e751525SEric Saxe  * CPU power management.
1620e751525SEric Saxe  */
1630e751525SEric Saxe #define	CPUPM_DISABLE() cpupm_disable(CPUPM_ALL_STATES)
1640e751525SEric Saxe 
1650e751525SEric Saxe #define	CPUPM_SPEED_HZ(unused, mhz) ((uint64_t)mhz * 1000000)
1660e751525SEric Saxe 
1670e751525SEric Saxe /*
1680e751525SEric Saxe  * Callbacks used for CPU power management.
1690e751525SEric Saxe  */
170444f66e7SMark Haywood extern void (*cpupm_ppm_alloc_pstate_domains)(cpu_t *);
171444f66e7SMark Haywood extern void (*cpupm_ppm_free_pstate_domains)(cpu_t *);
1720e751525SEric Saxe extern void (*cpupm_redefine_topspeed)(void *);
1730e751525SEric Saxe extern int (*cpupm_get_topspeed_callb)(void *);
1740e751525SEric Saxe extern void (*cpupm_set_topspeed_callb)(void *, int);
1750e751525SEric Saxe 
1760e751525SEric Saxe extern void cpupm_init(cpu_t *);
177444f66e7SMark Haywood extern void cpupm_fini(cpu_t *);
178444f66e7SMark Haywood extern void cpupm_start(cpu_t *);
179444f66e7SMark Haywood extern void cpupm_stop(cpu_t *);
180444f66e7SMark Haywood extern boolean_t cpupm_is_ready(cpu_t *);
1810e751525SEric Saxe extern boolean_t cpupm_is_enabled(uint32_t);
1820e751525SEric Saxe extern void cpupm_disable(uint32_t);
1830e751525SEric Saxe extern void cpupm_alloc_domains(cpu_t *, int);
1840e751525SEric Saxe extern void cpupm_free_domains(cpupm_state_domains_t **);
185444f66e7SMark Haywood extern void cpupm_remove_domains(cpu_t *, int, cpupm_state_domains_t **);
1860e751525SEric Saxe extern void cpupm_alloc_ms_cstate(cpu_t *cp);
1870e751525SEric Saxe extern void cpupm_free_ms_cstate(cpu_t *cp);
1880e751525SEric Saxe extern void cpupm_state_change(cpu_t *, int, int);
1890e751525SEric Saxe extern id_t cpupm_plat_domain_id(cpu_t *cp, cpupm_dtype_t type);
1900e751525SEric Saxe extern uint_t cpupm_plat_state_enumerate(cpu_t *, cpupm_dtype_t,
1910e751525SEric Saxe     cpupm_state_t *);
1920e751525SEric Saxe extern int cpupm_plat_change_state(cpu_t *, cpupm_state_t *);
1930e751525SEric Saxe extern uint_t cpupm_get_speeds(cpu_t *, int **);
1940e751525SEric Saxe extern void cpupm_free_speeds(int *, uint_t);
195444f66e7SMark Haywood extern boolean_t cpupm_power_ready(cpu_t *);
196444f66e7SMark Haywood extern boolean_t cpupm_throttle_ready(cpu_t *);
197444f66e7SMark Haywood extern boolean_t cpupm_cstate_ready(cpu_t *);
1980e751525SEric Saxe extern void cpupm_add_notify_handler(cpu_t *, CPUPM_NOTIFY_HANDLER, void *);
1990e751525SEric Saxe extern int cpupm_get_top_speed(cpu_t *);
2000e751525SEric Saxe extern void cpupm_idle_cstate_data(cma_c_state_t *, int);
2010e751525SEric Saxe extern void cpupm_wakeup_cstate_data(cma_c_state_t *, hrtime_t);
202*5951ced0SHans Rosenfeld extern void cpupm_record_turbo_info(cpupm_mach_turbo_info_t *, uint32_t,
203*5951ced0SHans Rosenfeld     uint32_t);
204*5951ced0SHans Rosenfeld extern cpupm_mach_turbo_info_t *cpupm_turbo_init(cpu_t *);
205*5951ced0SHans Rosenfeld extern void cpupm_turbo_fini(cpupm_mach_turbo_info_t *);
2060e751525SEric Saxe 
2070e751525SEric Saxe #ifdef __cplusplus
2080e751525SEric Saxe }
2090e751525SEric Saxe #endif
2100e751525SEric Saxe 
2110e751525SEric Saxe #endif	/* _CPUPM_MACH_H */
212