每一個 CPU 核心都會有一個 idle 進程,idle 進程是當系統(tǒng)沒有調度 CPU 資源的時候,會進入 idle 進程,而 idle 進程的作用就是不使用 CPU,以此達到省電的目的。
在ARM64架構中,當CPU Idle時,會調用WFI指令(wait for interrupt),關掉CPU的Clock以便降低功耗,當有外設中斷觸發(fā)時,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狀態(tài)的時間(us) intlast_residency; //記錄每個cpuidle狀態(tài)的統(tǒng)計信息,包括是否使能、進入該cpuidle狀態(tài)的次數,停留在該cpuidle狀態(tài)的總時間(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的狀態(tài),需要按照功耗從大到小來排序,具體有多少個cpuidle狀態(tài) 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下返回運行狀態(tài)的延遲,單位為us。它決定了CPU在idle狀態(tài)和run狀態(tài)之間切換的效率,如果延遲過大,將會影響系統(tǒng)性能; unsignedintexit_latency;/*inUS*/ //CPU在該idlestate下的功耗,單位為mW intpower_usage;/*inmW*/ //期望的停留時間,單位為us。進入和退出idle state是需要消耗額外的能量的,如果在idle狀態(tài)停留的時間過短,節(jié)省的功耗少于額外的消耗,則得不償失。governor會根據該字段,結合當前的系統(tǒng)情況(如可以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會選擇系統(tǒng)中rating值最大的governor作為當前governor unsignedintrating; //在設備驅動注冊和注銷的時候調用 int(*enable)(structcpuidle_driver*drv, structcpuidle_device*dev); void(*disable)(structcpuidle_driver*drv, structcpuidle_device*dev); //根據當前系統(tǒng)的運行狀況,以及各個idlestate的特性,選擇一個state(即決策) int(*select)(structcpuidle_driver*drv, structcpuidle_device*dev, bool*stop_tick); //通過該回調函數,可以告知governor,系統(tǒng)上一次所處的idlestate是哪個 void(*reflect)(structcpuidle_device*dev,intindex); };
對應的注冊接口是 cpuidle_register_governor。
流程
我們先看下設備和驅動的注冊過程:
注冊之后便將設備和驅動建立起連接關系了,最終 cpuidle framework 的用戶便可通過接口來調用下層的接口,進而完成具體的硬件操作。
下面看下 CPU 進入 idle 狀態(tài)的流程圖:
可以看出,最終是通過 PSCI 來實現 CPU 的 suspend。
PSCI
PSCI, Power State Coordination Interface,由ARM定義的電源管理接口規(guī)范,通常由Firmware來實現,而Linux系統(tǒng)可以通過smc/hvc指令來進入不同的Exception Level,進而調用對應的實現。
PSCI 支持如下功能:
CPU hotplug (on/off)
CPU idle (suspend/resume)
System suspend/resume
System shutdown and reset
每個功能和ATF之間的調用接口如下所示:
-
cpu
+關注
關注
68文章
10863瀏覽量
211782 -
接口
+關注
關注
33文章
8598瀏覽量
151166 -
數據
+關注
關注
8文章
7030瀏覽量
89038
發(fā)布評論請先 登錄
相關推薦
評論