요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
==============================================
``intel_idle`` CPU Idle Time Management Driver
==============================================
:Copyright: |copy| 2020 Intel Corporation
:Author: Rafael J. Wysocki <[email protected]>
General Information
===================
``intel_idle`` is a part of the
:doc:`CPU idle time management subsystem <cpuidle>` in the Linux kernel
(``CPUIdle``). It is the default CPU idle time management driver for the
Nehalem and later generations of Intel processors, but the level of support for
a particular processor model in it depends on whether or not it recognizes that
processor model and may also depend on information coming from the platform
firmware. [To understand ``intel_idle`` it is necessary to know how ``CPUIdle``
works in general, so this is the time to get familiar with
Documentation/admin-guide/pm/cpuidle.rst if you have not done that yet.]
``intel_idle`` uses the ``MWAIT`` instruction to inform the processor that the
logical CPU executing it is idle and so it may be possible to put some of the
processor's functional blocks into low-power states. That instruction takes two
arguments (passed in the ``EAX`` and ``ECX`` registers of the target CPU), the
first of which, referred to as a *hint*, can be used by the processor to
determine what can be done (for details refer to Intel Software Developer’s
Manual [1]_). Accordingly, ``intel_idle`` refuses to work with processors in
which the support for the ``MWAIT`` instruction has been disabled (for example,
via the platform firmware configuration menu) or which do not support that
instruction at all.
``intel_idle`` is not modular, so it cannot be unloaded, which means that the
only way to pass early-configuration-time parameters to it is via the kernel
command line.
Sysfs Interface
===============
The ``intel_idle`` driver exposes the following ``sysfs`` attributes in
``/sys/devices/system/cpu/cpuidle/``:
``intel_c1_demotion``
Enable or disable C1 demotion for all CPUs in the system. This file is
only exposed on platforms that support the C1 demotion feature and where
it was tested. Value 0 means that C1 demotion is disabled, value 1 means
that it is enabled. Write 0 or 1 to disable or enable C1 demotion for
all CPUs.
The C1 demotion feature involves the platform firmware demoting deep
C-state requests from the OS (e.g., C6 requests) to C1. The idea is that
firmware monitors CPU wake-up rate, and if it is higher than a
platform-specific threshold, the firmware demotes deep C-state requests
to C1. For example, Linux requests C6, but firmware noticed too many
wake-ups per second, and it keeps the CPU in C1. When the CPU stays in
C1 long enough, the platform promotes it back to C6. This may improve
some workloads' performance, but it may also increase power consumption.
.. _intel-idle-enumeration-of-states:
Enumeration of Idle States
==========================
Each ``MWAIT`` hint value is interpreted by the processor as a license to
reconfigure itself in a certain way in order to save energy. The processor
configurations (with reduced power draw) resulting from that are referred to
as C-states (in the ACPI terminology) or idle states. The list of meaningful
``MWAIT`` hint values and idle states (i.e. low-power configurations of the
processor) corresponding to them depends on the processor model and it may also
depend on the configuration of the platform.
In order to create a list of available idle states required by the ``CPUIdle``
subsystem (see :ref:`idle-states-representation` in
Documentation/admin-guide/pm/cpuidle.rst),
``intel_idle`` can use two sources of information: static tables of idle states
for different processor models included in the driver itself and the ACPI tables
of the system. The former are always used if the processor model at hand is
recognized by ``intel_idle`` and the latter are used if that is required for
the given processor model (which is the case for all server processor models
recognized by ``intel_idle``) or if the processor model is not recognized.
[There is a module parameter that can be used to make the driver use the ACPI
tables with any processor model recognized by it; see
`below <intel-idle-parameters_>`_.]
If the ACPI tables are going to be used for building the list of available idle
states, ``intel_idle`` first looks for a ``_CST`` object under one of the ACPI
objects corresponding to the CPUs in the system (refer to the ACPI specification
[2]_ for the description of ``_CST`` and its output package). Because the
``CPUIdle`` subsystem expects that the list of idle states supplied by the
driver will be suitable for all of the CPUs handled by it and ``intel_idle`` is
registered as the ``CPUIdle`` driver for all of the CPUs in the system, the
driver looks for the first ``_CST`` object returning at least one valid idle
state description and such that all of the idle states included in its return
package are of the FFH (Functional Fixed Hardware) type, which means that the
``MWAIT`` instruction is expected to be used to tell the processor that it can
enter one of them. The return package of that ``_CST`` is then assumed to be
applicable to all of the other CPUs in the system and the idle state
descriptions extracted from it are stored in a preliminary list of idle states
coming from the ACPI tables. [This step is skipped if ``intel_idle`` is
configured to ignore the ACPI tables; see `below <intel-idle-parameters_>`_.]
Next, the first (index 0) entry in the list of available idle states is
initialized to represent a "polling idle state" (a pseudo-idle state in which
the target CPU continuously fetches and executes instructions), and the
subsequent (real) idle state entries are populated as follows.
If the processor model at hand is recognized by ``intel_idle``, there is a
(static) table of idle state descriptions for it in the driver. In that case,
the "internal" table is the primary source of information on idle states and the
information from it is copied to the final list of available idle states. If
using the ACPI tables for the enumeration of idle states is not required
(depending on the processor model), all of the listed idle state are enabled by
default (so all of them will be taken into consideration by ``CPUIdle``
governors during CPU idle state selection). Otherwise, some of the listed idle
states may not be enabled by default if there are no matching entries in the
preliminary list of idle states coming from the ACPI tables. In that case user
space still can enable them later (on a per-CPU basis) with the help of
the ``disable`` idle state attribute in ``sysfs`` (see
:ref:`idle-states-representation` in
Documentation/admin-guide/pm/cpuidle.rst). This basically means that
the idle states "known" to the driver may not be enabled by default if they have
not been exposed by the platform firmware (through the ACPI tables).
If the given processor model is not recognized by ``intel_idle``, but it
supports ``MWAIT``, the preliminary list of idle states coming from the ACPI
tables is used for building the final list that will be supplied to the
``CPUIdle`` core during driver registration. For each idle state in that list,
the description, ``MWAIT`` hint and exit latency are copied to the corresponding
entry in the final list of idle states. The name of the idle state represented
by it (to be returned by the ``name`` idle state attribute in ``sysfs``) is
"CX_ACPI", where X is the index of that idle state in the final list (note that
the minimum value of X is 1, because 0 is reserved for the "polling" state), and
its target residency is based on the exit latency value. Specifically, for
C1-type idle states the exit latency value is also used as the target residency
(for compatibility with the majority of the "internal" tables of idle states for
various processor models recognized by ``intel_idle``) and for the other idle
state types (C2 and C3) the target residency value is 3 times the exit latency
(again, that is because it reflects the target residency to exit latency ratio
in the majority of cases for the processor models recognized by ``intel_idle``).
All of the idle states in the final list are enabled by default in this case.
.. _intel-idle-initialization:
Initialization
==============
The initialization of ``intel_idle`` starts with checking if the kernel command
line options forbid the use of the ``MWAIT`` instruction. If that is the case,
an error code is returned right away.
The next step is to check whether or not the processor model is known to the
driver, which determines the idle states enumeration method (see
`above <intel-idle-enumeration-of-states_>`_), and whether or not the processor
supports ``MWAIT`` (the initialization fails if that is not the case). Then,
the ``MWAIT`` support in the processor is enumerated through ``CPUID`` and the
driver initialization fails if the level of support is not as expected (for
example, if the total number of ``MWAIT`` substates returned is 0).
Next, if the driver is not configured to ignore the ACPI tables (see
`below <intel-idle-parameters_>`_), the idle states information provided by the
platform firmware is extracted from them.
Then, ``CPUIdle`` device objects are allocated for all CPUs and the list of
available idle states is created as explained
`above <intel-idle-enumeration-of-states_>`_.
Finally, ``intel_idle`` is registered with the help of cpuidle_register_driver()
as the ``CPUIdle`` driver for all CPUs in the system and a CPU online callback
for configuring individual CPUs is registered via cpuhp_setup_state(), which
(among other things) causes the callback routine to be invoked for all of the
CPUs present in the system at that time (each CPU executes its own instance of
the callback routine). That routine registers a ``CPUIdle`` device for the CPU
running it (which enables the ``CPUIdle`` subsystem to operate that CPU) and
optionally performs some CPU-specific initialization actions that may be
required for the given processor model.
.. _intel-idle-parameters:
Kernel Command Line Options and Module Parameters
=================================================
The *x86* architecture support code recognizes three kernel command line
options related to CPU idle time management: ``idle=poll``, ``idle=halt``,
and ``idle=nomwait``. If any of them is present in the kernel command line, the
``MWAIT`` instruction is not allowed to be used, so the initialization of
``intel_idle`` will fail.
Apart from that there are five module parameters recognized by ``intel_idle``
itself that can be set via the kernel command line (they cannot be updated via
sysfs, so that is the only way to change their values).
The ``max_cstate`` parameter value is the maximum idle state index in the list
of idle states supplied to the ``CPUIdle`` core during the registration of the
driver. It is also the maximum number of regular (non-polling) idle states that
can be used by ``intel_idle``, so the enumeration of idle states is terminated
after finding that number of usable idle states (the other idle states that
potentially might have been used if ``max_cstate`` had been greater are not
taken into consideration at all). Setting ``max_cstate`` can prevent
``intel_idle`` from exposing idle states that are regarded as "too deep" for
some reason to the ``CPUIdle`` core, but it does so by making them effectively
invisible until the system is shut down and started again which may not always
be desirable. In practice, it is only really necessary to do that if the idle
states in question cannot be enabled during system startup, because in the
working state of the system the CPU power management quality of service (PM
QoS) feature can be used to prevent ``CPUIdle`` from touching those idle states
even if they have been enumerated (see :ref:`cpu-pm-qos` in
Documentation/admin-guide/pm/cpuidle.rst).
Setting ``max_cstate`` to 0 causes the ``intel_idle`` initialization to fail.
The ``no_acpi``, ``use_acpi`` and ``no_native`` module parameters are
recognized by ``intel_idle`` if the kernel has been configured with ACPI
support. In the case that ACPI is not configured these flags have no impact
on functionality.
``no_acpi`` - Do not use ACPI at all. Only native mode is available, no
ACPI mode.
``use_acpi`` - No-op in ACPI mode, the driver will consult ACPI tables for
C-states on/off status in native mode.
``no_native`` - Work only in ACPI mode, no native mode available (ignore
all custom tables).
The value of the ``states_off`` module parameter (0 by default) represents a
list of idle states to be disabled by default in the form of a bitmask.
Namely, the positions of the bits that are set in the ``states_off`` value are
the indices of idle states to be disabled by default (as reflected by the names
of the corresponding idle state directories in ``sysfs``, :file:`state0`,
:file:`state1` ... :file:`state<i>` ..., where ``<i>`` is the index of the given
idle state; see :ref:`idle-states-representation` in
Documentation/admin-guide/pm/cpuidle.rst).
For example, if ``states_off`` is equal to 3, the driver will disable idle
states 0 and 1 by default, and if it is equal to 8, idle state 3 will be
disabled by default and so on (bit positions beyond the maximum idle state index
are ignored).
The idle states disabled this way can be enabled (on a per-CPU basis) from user
space via ``sysfs``.
The ``ibrs_off`` module parameter is a boolean flag (defaults to
false). If set, it is used to control if IBRS (Indirect Branch Restricted
Speculation) should be turned off when the CPU enters an idle state.
This flag does not affect CPUs that use Enhanced IBRS which can remain
on with little performance impact.
For some CPUs, IBRS will be selected as mitigation for Spectre v2 and Retbleed
security vulnerabilities by default. Leaving the IBRS mode on while idling may
have a performance impact on its sibling CPU. The IBRS mode will be turned off
by default when the CPU enters into a deep idle state, but not in some
shallower ones. Setting the ``ibrs_off`` module parameter will force the IBRS
mode to off when the CPU is in any one of the available idle states. This may
help performance of a sibling CPU at the expense of a slightly higher wakeup
latency for the idle CPU.
.. _intel-idle-core-and-package-idle-states:
Core and Package Levels of Idle States
======================================
Typically, in a processor supporting the ``MWAIT`` instruction there are (at
least) two levels of idle states (or C-states). One level, referred to as
"core C-states", covers individual cores in the processor, whereas the other
level, referred to as "package C-states", covers the entire processor package
and it may also involve other components of the system (GPUs, memory
controllers, I/O hubs etc.).
Some of the ``MWAIT`` hint values allow the processor to use core C-states only
(most importantly, that is the case for the ``MWAIT`` hint value corresponding
to the ``C1`` idle state), but the majority of them give it a license to put
the target core (i.e. the core containing the logical CPU executing ``MWAIT``
with the given hint value) into a specific core C-state and then (if possible)
to enter a specific package C-state at the deeper level. For example, the
``MWAIT`` hint value representing the ``C3`` idle state allows the processor to
put the target core into the low-power state referred to as "core ``C3``" (or
``CC3``), which happens if all of the logical CPUs (SMT siblings) in that core
have executed ``MWAIT`` with the ``C3`` hint value (or with a hint value
representing a deeper idle state), and in addition to that (in the majority of
cases) it gives the processor a license to put the entire package (possibly
including some non-CPU components such as a GPU or a memory controller) into the
low-power state referred to as "package ``C3``" (or ``PC3``), which happens if
all of the cores have gone into the ``CC3`` state and (possibly) some additional
conditions are satisfied (for instance, if the GPU is covered by ``PC3``, it may
be required to be in a certain GPU-specific low-power state for ``PC3`` to be
reachable).
As a rule, there is no simple way to make the processor use core C-states only
if the conditions for entering the corresponding package C-states are met, so
the logical CPU executing ``MWAIT`` with a hint value that is not core-level
only (like for ``C1``) must always assume that this may cause the processor to
enter a package C-state. [That is why the exit latency and target residency
values corresponding to the majority of ``MWAIT`` hint values in the "internal"
tables of idle states in ``intel_idle`` reflect the properties of package
C-states.] If using package C-states is not desirable at all, either
:ref:`PM QoS <cpu-pm-qos>` or the ``max_cstate`` module parameter of
``intel_idle`` described `above <intel-idle-parameters_>`_ must be used to
restrict the range of permissible idle states to the ones with core-level only
``MWAIT`` hint values (like ``C1``).
References
==========
.. [1] *Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B*,
https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2b-manual.html
.. [2] *Advanced Configuration and Power Interface (ACPI) Specification*,
https://uefi.org/specifications
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
`intel_idle` CPU 유휴 시간 관리 driver
1-14이 문서는 `SPDX-License-Identifier: GPL-2.0`을 따르며, 저작권은 2020 Intel Corporation에 있습니다. 작성자는 Rafael J. Wysocki `<[email protected]>`입니다.
일반 정보
15-40`intel_idle`은 Linux kernel의 CPU idle time management subsystem인 `CPUIdle`의 일부입니다. Nehalem 이후 세대 Intel processor의 기본 CPU idle time management driver이지만, 특정 processor model에 대한 지원 수준은 driver가 그 model을 인식하는지에 따라 달라지고 platform firmware에서 오는 정보에도 의존할 수 있습니다. `intel_idle`을 이해하려면 `CPUIdle`의 일반 동작을 알아야 하므로, 아직 읽지 않았다면 `Documentation/admin-guide/pm/cpuidle.rst`를 먼저 익히는 것이 좋습니다.
`intel_idle`은 `MWAIT` instruction을 사용해 이를 실행하는 logical CPU가 idle 상태이며 processor의 일부 functional block을 low-power state로 둘 수 있음을 processor에 알립니다. 이 instruction은 대상 CPU의 `EAX`와 `ECX` register를 통해 두 argument를 받습니다. 첫 번째 argument는 *hint*라 하며 processor가 어떤 조치를 취할 수 있는지 판단하는 데 사용합니다. 자세한 내용은 Intel Software Developer’s Manual [1]을 참조하십시오. 따라서 `intel_idle`은 platform firmware 설정 menu 등에서 `MWAIT` 지원이 비활성화된 processor나 이 instruction을 전혀 지원하지 않는 processor에서는 동작을 거부합니다.
`intel_idle`은 modular driver가 아니어서 unload할 수 없습니다. 그러므로 초기 설정 시점의 parameter를 전달하는 유일한 방법은 kernel command line입니다.
`sysfs` interface
41-62`intel_idle` driver는 `/sys/devices/system/cpu/cpuidle/` 아래에 다음 `sysfs` attribute를 노출합니다.
`intel_c1_demotion`은 시스템의 모든 CPU에 대해 C1 demotion을 활성화하거나 비활성화합니다. 이 file은 C1 demotion 기능을 지원하고 해당 기능의 검증이 끝난 platform에서만 나타납니다. 값 `0`은 비활성화, 값 `1`은 활성화를 뜻하며, 모든 CPU의 C1 demotion을 끄거나 켜려면 `0` 또는 `1`을 씁니다.
C1 demotion은 platform firmware가 OS의 deep C-state 요청, 예를 들어 C6 요청을 C1으로 낮추는 기능입니다. Firmware는 CPU wake-up rate를 감시하다가 platform별 threshold보다 높으면 deep C-state 요청을 C1으로 demote합니다. 예를 들어 Linux가 C6을 요청해도 firmware가 초당 wake-up이 너무 많다고 판단하면 CPU를 C1에 유지합니다. CPU가 C1에 충분히 오래 머무르면 platform은 다시 C6으로 promote합니다. 이 동작은 일부 workload의 성능을 높일 수 있지만 power consumption도 증가시킬 수 있습니다.
Idle state 열거와 정보 출처
63-88각 `MWAIT` hint 값은 energy를 절약하도록 processor 자체를 특정 방식으로 재구성해도 된다는 허가로 해석됩니다. 그 결과인 power draw가 감소한 processor configuration을 ACPI 용어로 C-state, 또는 idle state라 부릅니다. 의미 있는 `MWAIT` hint 값과 이에 대응하는 low-power processor configuration 목록은 processor model에 따라 다르며 platform configuration에도 의존할 수 있습니다.
`CPUIdle` subsystem에 필요한 available idle state 목록을 만들기 위해 `intel_idle`은 두 정보원을 사용할 수 있습니다. 하나는 driver 자체에 포함된 processor model별 static idle-state table이고, 다른 하나는 system ACPI table입니다. 현재 processor model을 `intel_idle`이 인식하면 전자를 항상 사용합니다. 후자는 해당 model에 필요할 때, 즉 `intel_idle`이 인식하는 모든 server processor model에서 사용하거나 processor model을 인식하지 못할 때 사용합니다. Driver가 인식하는 어떤 processor model에서도 ACPI table을 사용하도록 만드는 module parameter가 있으며, 아래의 `intel-idle-parameters` 절에서 설명합니다.
ACPI `_CST`와 예비 상태 목록
89-110Available idle state 목록을 만드는 데 ACPI table을 사용한다면 `intel_idle`은 먼저 system CPU에 대응하는 ACPI object 가운데 하나에서 `_CST` object를 찾습니다. `_CST`와 그 output package는 ACPI specification [2]에 설명되어 있습니다. `CPUIdle` subsystem은 driver가 제공하는 idle-state 목록이 driver가 다루는 모든 CPU에 적합하다고 기대하고, `intel_idle`은 system의 모든 CPU에 대한 `CPUIdle` driver로 등록됩니다. 이 때문에 driver는 적어도 하나의 유효한 idle-state description을 반환하고, return package의 모든 idle state가 FFH(Functional Fixed Hardware) type인 첫 `_CST` object를 찾습니다. FFH type은 processor에 상태 진입 가능성을 알리는 데 `MWAIT` instruction을 사용한다고 기대한다는 뜻입니다.
그 `_CST`의 return package는 system의 다른 모든 CPU에도 적용된다고 가정합니다. 여기서 추출한 idle-state description은 ACPI table에서 온 preliminary idle-state list에 저장합니다. `intel_idle`이 ACPI table을 무시하도록 설정된 경우 이 단계는 생략됩니다. 이어서 available idle-state list의 첫 entry인 index 0을 polling idle state로 초기화합니다. 이는 대상 CPU가 instruction을 계속 fetch하고 execute하는 pseudo-idle state입니다. 이후 entry에는 실제 idle state를 채웁니다.
인식 여부에 따른 최종 상태 목록
111-146현재 processor model을 `intel_idle`이 인식하면 driver 안에 해당 model의 static idle-state description table이 있습니다. 이때 internal table이 idle-state 정보의 primary source이며 그 내용을 최종 available idle-state list로 복사합니다. Processor model에 따라 ACPI table을 통한 열거가 필요하지 않다면 나열된 모든 idle state가 기본으로 활성화되어 `CPUIdle` governor의 state 선택 후보가 됩니다. ACPI 열거가 필요하면 ACPI preliminary list에 matching entry가 없는 일부 상태는 기본으로 활성화되지 않을 수 있습니다. 그래도 user space는 CPU별 `sysfs` idle-state attribute인 `disable`을 사용해 나중에 활성화할 수 있습니다. 즉, driver가 알고 있는 idle state라도 platform firmware가 ACPI table을 통해 노출하지 않았다면 기본으로 활성화되지 않을 수 있습니다.
Processor model을 `intel_idle`이 인식하지 못하지만 `MWAIT`을 지원한다면 ACPI table에서 온 preliminary idle-state list로 `CPUIdle` core에 제공할 최종 목록을 만듭니다. 각 state의 description, `MWAIT` hint, exit latency를 대응하는 최종 entry에 복사합니다. `sysfs`의 `name` attribute가 반환할 state 이름은 `CX_ACPI`이며, 여기서 X는 최종 목록의 state index입니다. Index 0은 polling state용이므로 X의 최솟값은 1입니다. Target residency는 exit latency를 바탕으로 정합니다. C1-type state는 여러 internal table과의 호환성을 위해 exit latency를 target residency로도 사용하고, C2와 C3 type은 인식되는 processor model에서 흔한 비율을 반영해 target residency를 exit latency의 3배로 정합니다. 이 경우 최종 목록의 모든 idle state가 기본으로 활성화됩니다.
초기화
147-182`intel_idle` 초기화는 kernel command line option이 `MWAIT` instruction 사용을 금지하는지 확인하는 것으로 시작합니다. 금지되어 있으면 즉시 error code를 반환합니다.
다음으로 processor model이 driver에 알려져 있는지 확인하여 위에서 설명한 idle-state enumeration method를 결정하고, processor가 `MWAIT`을 지원하는지도 확인합니다. 지원하지 않으면 초기화가 실패합니다. 이어서 `CPUID`로 processor의 `MWAIT` 지원을 열거하며, 반환된 전체 `MWAIT` substate 수가 0인 경우처럼 지원 수준이 기대와 다르면 driver 초기화가 실패합니다.
그다음 driver가 ACPI table을 무시하도록 설정되지 않았다면 platform firmware가 제공한 idle-state 정보를 ACPI table에서 추출합니다.
이어서 모든 CPU에 대한 `CPUIdle` device object를 할당하고, 위에서 설명한 방식으로 available idle-state list를 만듭니다.
마지막으로 `cpuidle_register_driver()`를 사용해 `intel_idle`을 system의 모든 CPU에 대한 `CPUIdle` driver로 등록합니다. 또한 개별 CPU 설정을 위한 CPU online callback을 `cpuhp_setup_state()`로 등록합니다. 이 과정은 당시 system에 존재하는 모든 CPU에서 callback routine의 각자 instance를 실행하게 합니다. 이 routine은 자신을 실행하는 CPU에 `CPUIdle` device를 등록하여 `CPUIdle` subsystem이 그 CPU를 운용할 수 있게 하고, 해당 processor model에 필요할 수 있는 CPU-specific initialization action도 선택적으로 수행합니다.
Kernel command line option과 module parameter
183-229*x86* architecture support code는 CPU idle time management와 관련된 kernel command line option `idle=poll`, `idle=halt`, `idle=nomwait`을 인식합니다. 이 가운데 하나라도 kernel command line에 있으면 `MWAIT` instruction 사용이 허용되지 않으므로 `intel_idle` 초기화가 실패합니다.
이 밖에도 `intel_idle` 자체가 인식하는 module parameter가 다섯 개 있습니다. 이 값들은 kernel command line으로 설정할 수 있지만 `sysfs`를 통해 갱신할 수 없으므로, 값을 바꾸는 유일한 방법은 kernel command line입니다.
`max_cstate` 값은 driver 등록 때 `CPUIdle` core에 제공하는 idle-state list에서 허용할 최대 idle-state index입니다. 동시에 `intel_idle`이 사용할 수 있는 일반, 즉 non-polling idle state의 최대 개수이므로, 사용할 수 있는 state를 그 수만큼 찾으면 열거를 끝내고 더 큰 `max_cstate`에서 사용할 수 있었을 나머지 state는 전혀 고려하지 않습니다.
`max_cstate`를 설정하면 어떤 이유로 너무 깊다고 여기는 idle state를 `CPUIdle` core에 노출하지 않을 수 있습니다. 그러나 system을 종료하고 다시 시작할 때까지 그 상태를 사실상 보이지 않게 만들므로 항상 바람직한 것은 아닙니다. 실제로는 system startup 중 해당 state를 활성화할 수 없을 때만 꼭 필요합니다. System working state에서는 CPU power management quality of service(PM QoS)를 사용해 열거된 state라도 `CPUIdle`이 접근하지 못하게 할 수 있습니다. 자세한 내용은 `Documentation/admin-guide/pm/cpuidle.rst`의 `cpu-pm-qos` 절을 참조하십시오. `max_cstate`를 0으로 설정하면 `intel_idle` 초기화가 실패합니다.
Kernel이 ACPI support와 함께 설정된 경우 `intel_idle`은 `no_acpi`, `use_acpi`, `no_native` module parameter를 인식합니다. ACPI가 설정되지 않은 경우 이 flag들은 기능에 영향을 주지 않습니다.
`no_acpi`는 ACPI를 전혀 사용하지 않게 합니다. Native mode만 사용할 수 있고 ACPI mode는 사용할 수 없습니다.
`use_acpi`는 ACPI mode에서는 아무 동작도 하지 않는 no-op이며, native mode에서는 driver가 C-state의 on/off status를 확인하려고 ACPI table을 참조하게 합니다.
`no_native`는 ACPI mode에서만 동작하게 합니다. Native mode는 사용할 수 없으며 모든 custom table을 무시합니다.
`states_off` bitmask
230-247`states_off` module parameter의 값은 기본적으로 0이며, 기본으로 비활성화할 idle-state 목록을 bitmask 형태로 나타냅니다.
구체적으로 `states_off` 값에서 설정된 bit의 position이 기본 비활성화할 idle-state index입니다. 이는 `sysfs`의 대응 idle-state directory 이름인 `state0`, `state1` ... `state<i>` ... 에 반영되며, `<i>`가 해당 state의 index입니다. 자세한 내용은 `Documentation/admin-guide/pm/cpuidle.rst`의 idle-state representation 절을 참조하십시오.
예를 들어 `states_off`가 3이면 driver는 idle state 0과 1을 기본으로 비활성화합니다. 값이 8이면 idle state 3을 기본으로 비활성화합니다. 최대 idle-state index를 넘는 bit position은 무시합니다.
이 방식으로 비활성화한 idle state는 user space에서 `sysfs`를 통해 CPU별로 활성화할 수 있습니다.
`ibrs_off`와 idle 중 IBRS
248-263`ibrs_off` module parameter는 기본값이 false인 boolean flag입니다. 이 값을 설정하면 CPU가 idle state에 들어갈 때 IBRS(Indirect Branch Restricted Speculation)를 끌지 제어하는 데 사용합니다. 성능 영향이 작아서 켠 채 유지할 수 있는 Enhanced IBRS를 사용하는 CPU에는 이 flag가 영향을 주지 않습니다.
일부 CPU에서는 Spectre v2와 Retbleed security vulnerability의 기본 mitigation으로 IBRS를 선택합니다. Idle 중 IBRS mode를 켜 두면 sibling CPU의 성능에 영향을 줄 수 있습니다. 기본적으로 CPU가 deep idle state에 들어가면 IBRS mode를 끄지만 일부 shallow state에서는 끄지 않습니다. `ibrs_off`를 설정하면 CPU가 available idle state 가운데 어느 것에 있든 IBRS mode를 강제로 끕니다. 이 방법은 idle CPU의 wakeup latency가 약간 늘어나는 대신 sibling CPU의 성능에 도움이 될 수 있습니다.
Core와 package 수준의 idle state
264-307일반적으로 `MWAIT` instruction을 지원하는 processor에는 적어도 두 수준의 idle state, 즉 C-state가 있습니다. Core C-state는 processor의 개별 core를 다루고, package C-state는 processor package 전체를 다루며 GPU, memory controller, I/O hub 같은 system의 다른 component도 포함할 수 있습니다.
일부 `MWAIT` hint 값은 processor가 core C-state만 사용하도록 허용합니다. 대표적으로 `C1` idle state에 대응하는 hint가 그렇습니다. 그러나 대부분의 hint 값은 대상 core, 즉 주어진 hint로 `MWAIT`을 실행한 logical CPU가 속한 core를 특정 core C-state에 넣고, 가능하다면 더 깊은 수준의 특정 package C-state에도 들어가도록 허용합니다.
예를 들어 `C3` idle state를 나타내는 `MWAIT` hint는 processor가 대상 core를 core `C3`, 즉 `CC3`이라는 low-power state에 둘 수 있게 합니다. 이는 그 core의 모든 logical CPU인 SMT siblings가 `C3` hint 또는 더 깊은 idle state의 hint로 `MWAIT`을 실행했을 때 일어납니다. 또한 대부분의 경우 이 hint는 GPU나 memory controller 같은 non-CPU component를 포함할 수 있는 package 전체를 package `C3`, 즉 `PC3`에 둘 수 있게 합니다. 모든 core가 `CC3`에 들어가고 추가 조건도 충족할 때 `PC3`에 진입합니다. 예를 들어 GPU가 `PC3` 범위에 포함된다면 `PC3`에 도달하려면 GPU가 특정 GPU-specific low-power state에 있어야 할 수 있습니다.
일반적으로 대응하는 package C-state 진입 조건이 충족되었을 때 processor가 core C-state만 사용하도록 만드는 간단한 방법은 없습니다. 따라서 `C1`처럼 core-level only가 아닌 hint 값으로 `MWAIT`을 실행하는 logical CPU는 이것이 processor의 package C-state 진입을 일으킬 수 있다고 항상 가정해야 합니다. 이 때문에 `intel_idle` internal table에서 대부분의 `MWAIT` hint에 대응하는 exit latency와 target residency는 package C-state의 특성을 반영합니다. Package C-state 사용을 완전히 피하려면 `PM QoS` 또는 위에서 설명한 `intel_idle`의 `max_cstate` module parameter를 사용해 허용되는 idle-state 범위를 `C1` 같은 core-level only `MWAIT` hint로 제한해야 합니다.
참고문헌
308-316[1] *Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B*: `https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2b-manual.html`
[2] *Advanced Configuration and Power Interface (ACPI) Specification*: `https://uefi.org/specifications`
요약과 해설
intel_idle.rst:1-316`intel_idle`은 processor model별 static table과 필요에 따라 ACPI `_CST`를 결합해 `CPUIdle`에 상태 목록을 제공합니다. 운영자는 상태의 깊이, 기본 활성화 여부, ACPI 사용 mode, idle 중 IBRS 처리 방식을 boot parameter로 제한할 수 있습니다.
Core C-state 요청은 조건이 맞으면 package C-state까지 유도할 수 있으므로, latency 제약은 core만이 아니라 package 전체의 특성을 기준으로 판단해야 합니다.