天天看點

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