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