cpuidle framework
每一个 CPU 核心都会有一个 idle 进程,idle 进程是当系统没有调度 CPU 资源的时候,会进入 idle 进程,而 idle 进程的作用就是不使用 CPU,以此达到省电的目的。
在ARM64架构中,当CPU Idle时,会调用WFI指令(wait for interrupt),关掉CPU的Clock以便降低功耗,当有外设中断触发时,CPU又会恢复回来。
cpuidle core 是 cpuidle framework 的核心模块,负责抽象出 cpuidle device、cpuidle driver 和 cpuidle governor 三个实体,如下所示:

cpuidle core 抽象出了 cpuidle device、cpuidle driver 和 cpuidle governor 三个数据结构。
数据结构
cpuidle_device
针对每个CPU核都对应一个struct cpuidle_device结构,主要字段介绍如下
structcpuidle_device{
//该cpu核是否注册进内核中
unsignedintregistered:1;
//该cpu核是否已经使能
unsignedintenabled:1;
unsignedintuse_deepest_state:1;
//对应的cpunumber
unsignedintcpu;
//该cpu核上一次停留在cpuidle状态的时间(us)
intlast_residency;
//记录每个cpuidle状态的统计信息,包括是否使能、进入该cpuidle状态的次数,停留在该cpuidle状态的总时间(us)
structcpuidle_state_usagestates_usage[CPUIDLE_STATE_MAX];
......
};
对应的注册接口是 cpuidle_register_device。
cpuidle_driver
cpuidle driver用于驱动一个或多个CPU核,关键字段描述如下:
structcpuidle_driver{
constchar*name;
structmodule*owner;
intrefcnt;
//用于驱动注册时判断是否需要设置broadcasttimer
unsignedintbctimer:1;
//用于描述cpuidle的状态,需要按照功耗从大到小来排序,具体有多少个cpuidle状态
structcpuidle_statestates[CPUIDLE_STATE_MAX];
......
};
//CPU有多种不同的idle级别。这些idle级别有不同的功耗和延迟,从而可以在不同的场景下使用
//主要包括exit_latency、power_usage、target_residency。这些特性是governor制定idle策略的依据
structcpuidle_state{
charname[CPUIDLE_NAME_LEN];
chardesc[CPUIDLE_DESC_LEN];
unsignedintflags;
//CPU从该idle state下返回运行状态的延迟,单位为us。它决定了CPU在idle状态和run状态之间切换的效率,如果延迟过大,将会影响系统性能;
unsignedintexit_latency;/*inUS*/
//CPU在该idlestate下的功耗,单位为mW
intpower_usage;/*inmW*/
//期望的停留时间,单位为us。进入和退出idle state是需要消耗额外的能量的,如果在idle状态停留的时间过短,节省的功耗少于额外的消耗,则得不偿失。governor会根据该字段,结合当前的系统情况(如可以idle多久),选择idle level;
unsignedinttarget_residency;/*inUS*/
booldisabled;/*disabledonallCPUs*/
//进入该state的回调函数
int(*enter)(structcpuidle_device*dev,
structcpuidle_driver*drv,
intindex);
//CPU长时间不需要工作时(称作offline),可调用该回调函数。
int(*enter_dead)(structcpuidle_device*dev,intindex);
......
};
对应的注册接口是 cpuidle_register_driver。
cpuidle_governor
governor 结构主要提供不同的回调函数,最终由 menu_governor 填充,主要字段如下:
structcpuidle_governor{
charname[CPUIDLE_NAME_LEN];
structlist_headgovernor_list;
//governor的级别,正常情况下,kernel会选择系统中rating值最大的governor作为当前governor
unsignedintrating;
//在设备驱动注册和注销的时候调用
int(*enable)(structcpuidle_driver*drv,
structcpuidle_device*dev);
void(*disable)(structcpuidle_driver*drv,
structcpuidle_device*dev);
//根据当前系统的运行状况,以及各个idlestate的特性,选择一个state(即决策)
int(*select)(structcpuidle_driver*drv,
structcpuidle_device*dev,
bool*stop_tick);
//通过该回调函数,可以告知governor,系统上一次所处的idlestate是哪个
void(*reflect)(structcpuidle_device*dev,intindex);
};
对应的注册接口是 cpuidle_register_governor。
流程
我们先看下设备和驱动的注册过程:

注册之后便将设备和驱动建立起连接关系了,最终 cpuidle framework 的用户便可通过接口来调用下层的接口,进而完成具体的硬件操作。
下面看下 CPU 进入 idle 状态的流程图:

可以看出,最终是通过 PSCI 来实现 CPU 的 suspend。
PSCI
PSCI, Power State Coordination Interface,由ARM定义的电源管理接口规范,通常由Firmware来实现,而Linux系统可以通过smc/hvc指令来进入不同的Exception Level,进而调用对应的实现。

PSCI 支持如下功能:
CPU hotplug (on/off)
CPU idle (suspend/resume)
System suspend/resume
System shutdown and reset
每个功能和ATF之间的调用接口如下所示:


审核编辑:刘清
-
ARM
+关注
关注
135文章
9499浏览量
388800 -
电源管理
+关注
关注
117文章
6549浏览量
147543 -
cpu
+关注
关注
68文章
11218浏览量
222974
原文标题:CPU 进入 IDLE 都做了啥?
文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
电源管理入门-CPU Idle有什么用?Idle状态判断
关于CC1101的WOR问题,请问SLLEP状态下想切换进入WOR,是要先进入IDLE,然后延时发送sworrs以及swor指令吗?
请问低功耗IDLE模式的唤醒如何做到几个毫秒唤醒一次继而再次进入该模式?
Linux 进程状态浅析
如何在connected idle状态下向手机同步音量
python自带的idle怎么进入
secondary cpu执行流程介绍

CPU进入idle进程状态的流程
评论