本文会基于Android Pixel4(android linux kernel 4.14+ARMv8(AArch64)),重点分析schedutil这个cpufreq的governor,同时简单回顾CPU电源管理的常见手段以及cpufreq的框架,以便更加完整和清晰的分析schedutil的核心逻辑和来龙去脉。即本文会围绕以下问题展开:
CPU的电源管理主要的软硬件手段有哪些?
cpufreq框架有哪些核心组件,主要作用分别是什么,体现了哪些软件思想?
cpufreq有哪些常见的governor,分别适用于什么场景?
为什么要提出schedutil?
schedutil与EAS有什么关系?
schedutil的核心逻辑是什么?
一、CPU电源管理简介
如果我们的能源是无限制的,那可能也不需要做现在这样复杂的电源管理控制,尤其是在嵌入式设备如手机上,在追求极致性能的同时,还要追求续航时间,二者是一对相互约束的矛盾体,需要软硬件紧密配合以满足用户越发苛刻的性能和功耗的需求。
CPU是设备的控制核心,它的电源管理是整个SOC电源管理非常重要的一环。常见的CPU电源管理设计,主要也是围绕静态功耗和动态功耗的设计和优化展开:
1)静态功耗:ASIC集成电路的最基本单元是晶体管,我们的SOC在待机时仍然会有漏电流产生,从而引起静态功耗的消耗,得益于晶圆厂SOC制程(工艺)不断改进,如相比7nm FinFET,台积电5nm EUV工艺能效提升15%,功耗减少30%。所以从这个角度来讲,CPU要降低静态功耗,需要ASIC工程师把面积做小,同时需要晶圆厂把工艺制程不断改进。
2)动态功耗:这块比较复杂,软硬件配合的有cpufreq、cpuidle、锁机制底层实现等,ASIC方面有clock gating、不同power domain等,我们简单介绍下。
cpufreq:根据cpu负载,选择满足性能需求的最低的电压/频率对(也叫OPP,Operating Performance Points)。对ARM而言,这种电压/频率对的调整的最小单位是cluster,也就是说一个cluster里的所有工作的CPU核心的频率/电压对是相同的。在ARM支持DynamIQ后,不再是只有2个cluster了,每个cluster也不要求放置同一种微架构的CPU核心了,而是出现了如1小核+3中核+4小核的结构,笔者手中的Google Pixel4手机,就是这种架构,这款手机中vendor厂商把大核和中核,电压设置成一路电源去供电,而频率却不一样,这样对软件调频的策略提出了更高的要求,这里不再展开了。这种电压/频率对的调整,其他很多设备也都适用,统称为DVFS(Dynamic Voltage/Frequency Scaling,动态电压/频率调整)。
cpuidle:Linux用C-States来描述,最早应该是Intel提出来的概念,有4个状态(C0到C3)。ARM架构中,C0对应Running状态,C1对应Idle状态,C3对应Sleep状态,没有C2,CPU根据设定策略进入不同的低功耗状态,当然进出不同低功耗状态的时延是不也一样的。C1状态对应我们的cpuidle去控制,底层实现一般会执行WFI(Wait for Interrupt )指令,等到有中断的时候从C1迁移至C0状态,如果没有中断且满足一定条件会进一步转移至C3状态。CPU内部会有一个状态机控制这些状态的迁移和转换,不同状态可以简单的理解为参与工作的CPU部件不一样,状态的数字越小,参与工作的部件就越多。细节请参考ARM ARM(ARM Architecture Reference Manual)和各个CPU的微架构的TRM(Technical Reference Manual)。
spinlock锁机制:底层实现会执行WFE(Wait for Event)指令,进入低功耗状态,待收到SEV指令的时候,会从低功耗状态退出。避免在lock时忙等,节省部分功耗。
clock gating:这是ASIC设计的自动门控功能,一般外设会有寄存器控制是否使能,而CPU主要是在WFI的时候会关闭一些时钟,这个是CPU内部的状态机逻辑来做的,也算是clock gating,这个过程一般不需要软件参与。
power domain:划分不同的domain,是为了方便去做精细控制,需要软件参与。例如Pixel4手机有3个cluster划分了两个power domain(大核和中核是一个domain,小核是另外一个domain)。例如在系统轻载,甚至可以把大核和中核这两个cluster下电。细节可以参考TRM,比如A57 TRM的有关power domain划分示意如下图所示,这里不再展开。
二、cpufreq总体框架简介
介绍完CPU电源管理的常用手段,我们简单回顾下cpufreq的总体架构和各模块的作用,以及体现的软件思想。更细节的大家可以参考蜗窝科技的分析文章。
1. 主要模块介绍
Core:是对通用流程和方法的抽象;
Governor:负责调频策略,解决如何调频的问题;
Driver:负责平台相关调频机制的具体实现(需要直接操作硬件);
Stats:负责调频信息和各频点运行时间等统计,使用time_in_state ,结合算力和最大频率,可以做归一化的CPU负载统计。
Notifer:通知链,负责通知其他关心调频动作的driver。
Sysfs:暴露接口给用户态应用程序,使其可以灵活控制,实现不同的控制策略。