Hello. The kernel needs a MI interface for CPU frequency scaling. Below is a draft that is deliberately as simple as possible.
This is NOT about frequency scaling done by the kernel as a "governor" (although the long-term goal should point to that direction). The present goal is just to add a simple MI "interface" (or rather, wrapper) and abstract away machine- and platform-dependent code and user interfaces. As far as the implementation goes, this would add two simple MD callback functions to cpu_info. All ugly MD sysctls would be deprecated and setting the frequency would be done by cpuctl(8) via these callbacks.[1] The only interesting detail is that the term "CPU frequency" is defined as a percentage value: 100 % implies "full performance" and 0 % denotes the "lowest performance". This follows OpenBSD, being also one of the few possible ways to define "CPU frequency levels" independently from the machine. All details are left to the MD implementations, including how to translate the percentage to actual frequency (and/or voltage, etc.). For instance, for systems with only two states, all values higher than zero would set the "high performance mode".[2] Comments? - Jukka. [1] The currently known users would include x86 (with five (!) different implementations) and PowerPC, but frequency scaling is nowadays widely used also in the ARM realm. [2] Note that even in the x86 land it is no longer necessarily known which is the exact MHz at which the CPU currently runs (cf. TurboBoost, etc.). * * * CPUFREQ(9) NetBSD Kernel Developer's Manual CPUFREQ(9) NAME cpufreq -- interface for CPU frequency scaling SYNOPSIS #include <sys/cpufreq.h> void cpufreq_register(cpufreq_get_cb *get, cpufreq_set_cb *set, void *aux); bool cpufreq_get(struct cpu_info *ci, uint8_t *valp); bool cpufreq_set(struct cpu_info *ci, const uint8_t val); DESCRIPTION The machine-independent cpufreq interface provides a simple framework for CPU frequency scaling. 1. The cpufreq interface uses percentage values in place of actual frequencies. Thus, values 100 % and 0 % denote the highest and lowest frequency supported by the CPU. It is the responsibility of machine-dependent implementations to trans- late the percentage values to actual frequencies or other related performance levels. 2. The cpufreq interface is stateless and does no locking while calling the machine-dependent callbacks. 3. The cpufreq interface is a per-CPU framework. It is implic- itly assumed that the frequency can be set independently for all processors in the system. However, cpufreq does not imply any restrictions upon whether this information is utilized by the actual machine-dependent implementation. FUNCTIONS cpufreq_register(get, set) The cpufreq_register() function initializes the subsystem by associating the machine-dependent callback functions get and set with the machine-independent cpufreq_get() and cpufreq_set(), respectively. The cpufreq_set_cb and cpufreq_get_cb types are function pointers defined as: bool (*get)(struct cpuinfo_t *ci, void *aux, uint8_t *valp) bool (*set)(struct cpuinfo_t *ci, void *aux, const uint8_t val) Note that cpufreq does not keep track of the registered call- backs. Each call to cpufreq_register() will override any exist- ing callbacks. cpufreq_get(ci, valp) The cpufreq_get() function obtains the current frequency level of the CPU pointed by ci in the parameter valp. cpufreq_set(ci, val) The cpufreq_set() function sets the performance level of ci to val. The value val is guaranteed to be in the range [0, 100]. CODE REFERENCES The cpufreq subsystem is implemented within sys/kern/subr_cpufreq.c. SEE ALSO cpuctl(8) HISTORY The cpufreq subsystem first appeared in NetBSD 6.0.