1.介紹
CPU dvfs(dynamic voltage frequency scaling)子系統(tǒng)負(fù)責(zé)cpu運行時,對其頻率及電壓進行調(diào)整,以求性能滿足的前提下,cpu的功耗盡可能低。
芯片的CMOS電路的功耗有個計算公式,比較復(fù)雜,簡單來說功耗跟電壓平方成正比,跟頻率成正比,因此CPU dvfs在涉及到電壓調(diào)整的時候,功耗受益還是很明顯的。 但是僅調(diào)頻的話,收益是比較小的,因為頻率對應(yīng)著算力,當(dāng)頻率減少,對應(yīng)的算力也減弱,這樣執(zhí)行時間也會變長。
CPU dvfs framework(也常被稱為cpufreq framework)和其他的linux framework類似。 主要解決兩個問題:什么時候調(diào)頻調(diào)壓,怎么調(diào)頻調(diào)壓。 cpufreq driver提供調(diào)頻調(diào)壓的機制,cpufreq governor提供不同的策略,cpufreq core對通用的調(diào)頻邏輯做抽象,為上層提供功能、接口封裝,對下層調(diào)用抽象封裝的硬件控制接口。 此外,還借助頻率電壓對opp(operating performance points)功能,clk driver、regulator driver對頻率及電壓做硬件時鐘及電壓的調(diào)整。
2. 框架
cpufreq core:是cpufreq framework的核心模塊,和kernel其它framework類似,主要實現(xiàn)三類功能
抽象調(diào)頻調(diào)壓的公共邏輯和接口,主要圍繞struct cpufreq_driver、struct cpufreq_policy和struct cpufreq_governor三個數(shù)據(jù)結(jié)構(gòu)進行
以sysfs的形式向用戶空間提供統(tǒng)一的接口,以notifier的形式向其它driver提供頻率變化的通知。
提供CPU頻率和電壓控制的驅(qū)動框架,方便底層driver的開發(fā); 同時,提供governor框架,用于實現(xiàn)不同的頻率調(diào)整機制。
cpufreq governor:負(fù)責(zé)調(diào)頻調(diào)壓的各種策略,每種governor計算頻率的方式不同,根據(jù)提供的頻率范圍和參數(shù)(閾值等),計算合適的頻率。
userspace:用戶通過操作scaling_setspeed文件節(jié)點操作頻率及電壓的調(diào)整。
ondemand:根據(jù)CPU當(dāng)前的使用率,動態(tài)調(diào)整cpu的頻率及電壓。 Sched通過調(diào)用ondemand注冊進來的回調(diào)函數(shù)來觸發(fā)負(fù)載的估算,它以一定時間間隔對系統(tǒng)負(fù)載進行采樣,按需調(diào)整cpu的頻率及電壓,若當(dāng)前cpu的利用率超過設(shè)定的閾值,就會立即調(diào)整到最大的頻率。 調(diào)頻速度快,但是不夠精確。
conservative:類似ondemand,在調(diào)頻調(diào)節(jié)時會平滑一下,以防最大、最小頻率之間來回跳變。 調(diào)整的時候會以一定步長調(diào)整,而不是直接調(diào)整到目標(biāo)值。 同時會周期的計算系統(tǒng)負(fù)載,用以決定調(diào)到什么頻率。
schedutil:通過將自己的調(diào)頻策略注冊到hook,在負(fù)載發(fā)生變化的時候,會調(diào)用該hook,此時就可以進行調(diào)頻決策或執(zhí)行調(diào)頻動作。 前面的調(diào)頻策略都是周期采樣計算cpu負(fù)載有滯后性,精度也有限,而schedutil可以使用PELT(per entity load tracking)或者WALT(window assist load tracking)準(zhǔn)確的計算task的負(fù)載。 如果支持fast_switch的功能,可以在中斷上下文直接進行調(diào)頻。
cpufreq driver:負(fù)責(zé)平臺相關(guān)的調(diào)頻調(diào)壓機制的實現(xiàn),基于cpu subsystem driver、OPP、clock driver、regulator driver等模塊,提供對CPU頻率和電壓的控制。
cpufreq stats:負(fù)責(zé)調(diào)頻信息和各頻點運行時間等統(tǒng)計,提供每個cpu的cpufreq有關(guān)的統(tǒng)計信息。
3. 數(shù)據(jù)結(jié)構(gòu)
struct cpufreq_policy:linux使用cpufreq policy來抽象cpu設(shè)備的調(diào)頻調(diào)壓功能,用于描述不同的policy,包含頻率表、cpuinfo等各種信息,并且每個policy都會對應(yīng)某個具體的governor。
struct cpufreq_governor:不同policy的管理策略,根據(jù)使用場景的不同,會有不同的調(diào)頻調(diào)壓策略。
struct cpufreq_driver:用于描述cpufreq的驅(qū)動,是驅(qū)動工程師最關(guān)注的結(jié)構(gòu)。
4. 初始化及工作流程
4.1 初始化流程
cpufreq_register_driver函數(shù)為cpufreqdriver注冊的入口,驅(qū)動程序通過調(diào)用該函數(shù)進行初始化,并傳入相關(guān)的struct cpufreq_driver,cpufreq_register_driver會調(diào)用subsys_interface_register,最終執(zhí)行回調(diào)函數(shù)cpufreq_add_dev。
系統(tǒng)中可以同時存在多個governor,policy通過cpufreq_policy->governor指針和某個governor相關(guān)聯(lián)。要想一個governor能夠被使用,首先要把該governor注冊到cpufreq framework中。
cpufreq core定義了一個全局鏈表變量:cpufreq_governor_list,注冊函數(shù)首先根據(jù)governor的名稱,通過__find_governor()函數(shù)查找該governor是否已經(jīng)被注冊過,如果沒有被注冊過,則把代表該governor的結(jié)構(gòu)體添加到cpufreq_governor_list鏈表中。
4.2 工作流程
不同的governor的觸發(fā)調(diào)頻調(diào)壓流程不一樣,這里以scheduutil governor為例。
CFS負(fù)載變化的時候或者RT、DL任務(wù)狀態(tài)更新的時候,就會啟動調(diào)頻這幾個scheduler類會調(diào)用cpufreq_update_util函數(shù)(前面注冊進來的hook函數(shù))觸發(fā)schedutil工作。每個cpu最終會回調(diào)到sugov_upate_shared或者sugov_upate_single函數(shù)中的一個。
由于是從scheduler里直接調(diào)用下來的,最終執(zhí)行調(diào)頻切換時,無論是快速路徑觸發(fā)的簡單寫寄存器,還是慢速路徑觸發(fā)的kthread都不會占用過多時間或者調(diào)度開銷。
具體的觸發(fā)時機如下:
審核編輯:湯梓紅
-
cpu
+關(guān)注
關(guān)注
68文章
10813瀏覽量
210880 -
Linux
+關(guān)注
關(guān)注
87文章
11215瀏覽量
208742 -
功耗
+關(guān)注
關(guān)注
1文章
808瀏覽量
31902 -
數(shù)據(jù)結(jié)構(gòu)
+關(guān)注
關(guān)注
3文章
569瀏覽量
40076 -
DVFS
+關(guān)注
關(guān)注
1文章
17瀏覽量
11982
發(fā)布評論請先 登錄
相關(guān)推薦
評論