背景 By 魯迅 By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器 3. 使用工具:Source Insight 3.5, Visio 1. 介紹 子系統負責在運行時對CPU頻率和電壓的動態調整,以達到性能和功耗的平衡,它也叫 。 原理:CMOS電路中功耗與電壓的平方成 ...
背景
Read the fucking source code!
--By 魯迅A picture is worth a thousand words.
--By 高爾基
說明:
- Kernel版本:4.14
- ARM64處理器
- 使用工具:Source Insight 3.5, Visio
1. 介紹
cpufreq
子系統負責在運行時對CPU頻率和電壓的動態調整,以達到性能和功耗的平衡,它也叫DVFS(Dynamic Voltage Frequency Scaling)
。DVFS
原理:CMOS電路中功耗與電壓的平方成正比,與頻率也成正比。此外,頻率越高,性能也越強,相應的能耗就增大了,所以Tradeoff依舊是一門藝術。cpufreq framework
類似於cpuidle framework
,提供機制(cpufreq driver
)與策略(cpufreq governor
),此外提供了cpufreq core
來對機制和策略進行管理。
2. 框架
主要代碼路徑:
driver/cpufreq/cpufreq.c
include/linux/cpufreq.h
drivers/cpufreq/cpufreq_userspace.c
先上框架圖:
粗一看與cpuidle framework
的圖很像,但是有些差別如下:
- 用戶層與
cpufreq framework
的交互,主要是通過sysfs
,這個可以在/sys
下看到很多文件,而Kernel Module
也可以使用某些介面來回調它; - 系統只允許有一個Platform Drivers,為全局變數
cpufreq_driver
,cpufreq core
通過它去回調驅動; - 驅動與硬體的交互,通過如
set_clk_rate/regulator_set_voltage
等介面去設置CPU的時鐘和電壓,而不再是cpu_ops
; - 有一個全局的
governor
鏈表cpufreq_governor_list
,可以通過查找鏈表來選擇合適的governor
;
3. 數據結構
核心的數據結構有三個:
struct cpufreq_policy
:用於描述不同的policy,涉及到頻率表、cpuinfo等各種信息,並且每個policy都會指向某個governor
;struct cpufreq_governor
:用於對policy的管理;struct cpufreq_driver
:用於描述具體的驅動程式;
如下圖:
4. 流程
4.1 cpufreq_driver註冊
仔細觀察上圖中struct cpufreq_driver
結構體,你會發現它與傳統的設備模型中的驅動結構不一致,它並沒有內嵌struct bus_type
或struct device_driver
類型,這就決定了它不屬於“device<--->bus<--->driver”
這種模型。
事實上,cpufreq_driver
是一個全局的變數,不屬於任何一個拓撲的結構。它的註冊從cpufreq_register_driver
開始。
流程如下圖:
4.2 governor註冊
介面為:cpufreq_register_governor
,這個操作實在是太簡單了,添加到全局鏈表即可,完事!
順帶提一句吧,還有一個介面cpufreq_register_notifier
,這個用於通知機制,具體不再深入分析了。
4.3 sysfs訪問
cpufreq core
會在/sys目錄下創建相應的節點,如下圖所示:
用戶態可以通過cat/echo
命令來讀取/設置相應的值。
對應結構體如下:
static struct attribute *default_attrs[] = {
&cpuinfo_min_freq.attr,
&cpuinfo_max_freq.attr,
&cpuinfo_transition_latency.attr,
&scaling_min_freq.attr,
&scaling_max_freq.attr,
&affected_cpus.attr,
&related_cpus.attr,
&scaling_governor.attr,
&scaling_driver.attr,
&scaling_available_governors.attr,
&scaling_setspeed.attr,
NULL
};
各個欄位含義如下:
affected_cpus
:需要軟體調整頻率的cpu列表;related_cpus
:需要軟體或硬體來調整頻率的cpu列表;cpuinfo_max_freq
:CPU能夠支持的最高頻率(khz);cpuinfo_min_freq
:CPU能夠支持的最小頻率(khz);cpuinfo_transition_latency
:CPU頻率切換時的時間開銷(ns);scaling_available_governors
:內核中支持的governor
;scaling_driver
:硬體驅動,比如cpufreq-dt
;scaling_cur_freq
:CPU工作頻率;scaling_max_freq
:當前policy的頻率上限;scaling_min_freq
:當前policy的頻率下限;scaling_governor
:CPU調頻策略,可以修改;scaling_setspeed
:設置CPU運行頻率;
如下圖:
sysfs
回調下來後,會進入xxx_store/xxx_show
函數來進行具體的設置,至於設置的流程大體與cpufreq_driver
註冊圖中類似,不再深入分析了。
驅動的實現變成了實現struct cpufreq_driver
函數指針中的函數,並註冊即可。目前的驅動開發大抵如此,變成了一道填空題,當然我們也需要去瞭解背後的原理。