天天看点

cpuidle framework in Linux Kernel(1)概述Why to Idle?CPUidle Framework in LinuxCPU idle流程

这个系列的文章,介绍了CPU 电源管理的一个重要分支CPUidle subsystem,所谓CPU idle,就是在CPU没有事情做的时候,通过clock gating或power gating的方式降低或是关闭CPU internal某些单元的clock或power的方式,降低CPU的功耗并改善发热问题。

文章是在参考了多位大神文章的基础上,结合自己对Linux kernel cpuidle 相关code以及ACPI spec的理解形成的,记录在这里,并不断地迭代修正,实现螺旋形上升成长。

cpuidle 相关的文章分5大部分,旨在解决以下几个问题:

1)why to idle?

2)what’s idle state?

3)when to idle?

4)which idle state to enter?

5)how to enter/exit idle state?

该系列文章包括:

概述,即本文,介绍一些背景知识和 cpuidle framework in Linux;

【what‘s idle states,】从ACPI spec定义和Linux kernel实现两个方面介绍各种idle state;

【cpuidle driver】解决how to enter idle state的问题。

【cpuidle device】利用linux设备模型的概念,虚拟出来一个cpuidle device,用来管理CPU idle相关的操作,并提供一些sysfs interface供userspace来控制;

【cpuidle governor】解决which idle state to enter的问题。

Why to Idle?

计算机系统中,CPU的功能是执行程序,就是取指、译码、执行。那么问题来了,如果没有程序要执行,CPU该怎么办呢?为了省电,需要停掉CPU,但什么时候停、怎么停呢?这就需要我们仔细斟酌了,因为实际的软硬件环境是非常复杂的。

在Linux系统中,CPU被两类程序占用:一类是进程(或线程),也称为进程上下文;另一类是中断、异常的处理程序,也称中断上下文。进程的存在是用来处理事务的,比如读取用户的输入,并显示在屏幕上。但是事务总有处理完的时候,如果用户不再输入,也没有新的内容需要显示在屏幕上。此时,该进程就可以让出CPU,但是要随时准备回来(用户可能突然有按键动作)。同理,如果系统没有中断、异常事件,CPU就不会花时间在中断上下文。

在Linux kernel中,把这种CPU无所事事的状态,称作idle state,并引入了idle framework来管理这种状态。

CPUidle Framework in Linux

Linux kernel中,cpuidle framework相关的代码在drivers/cpuidle目录下,主要有cpuidle core、cpuidle driver和cpuidle governor三部分构成,再结合kernel sched 中的cpuidle,共同完成cpuidle管理。

cpuidle framework in Linux Kernel(1)概述Why to Idle?CPUidle Framework in LinuxCPU idle流程

kernel sched

主要负责实现idle线程,代码位于kernel/sched/idle.c中。

CPUidle core 模块

Cpuidle core负责实现CPUidle framework的整体框架,主要实现以下功能:

1) 抽象出cpuidle device、cpuidle driver和cpuidle governor;

2) 向cpuidle driver模块,提供统一的driver注册和管理接口;

3) 向cpuidle governor模块,提供统一的governor注册和管理接口;

4) 向上层sched提供接口,比如cpuidle_enter、cpuidle_select等;

5) 以sysfs的形式,向userspace提供接口;

CPUidle governor模块

Cpuidle governor根据当前CPU load,确定进入哪个idle state。

Linux kernel中提供了menu和ladder两种governor,根据具体的场景选择进入哪个idle state,相应的代码在drivers/cpuidle/governors目录下。

CPUidle driver 模块

负责实现CPU idle,即解决如何进入idle state的问题。

不同的arch、CPU core,会有不同的cpuidle driver。你可以在cpuidle core提供的框架下,开发自己的cpuidle driver,我这里分析使用的是acpi cpuidle driver,对应的代码主要在drivers/acpi/processor_idle.c中。

了解了CPUidle framework之后,我们来看如何利用这个framework来实现CPU在normal execution state和low power state之间的转换。

CPU idle流程

进入idle state

CPU从C0切换到low power state时,需要解决以下三个问题:when to idle state?which idle state to enter?how to enter idle state?

  1. when to idle state?

    sched中的idle线程被调度时,表示当前没有其他任务在执行,CPU可以进入到idle state以省电。

  2. which idle state to enter?

    这就需要cpuidle governor来根据当前的CPU load,预计会idle的时间以及系统支持的idle state状态来选择一个合适的idle state了,在满足系统响应responsibility的前提下,尽可能省电。

  3. how to enter idle state?

    这个由cpuidle driver来负责,不同的CPU arch在进入idle state时会有不同的方式,不同的idle state也会有不同的进入方式,这个我们会在cpuidle driver中详细说明。

退出idle state

CPU退出low-power state时,需要解决以下两个问题:什么条件下退出?退回到哪个power state?退回之后需要哪些额外处理?

  1. 什么条件下退出?

    每个low power state,都会定义一些waking event用来让CPU退出当前的power state;

  2. 退回到哪个power state?

    一般是会退回到C0 state;

  3. 退回到C0后,CPU如何操作?

    在进入idle state之前,会调用local_irq_disable关闭local irq。

    因此,退出idle state时,会先退回到idle thread,调用local_irq_enable之后,重启local irq,才能去执行相应的IRQ handler。在IRQ handler里面可能会唤醒其他等待的线程,CPU去执行其他线程;如果没有调度其他线程,则继续执行idle线程。

参考文件

ACPI spec6.0

窝窝科技-cpuidle