by 宋宝华
在《Tegra3 vSMP架构Android运行时CPU热插拔及高低功耗CPU切换》一文中我们通过运行华硕平板电脑看出来tegra3的dvfs结合了CPU热插拔和G/LP core cluster之间的切换,本文从代码角度分析其运行机理。
tegra3是典型的BIG/LITTLE模式,4个G core(高性能,高功耗)加上1个LP core(低性能,低功耗)。运行过程中,我们会发现4个G core会动态热插拔,而4个G core和1个LP core之间,会根据运行负载进行cluster切换。这一部分都是在内核里面实现,和tegra的cpufreq驱动(DVFS驱动)紧密关联。相关代码可见于
相关代码未见于LKML和kernel org。
如何判断自己是什么core
每个core都可以通过调用is_lp_cluster()来判断当前执行CPU是LP还是G处理器:
即读FLOW_CTRL_CLUSTER_CONTROL寄存器判断出来自己是G core还是LP core。
G core和LP core cluster的切换时机
[场景1]何时从LP切换给G:当前执行于LPcluster,cpufreq驱动判断出LP需要升频率超过高值门限,即TEGRA_HP_UP:
[场景2]何时从G切换给LP:当前执行于Gcluster,cpufreq驱动判断出某G core需要降频率到小于低值门限,即TEGRA_HP_DOWN,且最慢的CPUID不小于nr_cpu_ids(实际上代码逻辑跟踪等价于只有CPU0还活着):
切换实际上就发生在clk_set_parent()更改CPU的父时钟里面,这部分代码写地比较丑,1个函数完成n个功能,实际不仅切换了时钟,还切换了G和LP cluster:
clk_set_parent(cpu_clk, cpu_lp_clk) ->
tegra3_cpu_cmplx_clk_set_parent(structclk *c, struct clk *p) ->
tegra_cluster_control(unsignedint us, unsigned int flags) ->
tegra_cluster_switch_prolog()-> tegra_cluster_switch_epilog()
G core动态热插拔
何时进行G core的动态plug和unplug:
[场景3]
1.当前执行于G cluster,cpufreq驱动判断出某Gcore需要降频率到小于低值门限,即TEGRA_HP_DOWN,且最慢的CPUID小于nr_cpu_ids(实际上等价于还有2个或2个以上的G core活着),关闭最慢的CPU,留意tegra_get_slowest_cpu_n()不会返回0,意味着CPU0要么活着,要么切换给LP(对应场景2):
[场景4]
2.当前执行于G cluster,cpufreq驱动判断出某Gcore需要设置频率大于高值门限,即TEGRA_HP_UP,如果负载平衡状态为TEGRA_CPU_SPEED_BALANCED,再开一个core;如果状态为TEGRA_CPU_SPEED_SKEWED,则关一个core。TEGRA_CPU_SPEED_BALANCED的含义是当前所有Gcore要求的频率都高于最高频率的50%,TEGRA_CPU_SPEED_SKEWED的含义是当前至少有2个Gcore要求的频率低于门限的25%,即CPU 频率的要求在各个core间有倾斜。
上述代码中TEGRA_CPU_SPEED_BIASED路径的含义是有1个以上Gcore的频率低于最高频率的50%但是未形成SKEWED条件,即只是“BIASED”,还没有达到“SKEWED”的程度,所以暂时什么都不做。