1.\" Copyright (c) 2005 Nate Lawson 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd January 22, 2020 28.Dt CPUFREQ 4 29.Os 30.Sh NAME 31.Nm cpufreq 32.Nd CPU frequency control framework 33.Sh SYNOPSIS 34.Cd "device cpufreq" 35.Pp 36.In sys/cpu.h 37.Ft int 38.Fn cpufreq_levels "device_t dev" "struct cf_level *levels" "int *count" 39.Ft int 40.Fn cpufreq_set "device_t dev" "const struct cf_level *level" "int priority" 41.Ft int 42.Fn cpufreq_get "device_t dev" "struct cf_level *level" 43.Ft int 44.Fo cpufreq_drv_settings 45.Fa "device_t dev" 46.Fa "struct cf_setting *sets" 47.Fa "int *count" 48.Fc 49.Ft int 50.Fn cpufreq_drv_type "device_t dev" "int *type" 51.Ft int 52.Fn cpufreq_drv_set "device_t dev" "const struct cf_setting *set" 53.Ft int 54.Fn cpufreq_drv_get "device_t dev" "struct cf_setting *set" 55.Sh DESCRIPTION 56The 57.Nm 58driver provides a unified kernel and user interface to CPU frequency 59control drivers. 60It combines multiple drivers offering different settings into a single 61interface of all possible levels. 62Users can access this interface directly via 63.Xr sysctl 8 64or by indicating to 65.Pa /etc/rc.d/power_profile 66that it should switch settings when the AC line state changes via 67.Xr rc.conf 5 . 68.Sh SYSCTL VARIABLES 69These settings may be overridden by kernel drivers requesting alternate 70settings. 71If this occurs, the original values will be restored once the condition 72has passed (e.g., the system has cooled sufficiently). 73If a sysctl cannot be set due to an override condition, it will return 74.Er EPERM . 75.Pp 76The frequency cannot be changed if TSC is in use as the timecounter. 77This is because the timecounter system needs to use a source that has a 78constant rate. 79The timecounter source can be changed with the 80.Pa kern.timecounter.hardware 81sysctl. 82Available modes are in 83.Pa kern.timecounter.choice 84sysctl entry. 85.Bl -tag -width indent 86.It Va dev.cpu.%d.freq 87Current active CPU frequency in MHz. 88.It Va dev.cpu.%d.freq_driver 89The specific 90.Nm 91driver used by this cpu. 92.It Va dev.cpu.%d.freq_levels 93Currently available levels for the CPU (frequency/power usage). 94Values are in units of MHz and milliwatts. 95.It Va dev.DEVICE.%d.freq_settings 96Currently available settings for the driver (frequency/power usage). 97Values are in units of MHz and milliwatts. 98This is helpful for understanding which settings are offered by which 99driver for debugging purposes. 100.It Va debug.cpufreq.lowest 101Lowest CPU frequency in MHz to offer to users. 102This setting is also accessible via a tunable with the same name. 103This can be used to disable very low levels that may be unusable on 104some systems. 105.It Va debug.cpufreq.verbose 106Print verbose messages. 107This setting is also accessible via a tunable with the same name. 108.El 109.Sh SUPPORTED DRIVERS 110The following device drivers offer absolute frequency control via the 111.Nm 112interface. 113Usually, only one of these can be active at a time. 114.Pp 115.Bl -tag -compact -width ".Pa acpi_perf" 116.It Pa acpi_perf 117ACPI CPU performance states 118.It Pa est 119Intel Enhanced SpeedStep 120.It Pa ichss 121Intel SpeedStep for ICH 122.It Pa powernow 123AMD PowerNow!\& and Cool'n'Quiet for K7 and K8 124.It Pa smist 125Intel SMI-based SpeedStep for PIIX4 126.El 127.Pp 128The following device drivers offer relative frequency control and 129have an additive effect: 130.Pp 131.Bl -tag -compact -width ".Pa acpi_throttle" 132.It Pa acpi_throttle 133ACPI CPU throttling 134.It Pa p4tcc 135Pentium 4 Thermal Control Circuitry 136.El 137.Sh KERNEL INTERFACE 138Kernel components can query and set CPU frequencies through the 139.Nm 140kernel interface. 141This involves obtaining a 142.Nm 143device, calling 144.Fn cpufreq_levels 145to get the currently available frequency levels, 146checking the current level with 147.Fn cpufreq_get , 148and setting a new one from the list with 149.Fn cpufreq_set . 150Each level may actually reference more than one 151.Nm 152driver but kernel components do not need to be aware of this. 153The 154.Va total_set 155element of 156.Vt "struct cf_level" 157provides a summary of the frequency and power for this level. 158Unknown or irrelevant values are set to 159.Dv CPUFREQ_VAL_UNKNOWN . 160.Pp 161The 162.Fn cpufreq_levels 163method takes a 164.Nm 165device and an empty array of 166.Fa levels . 167The 168.Fa count 169value should be set to the number of levels available and after the 170function completes, will be set to the actual number of levels returned. 171If there are more levels than 172.Fa count 173will allow, it should return 174.Er E2BIG . 175.Pp 176The 177.Fn cpufreq_get 178method takes a pointer to space to store a 179.Fa level . 180After successful completion, the output will be the current active level 181and is equal to one of the levels returned by 182.Fn cpufreq_levels . 183.Pp 184The 185.Fn cpufreq_set 186method takes a pointer a 187.Fa level 188and attempts to activate it. 189The 190.Fa priority 191(i.e., 192.Dv CPUFREQ_PRIO_KERN ) 193tells 194.Nm 195whether to override previous settings while activating this level. 196If 197.Fa priority 198is higher than the current active level, that level will be saved and 199overridden with the new level. 200If a level is already saved, the new level is set without overwriting 201the older saved level. 202If 203.Fn cpufreq_set 204is called with a 205.Dv NULL 206.Fa level , 207the saved level will be restored. 208If there is no saved level, 209.Fn cpufreq_set 210will return 211.Er ENXIO . 212If 213.Fa priority 214is lower than the current active level's priority, this method returns 215.Er EPERM . 216.Sh DRIVER INTERFACE 217Kernel drivers offering hardware-specific CPU frequency control export 218their individual settings through the 219.Nm 220driver interface. 221This involves implementing these methods: 222.Fn cpufreq_drv_settings , 223.Fn cpufreq_drv_type , 224.Fn cpufreq_drv_set , 225and 226.Fn cpufreq_drv_get . 227Additionally, the driver must attach a device as a child of a CPU 228device so that these methods can be called by the 229.Nm 230framework. 231.Pp 232The 233.Fn cpufreq_drv_settings 234method returns an array of currently available settings, each of type 235.Vt "struct cf_setting" . 236The driver should set unknown or irrelevant values to 237.Dv CPUFREQ_VAL_UNKNOWN . 238All the following elements for each setting should be returned: 239.Bd -literal 240struct cf_setting { 241 int freq; /* CPU clock in MHz or 100ths of a percent. */ 242 int volts; /* Voltage in mV. */ 243 int power; /* Power consumed in mW. */ 244 int lat; /* Transition latency in us. */ 245 device_t dev; /* Driver providing this setting. */ 246}; 247.Ed 248.Pp 249On entry to this method, 250.Fa count 251contains the number of settings that can be returned. 252On successful completion, the driver sets it to the actual number of 253settings returned. 254If the driver offers more settings than 255.Fa count 256will allow, it should return 257.Er E2BIG . 258.Pp 259The 260.Fn cpufreq_drv_type 261method indicates the type of settings it offers, either 262.Dv CPUFREQ_TYPE_ABSOLUTE 263or 264.Dv CPUFREQ_TYPE_RELATIVE . 265Additionally, the driver may set the 266.Dv CPUFREQ_FLAG_INFO_ONLY 267flag if the settings it provides are information for other drivers only 268and cannot be passed to 269.Fn cpufreq_drv_set 270to activate them. 271.Pp 272The 273.Fn cpufreq_drv_set 274method takes a driver setting and makes it active. 275If the setting is invalid or not currently available, it should return 276.Er EINVAL . 277.Pp 278The 279.Fn cpufreq_drv_get 280method returns the currently-active driver setting. 281The 282.Vt "struct cf_setting" 283returned must be valid for passing to 284.Fn cpufreq_drv_set , 285including all elements being filled out correctly. 286If the driver cannot infer the current setting 287(even by estimating it with 288.Fn cpu_est_clockrate ) 289then it should set all elements to 290.Dv CPUFREQ_VAL_UNKNOWN . 291.Sh SEE ALSO 292.Xr acpi 4 , 293.Xr est 4 , 294.Xr timecounters 4 , 295.Xr powerd 8 , 296.Xr sysctl 8 297.Sh AUTHORS 298.An Nate Lawson 299.An Bruno Ducrot 300contributed the 301.Pa powernow 302driver. 303.Sh BUGS 304The following drivers have not yet been converted to the 305.Nm 306interface: 307.Xr longrun 4 . 308.Pp 309Notification of CPU and bus frequency changes is not implemented yet. 310.Pp 311When multiple CPUs offer frequency control, they cannot be set to different 312levels and must all offer the same frequency settings. 313