| PSCI OS-initiated mode |
| ====================== |
| |
| :Author: Maulik Shah & Wing Li |
| :Organization: Qualcomm Innovation Center, Inc. & Google LLC |
| :Contact: Maulik Shah <quic_mkshah@quicinc.com> & Wing Li <wingers@google.com> |
| :Status: Accepted |
| |
| .. contents:: Table of Contents |
| |
| Introduction |
| ------------ |
| |
| Power state coordination |
| ^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| A power domain topology is a logical hierarchy of power domains in a system that |
| arises from the physical dependencies between power domains. |
| |
| Local power states describe power states for an individual node, and composite |
| power states describe the combined power states for an individual node and its |
| parent node(s). |
| |
| Entry into low-power states for a topology node above the core level requires |
| coordinating its children nodes. For example, in a system with a power domain |
| that encompasses a shared cache, and a separate power domain for each core that |
| uses the shared cache, the core power domains must be powered down before the |
| shared cache power domain can be powered down. |
| |
| PSCI supports two modes of power state coordination: platform-coordinated and |
| OS-initiated. |
| |
| Platform-coordinated |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| Platform-coordinated mode is the default mode of power state coordination, and |
| is currently the only supported mode in TF-A. |
| |
| In platform-coordinated mode, the platform is responsible for coordinating power |
| states, and chooses the deepest power state for a topology node that can be |
| tolerated by its children. |
| |
| OS-initiated |
| ~~~~~~~~~~~~ |
| |
| OS-initiated mode is optional. |
| |
| In OS-initiated mode, the calling OS is responsible for coordinating power |
| states, and may request for a topology node to enter a low-power state when |
| its last child enters the low-power state. |
| |
| Motivation |
| ---------- |
| |
| There are two reasons why OS-initiated mode might be a more suitable option than |
| platform-coordinated mode for a platform. |
| |
| Scalability |
| ^^^^^^^^^^^ |
| |
| In platform-coordinated mode, each core independently selects their own local |
| power states, and doesn't account for composite power states that are shared |
| between cores. |
| |
| In OS-initiated mode, the OS has knowledge of the next wakeup event for each |
| core, and can have more precise control over the entry, exit, and wakeup |
| latencies when deciding if a composite power state (e.g. for a cluster) is |
| appropriate. This is especially important for multi-cluster SMP systems and |
| heterogeneous systems like big.LITTLE, where different processor types can have |
| different power efficiencies. |
| |
| Simplicity |
| ^^^^^^^^^^ |
| |
| In platform-coordinated mode, the OS doesn't have visibility when the last core |
| at a power level enters a low-power state. If the OS wants to perform last man |
| activity (e.g. powering off a shared resource when it is no longer needed), it |
| would have to communicate with an API side channel to know when it can do so. |
| This could result in a design smell where the platform is using |
| platform-coordinated mode when it should be using OS-initiated mode instead. |
| |
| In OS-initiated mode, the OS can perform last man activity if it selects a |
| composite power state when the last core enters a low-power state. This |
| eliminates the need for a side channel, and uses the well documented API between |
| the OS and the platform. |
| |
| Current vendor implementations and workarounds |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| * STMicroelectronics |
| |
| * For their ARM32 platforms, they're using OS-initiated mode implemented in |
| OP-TEE. |
| * For their future ARM64 platforms, they are interested in using OS-initiated |
| mode in TF-A. |
| |
| * Qualcomm |
| |
| * For their mobile platforms, they're using OS-initiated mode implemented in |
| their own custom secure monitor firmware. |
| * For their Chrome OS platforms, they're using platform-coordinated mode in |
| TF-A with custom driver logic to perform last man activity. |
| |
| * Google |
| |
| * They're using platform-coordinated mode in TF-A with custom driver logic to |
| perform last man activity. |
| |
| Both Qualcomm and Google would like to be able to use OS-initiated mode in TF-A |
| in order to simplify custom driver logic. |
| |
| Requirements |
| ------------ |
| |
| PSCI_FEATURES |
| ^^^^^^^^^^^^^ |
| |
| PSCI_FEATURES is for checking whether or not a PSCI function is implemented and |
| what its properties are. |
| |
| .. c:macro:: PSCI_FEATURES |
| |
| :param func_id: 0x8400_000A. |
| :param psci_func_id: the function ID of a PSCI function. |
| :retval NOT_SUPPORTED: if the function is not implemented. |
| :retval feature flags associated with the function: if the function is |
| implemented. |
| |
| CPU_SUSPEND feature flags |
| ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| * Reserved, bits[31:2] |
| * Power state parameter format, bit[1] |
| |
| * A value of 0 indicates the original format is used. |
| * A value of 1 indicates the extended format is used. |
| |
| * OS-initiated mode, bit[0] |
| |
| * A value of 0 indicates OS-initiated mode is not supported. |
| * A value of 1 indicates OS-initiated mode is supported. |
| |
| See sections 5.1.14 and 5.15 of the PSCI spec (DEN0022D.b) for more details. |
| |
| PSCI_SET_SUSPEND_MODE |
| ^^^^^^^^^^^^^^^^^^^^^ |
| |
| PSCI_SET_SUSPEND_MODE is for switching between the two different modes of power |
| state coordination. |
| |
| .. c:macro:: PSCI_SET_SUSPEND_MODE |
| |
| :param func_id: 0x8400_000F. |
| :param mode: 0 indicates platform-coordinated mode, 1 indicates OS-initiated |
| mode. |
| :retval SUCCESS: if the request is successful. |
| :retval NOT_SUPPORTED: if OS-initiated mode is not supported. |
| :retval INVALID_PARAMETERS: if the requested mode is not a valid value (0 or |
| 1). |
| :retval DENIED: if the cores are not in the correct state. |
| |
| Switching from platform-coordinated to OS-initiated is only allowed if the |
| following conditions are met: |
| |
| * All cores are in one of the following states: |
| |
| * Running. |
| * Off, through a call to CPU_OFF or not yet booted. |
| * Suspended, through a call to CPU_DEFAULT_SUSPEND. |
| |
| * None of the cores has called CPU_SUSPEND since the last change of mode or |
| boot. |
| |
| Switching from OS-initiated to platform-coordinated is only allowed if all cores |
| other than the calling core are off, either through a call to CPU_OFF or not yet |
| booted. |
| |
| If these conditions are not met, the PSCI implementation must return DENIED. |
| |
| See sections 5.1.19 and 5.20 of the PSCI spec (DEN0022D.b) for more details. |
| |
| CPU_SUSPEND |
| ^^^^^^^^^^^ |
| |
| CPU_SUSPEND is for moving a topology node into a low-power state. |
| |
| .. c:macro:: CPU_SUSPEND |
| |
| :param func_id: 0xC400_0001. |
| :param power_state: the requested low-power state to enter. |
| :param entry_point_address: the address at which the core must resume |
| execution following wakeup from a powerdown state. |
| :param context_id: this field specifies a pointer to the saved context that |
| must be restored on a core following wakeup from a powerdown state. |
| :retval SUCCESS: if the request is successful. |
| :retval INVALID_PARAMETERS: in OS-initiated mode, this error is returned when |
| a low-power state is requested for a topology node above the core level, |
| and at least one of the node's children is in a local low-power state |
| that is incompatible with the request. |
| :retval INVALID_ADDRESS: if the entry_point_address argument is invalid. |
| :retval DENIED: only in OS-initiated mode; this error is returned when a |
| low-power state is requested for a topology node above the core level, |
| and at least one of the node's children is running, i.e. not in a |
| low-power state. |
| |
| In platform-coordinated mode, the PSCI implementation coordinates requests from |
| all cores to determine the deepest power state to enter. |
| |
| In OS-initiated mode, the calling OS is making an explicit request for a |
| specific power state, as opposed to expressing a vote. The PSCI implementation |
| must comply with the request, unless the request is not consistent with the |
| implementation's view of the system's state, in which case, the implementation |
| must return INVALID_PARAMETERS or DENIED. |
| |
| See sections 5.1.2 and 5.4 of the PSCI spec (DEN0022D.b) for more details. |
| |
| Power state formats |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| Original format |
| |
| * Power Level, bits[25:24] |
| |
| * The requested level in the power domain topology to enter a low-power |
| state. |
| |
| * State Type, bit[16] |
| |
| * A value of 0 indicates a standby or retention state. |
| * A value of 1 indicates a powerdown state. |
| |
| * State ID, bits[15:0] |
| |
| * Field to specify the requested composite power state. |
| * The state ID encodings must uniquely describe every possible composite |
| power state. |
| * In OS-initiated mode, the state ID encoding must allow expressing the |
| power level at which the calling core is the last to enter a powerdown |
| state. |
| |
| Extended format |
| |
| * State Type, bit[30] |
| * State ID, bits[27:0] |
| |
| Races in OS-initiated mode |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| In OS-initiated mode, there are race windows where the OS's view and |
| implementation's view of the system's state differ. It is possible for the OS to |
| make requests that are invalid given the implementation's view of the system's |
| state. For example, the OS might request a powerdown state for a node from one |
| core, while at the same time, the implementation observes that another core in |
| that node is powering up. |
| |
| To address potential race conditions in power state requests: |
| |
| * The calling OS must specify in each CPU_SUSPEND request the deepest power |
| level for which it sees the calling core as the last running core (last man). |
| This is required even if the OS doesn't want the node at that power level to |
| enter a low-power state. |
| * The implementation must validate that the requested power states in the |
| CPU_SUSPEND request are consistent with the system's state, and that the |
| calling core is the last core running at the requested power level, or deny |
| the request otherwise. |
| |
| See sections 4.2.3.2, 6.2, and 6.3 of the PSCI spec (DEN0022D.b) for more |
| details. |
| |
| Caveats |
| ------- |
| |
| CPU_OFF |
| ^^^^^^^ |
| |
| CPU_OFF is always platform-coordinated, regardless of whether the power state |
| coordination mode for suspend is platform-coordinated or OS-initiated. If all |
| cores in a topology node call CPU_OFF, the last core will power down the node. |
| |
| In OS-initiated mode, if a subset of the cores in a topology node has called |
| CPU_OFF, the last running core may call CPU_SUSPEND to request a powerdown state |
| at or above that node's power level. |
| |
| See section 5.5.2 of the PSCI spec (DEN0022D.b) for more details. |
| |
| Implementation |
| -------------- |
| |
| Current implementation of platform-coordinated mode |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Platform-coordinated is currently the only supported power state coordination |
| mode in TF-A. |
| |
| The functions of interest in the ``psci_cpu_suspend`` call stack are as follows: |
| |
| * ``psci_validate_power_state`` |
| |
| * This function calls a platform specific ``validate_power_state`` handler, |
| which takes the ``power_state`` parameter, and updates the ``state_info`` |
| object with the requested states for each power level. |
| |
| * ``psci_find_target_suspend_lvl`` |
| |
| * This function takes the ``state_info`` object containing the requested power |
| states for each power level, and returns the deepest power level that was |
| requested to enter a low power state, i.e. the target power level. |
| |
| * ``psci_do_state_coordination`` |
| |
| * This function takes the target power level and the ``state_info`` object |
| containing the requested power states for each power level, and updates the |
| ``state_info`` object with the coordinated target power state for each |
| level. |
| |
| * ``pwr_domain_suspend`` |
| |
| * This is a platform specific handler that takes the ``state_info`` object |
| containing the target power states for each power level, and transitions |
| each power level to the specified power state. |
| |
| Proposed implementation of OS-initiated mode |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| To add support for OS-initiated mode, the following changes are proposed: |
| |
| * Add a boolean build option ``PSCI_OS_INIT_MODE`` for a platform to enable |
| optional support for PSCI OS-initiated mode. This build option defaults to 0. |
| |
| .. note:: |
| |
| If ``PSCI_OS_INIT_MODE=0``, the following changes will not be compiled into |
| the build. |
| |
| * Update ``psci_features`` to return 1 in bit[0] to indicate support for |
| OS-initiated mode for CPU_SUSPEND. |
| * Define a ``suspend_mode`` enum: ``PLAT_COORD`` and ``OS_INIT``. |
| * Define a ``psci_suspend_mode`` global variable with a default value of |
| ``PLAT_COORD``. |
| * Implement a new function handler ``psci_set_suspend_mode`` for |
| PSCI_SET_SUSPEND_MODE. |
| * Since ``psci_validate_power_state`` calls a platform specific |
| ``validate_power_state`` handler, the platform implementation should populate |
| the ``state_info`` object based on the state ID from the given ``power_state`` |
| parameter. |
| * ``psci_find_target_suspend_lvl`` remains unchanged. |
| * Implement a new function ``psci_validate_state_coordination`` that ensures the |
| request satisfies the following conditions, and denies any requests |
| that don't: |
| |
| * The requested power states for each power level are consistent with the |
| system's state |
| * The calling core is the last core running at the requested power level |
| |
| This function differs from ``psci_do_state_coordination`` in that: |
| |
| * The ``psci_req_local_pwr_states`` map is not modified if the request were to |
| be denied |
| * The ``state_info`` argument is never modified since it contains the power |
| states requested by the calling OS |
| |
| * Update ``psci_cpu_suspend_start`` to do the following: |
| |
| * If ``PSCI_SUSPEND_MODE`` is ``PLAT_COORD``, call |
| ``psci_do_state_coordination``. |
| * If ``PSCI_SUSPEND_MODE`` is ``OS_INIT``, call |
| ``psci_validate_state_coordination``. If validation fails, propagate the |
| error up the call stack. |
| |
| * Add a new optional member ``pwr_domain_validate_suspend`` to |
| ``plat_psci_ops_t`` to allow the platform to optionally perform validations |
| based on hardware states. |
| |
| * The platform specific ``pwr_domain_suspend`` handler remains unchanged. |
| |
| .. image:: ../resources/diagrams/psci-osi-mode.png |
| |
| Testing |
| ------- |
| |
| The proposed patches can be found at |
| https://review.trustedfirmware.org/q/topic:psci-osi. |
| |
| Testing on FVP and Google platforms |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The proposed patches add a new CPU Suspend in OSI mode test suite to TF-A Tests. |
| This has been enabled and verified on the FVP_Base_RevC-2xAEMvA platform and |
| Google platforms, and excluded from all other platforms via the build option |
| ``PLAT_TESTS_SKIP_LIST``. |
| |
| Testing on STM32MP15 |
| ^^^^^^^^^^^^^^^^^^^^ |
| |
| The proposed patches have been tested and verified on the STM32MP15 platform, |
| which has a single cluster with 2 CPUs, by Gabriel Fernandez |
| <gabriel.fernandez@st.com> from STMicroelectronics with this device tree |
| configuration: |
| |
| .. code-block:: devicetree |
| |
| cpus { |
| #address-cells = <1>; |
| #size-cells = <0>; |
| |
| cpu0: cpu@0 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a7"; |
| reg = <0>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD0>; |
| power-domain-names = "psci"; |
| }; |
| cpu1: cpu@1 { |
| device_type = "cpu"; |
| compatible = "arm,cortex-a7"; |
| reg = <1>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD1>; |
| power-domain-names = "psci"; |
| }; |
| |
| idle-states { |
| cpu_retention: cpu-retention { |
| compatible = "arm,idle-state"; |
| arm,psci-suspend-param = <0x00000001>; |
| entry-latency-us = <130>; |
| exit-latency-us = <620>; |
| min-residency-us = <700>; |
| local-timer-stop; |
| }; |
| }; |
| |
| domain-idle-states { |
| CLUSTER_STOP: core-power-domain { |
| compatible = "domain-idle-state"; |
| arm,psci-suspend-param = <0x01000001>; |
| entry-latency-us = <230>; |
| exit-latency-us = <720>; |
| min-residency-us = <2000>; |
| local-timer-stop; |
| }; |
| }; |
| }; |
| |
| psci { |
| compatible = "arm,psci-1.0"; |
| method = "smc"; |
| |
| CPU_PD0: power-domain-cpu0 { |
| #power-domain-cells = <0>; |
| power-domains = <&pd_core>; |
| domain-idle-states = <&cpu_retention>; |
| }; |
| |
| CPU_PD1: power-domain-cpu1 { |
| #power-domain-cells = <0>; |
| power-domains = <&pd_core>; |
| domain-idle-states = <&cpu_retention>; |
| }; |
| |
| pd_core: power-domain-cluster { |
| #power-domain-cells = <0>; |
| domain-idle-states = <&CLUSTER_STOP>; |
| }; |
| }; |
| |
| Testing on Qualcomm SC7280 |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The proposed patches have been tested and verified on the SC7280 platform by |
| Maulik Shah <quic_mkshah@quicinc.com> from Qualcomm with this device tree |
| configuration: |
| |
| .. code-block:: devicetree |
| |
| cpus { |
| #address-cells = <2>; |
| #size-cells = <0>; |
| |
| CPU0: cpu@0 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x0>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD0>; |
| power-domain-names = "psci"; |
| }; |
| |
| CPU1: cpu@100 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x100>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD1>; |
| power-domain-names = "psci"; |
| }; |
| |
| CPU2: cpu@200 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x200>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD2>; |
| power-domain-names = "psci"; |
| }; |
| |
| CPU3: cpu@300 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x300>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD3>; |
| power-domain-names = "psci"; |
| } |
| |
| CPU4: cpu@400 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x400>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD4>; |
| power-domain-names = "psci"; |
| }; |
| |
| CPU5: cpu@500 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x500>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD5>; |
| power-domain-names = "psci"; |
| }; |
| |
| CPU6: cpu@600 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x600>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD6>; |
| power-domain-names = "psci"; |
| }; |
| |
| CPU7: cpu@700 { |
| device_type = "cpu"; |
| compatible = "arm,kryo"; |
| reg = <0x0 0x700>; |
| enable-method = "psci"; |
| power-domains = <&CPU_PD7>; |
| power-domain-names = "psci"; |
| }; |
| |
| idle-states { |
| entry-method = "psci"; |
| |
| LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { |
| compatible = "arm,idle-state"; |
| idle-state-name = "little-power-down"; |
| arm,psci-suspend-param = <0x40000003>; |
| entry-latency-us = <549>; |
| exit-latency-us = <901>; |
| min-residency-us = <1774>; |
| local-timer-stop; |
| }; |
| |
| LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 { |
| compatible = "arm,idle-state"; |
| idle-state-name = "little-rail-power-down"; |
| arm,psci-suspend-param = <0x40000004>; |
| entry-latency-us = <702>; |
| exit-latency-us = <915>; |
| min-residency-us = <4001>; |
| local-timer-stop; |
| }; |
| |
| BIG_CPU_SLEEP_0: cpu-sleep-1-0 { |
| compatible = "arm,idle-state"; |
| idle-state-name = "big-power-down"; |
| arm,psci-suspend-param = <0x40000003>; |
| entry-latency-us = <523>; |
| exit-latency-us = <1244>; |
| min-residency-us = <2207>; |
| local-timer-stop; |
| }; |
| |
| BIG_CPU_SLEEP_1: cpu-sleep-1-1 { |
| compatible = "arm,idle-state"; |
| idle-state-name = "big-rail-power-down"; |
| arm,psci-suspend-param = <0x40000004>; |
| entry-latency-us = <526>; |
| exit-latency-us = <1854>; |
| min-residency-us = <5555>; |
| local-timer-stop; |
| }; |
| }; |
| |
| domain-idle-states { |
| CLUSTER_SLEEP_0: cluster-sleep-0 { |
| compatible = "arm,idle-state"; |
| idle-state-name = "cluster-power-down"; |
| arm,psci-suspend-param = <0x40003444>; |
| entry-latency-us = <3263>; |
| exit-latency-us = <6562>; |
| min-residency-us = <9926>; |
| local-timer-stop; |
| }; |
| }; |
| }; |
| |
| psci { |
| compatible = "arm,psci-1.0"; |
| method = "smc"; |
| |
| CPU_PD0: cpu0 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD1: cpu1 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD2: cpu2 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD3: cpu3 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&LITTLE_CPU_SLEEP_0 &LITTLE_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD4: cpu4 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD5: cpu5 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD6: cpu6 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; |
| }; |
| |
| CPU_PD7: cpu7 { |
| #power-domain-cells = <0>; |
| power-domains = <&CLUSTER_PD>; |
| domain-idle-states = <&BIG_CPU_SLEEP_0 &BIG_CPU_SLEEP_1>; |
| }; |
| |
| CLUSTER_PD: cpu-cluster0 { |
| #power-domain-cells = <0>; |
| domain-idle-states = <&CLUSTER_SLEEP_0>; |
| }; |
| }; |
| |
| Comparisons on Qualcomm SC7280 |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| CPUIdle states |
| ~~~~~~~~~~~~~~ |
| |
| * 8 CPUs, 1 L3 cache |
| * Platform-coordinated mode |
| |
| * CPUIdle states |
| |
| * State0 - WFI |
| * State1 - Core collapse |
| * State2 - Rail collapse |
| * State3 - L3 cache off and system resources voted off |
| |
| * OS-initiated mode |
| |
| * CPUIdle states |
| |
| * State0 - WFI |
| * State1 - Core collapse |
| * State2 - Rail collapse |
| |
| * Cluster domain idle state |
| |
| * State3 - L3 cache off and system resources voted off |
| |
| .. image:: ../resources/diagrams/psci-flattened-vs-hierarchical-idle-states.png |
| |
| Results |
| ~~~~~~~ |
| |
| * The following stats have been captured with fixed CPU frequencies from the use |
| case of 10 seconds of device idle with the display turned on and Wi-Fi and |
| modem turned off. |
| * Count refers to the number of times a CPU or cluster entered power collapse. |
| * Residency refers to the time in seconds a CPU or cluster stayed in power |
| collapse. |
| * The results are an average of 3 iterations of actual counts and residencies. |
| |
| .. image:: ../resources/diagrams/psci-pc-mode-vs-osi-mode.png |
| |
| OS-initiated mode was able to scale better than platform-coordinated mode for |
| multiple CPUs. The count and residency results for state3 (i.e. a cluster domain |
| idle state) in OS-initiated mode for multiple CPUs were much closer to the |
| results for a single CPU than in platform-coordinated mode. |
| |
| -------------- |
| |
| *Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.* |