| .. SPDX-License-Identifier: GPL-2.0 |
| .. include:: <isonum.txt> |
| |
| ======================== |
| CPU Idle Time Management |
| ======================== |
| |
| :Copyright: |copy| 2019 Intel Corporation |
| |
| :Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| |
| |
| CPU Idle Time Management Subsystem |
| ================================== |
| |
| Every time one of the logical CPUs in the system (the entities that appear to |
| fetch and execute instructions: hardware threads, if present, or processor |
| cores) is idle after an interrupt or equivalent wakeup event, which means that |
| there are no tasks to run on it except for the special "idle" task associated |
| with it, there is an opportunity to save energy for the processor that it |
| belongs to. That can be done by making the idle logical CPU stop fetching |
| instructions from memory and putting some of the processor's functional units |
| depended on by it into an idle state in which they will draw less power. |
| |
| However, there may be multiple different idle states that can be used in such a |
| situation in principle, so it may be necessary to find the most suitable one |
| (from the kernel perspective) and ask the processor to use (or "enter") that |
| particular idle state. That is the role of the CPU idle time management |
| subsystem in the kernel, called ``CPUIdle``. |
| |
| The design of ``CPUIdle`` is modular and based on the code duplication avoidance |
| principle, so the generic code that in principle need not depend on the hardware |
| or platform design details in it is separate from the code that interacts with |
| the hardware. It generally is divided into three categories of functional |
| units: *governors* responsible for selecting idle states to ask the processor |
| to enter, *drivers* that pass the governors' decisions on to the hardware and |
| the *core* providing a common framework for them. |
| |
| |
| CPU Idle Time Governors |
| ======================= |
| |
| A CPU idle time (``CPUIdle``) governor is a bundle of policy code invoked when |
| one of the logical CPUs in the system turns out to be idle. Its role is to |
| select an idle state to ask the processor to enter in order to save some energy. |
| |
| ``CPUIdle`` governors are generic and each of them can be used on any hardware |
| platform that the Linux kernel can run on. For this reason, data structures |
| operated on by them cannot depend on any hardware architecture or platform |
| design details as well. |
| |
| The governor itself is represented by a struct cpuidle_governor object |
| containing four callback pointers, :c:member:`enable`, :c:member:`disable`, |
| :c:member:`select`, :c:member:`reflect`, a :c:member:`rating` field described |
| below, and a name (string) used for identifying it. |
| |
| For the governor to be available at all, that object needs to be registered |
| with the ``CPUIdle`` core by calling :c:func:`cpuidle_register_governor()` with |
| a pointer to it passed as the argument. If successful, that causes the core to |
| add the governor to the global list of available governors and, if it is the |
| only one in the list (that is, the list was empty before) or the value of its |
| :c:member:`rating` field is greater than the value of that field for the |
| governor currently in use, or the name of the new governor was passed to the |
| kernel as the value of the ``cpuidle.governor=`` command line parameter, the new |
| governor will be used from that point on (there can be only one ``CPUIdle`` |
| governor in use at a time). Also, user space can choose the ``CPUIdle`` |
| governor to use at run time via ``sysfs``. |
| |
| Once registered, ``CPUIdle`` governors cannot be unregistered, so it is not |
| practical to put them into loadable kernel modules. |
| |
| The interface between ``CPUIdle`` governors and the core consists of four |
| callbacks: |
| |
| :c:member:`enable` |
| :: |
| |
| int (*enable) (struct cpuidle_driver *drv, struct cpuidle_device *dev); |
| |
| The role of this callback is to prepare the governor for handling the |
| (logical) CPU represented by the struct cpuidle_device object pointed |
| to by the ``dev`` argument. The struct cpuidle_driver object pointed |
| to by the ``drv`` argument represents the ``CPUIdle`` driver to be used |
| with that CPU (among other things, it should contain the list of |
| struct cpuidle_state objects representing idle states that the |
| processor holding the given CPU can be asked to enter). |
| |
| It may fail, in which case it is expected to return a negative error |
| code, and that causes the kernel to run the architecture-specific |
| default code for idle CPUs on the CPU in question instead of ``CPUIdle`` |
| until the ``->enable()`` governor callback is invoked for that CPU |
| again. |
| |
| :c:member:`disable` |
| :: |
| |
| void (*disable) (struct cpuidle_driver *drv, struct cpuidle_device *dev); |
| |
| Called to make the governor stop handling the (logical) CPU represented |
| by the struct cpuidle_device object pointed to by the ``dev`` |
| argument. |
| |
| It is expected to reverse any changes made by the ``->enable()`` |
| callback when it was last invoked for the target CPU, free all memory |
| allocated by that callback and so on. |
| |
| :c:member:`select` |
| :: |
| |
| int (*select) (struct cpuidle_driver *drv, struct cpuidle_device *dev, |
| bool *stop_tick); |
| |
| Called to select an idle state for the processor holding the (logical) |
| CPU represented by the struct cpuidle_device object pointed to by the |
| ``dev`` argument. |
| |
| The list of idle states to take into consideration is represented by the |
| :c:member:`states` array of struct cpuidle_state objects held by the |
| struct cpuidle_driver object pointed to by the ``drv`` argument (which |
| represents the ``CPUIdle`` driver to be used with the CPU at hand). The |
| value returned by this callback is interpreted as an index into that |
| array (unless it is a negative error code). |
| |
| The ``stop_tick`` argument is used to indicate whether or not to stop |
| the scheduler tick before asking the processor to enter the selected |
| idle state. When the ``bool`` variable pointed to by it (which is set |
| to ``true`` before invoking this callback) is cleared to ``false``, the |
| processor will be asked to enter the selected idle state without |
| stopping the scheduler tick on the given CPU (if the tick has been |
| stopped on that CPU already, however, it will not be restarted before |
| asking the processor to enter the idle state). |
| |
| This callback is mandatory (i.e. the :c:member:`select` callback pointer |
| in struct cpuidle_governor must not be ``NULL`` for the registration |
| of the governor to succeed). |
| |
| :c:member:`reflect` |
| :: |
| |
| void (*reflect) (struct cpuidle_device *dev, int index); |
| |
| Called to allow the governor to evaluate the accuracy of the idle state |
| selection made by the ``->select()`` callback (when it was invoked last |
| time) and possibly use the result of that to improve the accuracy of |
| idle state selections in the future. |
| |
| In addition, ``CPUIdle`` governors are required to take power management |
| quality of service (PM QoS) constraints on the processor wakeup latency into |
| account when selecting idle states. In order to obtain the current effective |
| PM QoS wakeup latency constraint for a given CPU, a ``CPUIdle`` governor is |
| expected to pass the number of the CPU to |
| :c:func:`cpuidle_governor_latency_req()`. Then, the governor's ``->select()`` |
| callback must not return the index of an indle state whose |
| :c:member:`exit_latency` value is greater than the number returned by that |
| function. |
| |
| |
| CPU Idle Time Management Drivers |
| ================================ |
| |
| CPU idle time management (``CPUIdle``) drivers provide an interface between the |
| other parts of ``CPUIdle`` and the hardware. |
| |
| First of all, a ``CPUIdle`` driver has to populate the :c:member:`states` array |
| of struct cpuidle_state objects included in the struct cpuidle_driver object |
| representing it. Going forward this array will represent the list of available |
| idle states that the processor hardware can be asked to enter shared by all of |
| the logical CPUs handled by the given driver. |
| |
| The entries in the :c:member:`states` array are expected to be sorted by the |
| value of the :c:member:`target_residency` field in struct cpuidle_state in |
| the ascending order (that is, index 0 should correspond to the idle state with |
| the minimum value of :c:member:`target_residency`). [Since the |
| :c:member:`target_residency` value is expected to reflect the "depth" of the |
| idle state represented by the struct cpuidle_state object holding it, this |
| sorting order should be the same as the ascending sorting order by the idle |
| state "depth".] |
| |
| Three fields in struct cpuidle_state are used by the existing ``CPUIdle`` |
| governors for computations related to idle state selection: |
| |
| :c:member:`target_residency` |
| Minimum time to spend in this idle state including the time needed to |
| enter it (which may be substantial) to save more energy than could |
| be saved by staying in a shallower idle state for the same amount of |
| time, in microseconds. |
| |
| :c:member:`exit_latency` |
| Maximum time it will take a CPU asking the processor to enter this idle |
| state to start executing the first instruction after a wakeup from it, |
| in microseconds. |
| |
| :c:member:`flags` |
| Flags representing idle state properties. Currently, governors only use |
| the ``CPUIDLE_FLAG_POLLING`` flag which is set if the given object |
| does not represent a real idle state, but an interface to a software |
| "loop" that can be used in order to avoid asking the processor to enter |
| any idle state at all. [There are other flags used by the ``CPUIdle`` |
| core in special situations.] |
| |
| The :c:member:`enter` callback pointer in struct cpuidle_state, which must not |
| be ``NULL``, points to the routine to execute in order to ask the processor to |
| enter this particular idle state: |
| |
| :: |
| |
| void (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, |
| int index); |
| |
| The first two arguments of it point to the struct cpuidle_device object |
| representing the logical CPU running this callback and the |
| struct cpuidle_driver object representing the driver itself, respectively, |
| and the last one is an index of the struct cpuidle_state entry in the driver's |
| :c:member:`states` array representing the idle state to ask the processor to |
| enter. |
| |
| The analogous ``->enter_s2idle()`` callback in struct cpuidle_state is used |
| only for implementing the suspend-to-idle system-wide power management feature. |
| The difference between in and ``->enter()`` is that it must not re-enable |
| interrupts at any point (even temporarily) or attempt to change the states of |
| clock event devices, which the ``->enter()`` callback may do sometimes. |
| |
| Once the :c:member:`states` array has been populated, the number of valid |
| entries in it has to be stored in the :c:member:`state_count` field of the |
| struct cpuidle_driver object representing the driver. Moreover, if any |
| entries in the :c:member:`states` array represent "coupled" idle states (that |
| is, idle states that can only be asked for if multiple related logical CPUs are |
| idle), the :c:member:`safe_state_index` field in struct cpuidle_driver needs |
| to be the index of an idle state that is not "coupled" (that is, one that can be |
| asked for if only one logical CPU is idle). |
| |
| In addition to that, if the given ``CPUIdle`` driver is only going to handle a |
| subset of logical CPUs in the system, the :c:member:`cpumask` field in its |
| struct cpuidle_driver object must point to the set (mask) of CPUs that will be |
| handled by it. |
| |
| A ``CPUIdle`` driver can only be used after it has been registered. If there |
| are no "coupled" idle state entries in the driver's :c:member:`states` array, |
| that can be accomplished by passing the driver's struct cpuidle_driver object |
| to :c:func:`cpuidle_register_driver()`. Otherwise, :c:func:`cpuidle_register()` |
| should be used for this purpose. |
| |
| However, it also is necessary to register struct cpuidle_device objects for |
| all of the logical CPUs to be handled by the given ``CPUIdle`` driver with the |
| help of :c:func:`cpuidle_register_device()` after the driver has been registered |
| and :c:func:`cpuidle_register_driver()`, unlike :c:func:`cpuidle_register()`, |
| does not do that automatically. For this reason, the drivers that use |
| :c:func:`cpuidle_register_driver()` to register themselves must also take care |
| of registering the struct cpuidle_device objects as needed, so it is generally |
| recommended to use :c:func:`cpuidle_register()` for ``CPUIdle`` driver |
| registration in all cases. |
| |
| The registration of a struct cpuidle_device object causes the ``CPUIdle`` |
| ``sysfs`` interface to be created and the governor's ``->enable()`` callback to |
| be invoked for the logical CPU represented by it, so it must take place after |
| registering the driver that will handle the CPU in question. |
| |
| ``CPUIdle`` drivers and struct cpuidle_device objects can be unregistered |
| when they are not necessary any more which allows some resources associated with |
| them to be released. Due to dependencies between them, all of the |
| struct cpuidle_device objects representing CPUs handled by the given |
| ``CPUIdle`` driver must be unregistered, with the help of |
| :c:func:`cpuidle_unregister_device()`, before calling |
| :c:func:`cpuidle_unregister_driver()` to unregister the driver. Alternatively, |
| :c:func:`cpuidle_unregister()` can be called to unregister a ``CPUIdle`` driver |
| along with all of the struct cpuidle_device objects representing CPUs handled |
| by it. |
| |
| ``CPUIdle`` drivers can respond to runtime system configuration changes that |
| lead to modifications of the list of available processor idle states (which can |
| happen, for example, when the system's power source is switched from AC to |
| battery or the other way around). Upon a notification of such a change, |
| a ``CPUIdle`` driver is expected to call :c:func:`cpuidle_pause_and_lock()` to |
| turn ``CPUIdle`` off temporarily and then :c:func:`cpuidle_disable_device()` for |
| all of the struct cpuidle_device objects representing CPUs affected by that |
| change. Next, it can update its :c:member:`states` array in accordance with |
| the new configuration of the system, call :c:func:`cpuidle_enable_device()` for |
| all of the relevant struct cpuidle_device objects and invoke |
| :c:func:`cpuidle_resume_and_unlock()` to allow ``CPUIdle`` to be used again. |