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之間的調用接口如下所示:

-
cpu
+關注
關注
68文章
11277瀏覽量
224938 -
接口
+關注
關注
33文章
9519瀏覽量
157015 -
數據
+關注
關注
8文章
7335瀏覽量
94754
發布評論請先 登錄
電源管理入門-CPU Idle有什么用?Idle狀態判斷
【Nanopi2試用體驗】高級(十):進程綁定CPU核心
進程和線程區別
線程與6個arm核心中的一個綁定請問如何解綁?
CPU緩存是什么意思_CPU緩存有什么作用
把進程綁定到某個 CPU 上運行是怎么實現?
講講線程、進程和CPU中的超線程
python自帶的idle怎么進入
kernel到android核心啟動過程
CPU核心中idle進程作用
評論