最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

深入分析Linux中斷子系統(tǒng)之中斷控制器及驅(qū)動

2022-12-20 15:20 作者:補給站Linux內(nèi)核  | 我要投稿

說明:

  1. Kernel版本:4.14

  2. ARM64處理器,Contex-A53,雙核

  3. 使用工具:Source Insight 3.5, Visio

1. 概述

從這篇文章開始,來聊一聊中斷子系統(tǒng)。中斷是處理器用于異步處理外圍設(shè)備請求的一種機制,可以說中斷處理是操作系統(tǒng)管理外圍設(shè)備的基石,此外系統(tǒng)調(diào)度、核間交互等都離不開中斷,它的重要性不言而喻。

來一張概要的分層圖:

圖片
  • 硬件層:最下層為硬件連接層,對應(yīng)的是具體的外設(shè)與SoC的物理連接,中斷信號是從外設(shè)到中斷控制器,由中斷控制器統(tǒng)一管理,再路由到處理器上;

  • 硬件相關(guān)層:這個層包括兩部分代碼,一部分是架構(gòu)相關(guān)的,比如ARM64處理器處理中斷相關(guān),另一部分是中斷控制器的驅(qū)動代碼;

  • 通用層:這部分也可以認為是框架層,是硬件無關(guān)層,這部分代碼在所有硬件平臺上是通用的;

  • 用戶層:這部分也就是中斷的使用者了,主要是各類設(shè)備驅(qū)動,通過中斷相關(guān)接口來進行申請和注冊,最終在外設(shè)觸發(fā)中斷時,進行相應(yīng)的回調(diào)處理;

中斷子系統(tǒng)系列文章,會包括硬件相關(guān)、中斷框架層、上半部與下半部、Softirq、Workqueue等機制的介紹,本文會先介紹硬件相關(guān)的原理及驅(qū)動,前戲結(jié)束,直奔主題。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ?



2. GIC硬件原理

  • ARM公司提供了一個通用的中斷控制器GIC(Generic Interrupt Controller),GIC的版本包括V1 ~ V4,由于本人使用的SoC中的中斷控制器是V2版本,本文將圍繞GIC-V2來展開介紹;

來一張功能版的框圖:

圖片
  • GIC-V2從功能上說,除了常用的中斷使能、中斷屏蔽、優(yōu)先級管理等功能外,還支持安全擴展、虛擬化等;

  • GIC-V2從組成上說,主要分為DistributorCPU Interface兩個模塊,Distributor主要負責中斷源的管理,包括優(yōu)先級的處理,屏蔽、搶占等,并將最高優(yōu)先級的中斷分發(fā)給CPU Interface,CPU Interface主要用于連接處理器,與處理器進行交互;

  • Virtual DistributorVirtual CPU Interface都與虛擬化相關(guān),本文不深入分析;

再來一張細節(jié)圖看看DistributorCPU Interface的功能:

圖片
  • GIC-V2支持三種類型的中斷:

    1. SGI(software-generated interrupts):軟件產(chǎn)生的中斷,主要用于核間交互,內(nèi)核中的IPI:inter-processor interrupts就是基于SGI,中斷號ID0 - ID15用于SGI;

    2. PPI(Private Peripheral Interrupt):私有外設(shè)中斷,每個CPU都有自己的私有中斷,典型的應(yīng)用有local timer,中斷號ID16 - ID31用于PPI

    3. SPI(Shared Peripheral Interrupt):共享外設(shè)中斷,中斷產(chǎn)生后,可以分發(fā)到某一個CPU上,中斷號ID32 - ID1019用于SPIID1020 - ID1023保留用于特殊用途;

  • Distributor功能:

    1. 全局開關(guān)控制Distributor分發(fā)到CPU Interface

    2. 打開或關(guān)閉每個中斷;

    3. 設(shè)置每個中斷的優(yōu)先級;

    4. 設(shè)置每個中斷將路由的CPU列表;

    5. 設(shè)置每個外設(shè)中斷的觸發(fā)方式:電平觸發(fā)、邊緣觸發(fā);

    6. 設(shè)置每個中斷的Group:Group0或Group1,其中Group0用于安全中斷,支持FIQ和IRQ,Group1用于非安全中斷,只支持IRQ;

    7. SGI中斷分發(fā)到目標CPU上;

    8. 每個中斷的狀態(tài)可見;

    9. 提供軟件機制來設(shè)置和清除外設(shè)中斷的pending狀態(tài);

  • CPU Interface功能:

    1. 使能中斷請求信號到CPU上;

    2. 中斷的確認;

    3. 標識中斷處理的完成;

    4. 為處理器設(shè)置中斷優(yōu)先級掩碼;

    5. 設(shè)置處理器的中斷搶占策略;

    6. 確定處理器的最高優(yōu)先級pending中斷;

中斷處理的狀態(tài)機如下圖:

圖片
  • Inactive:無中斷狀態(tài);

  • Pending:硬件或軟件觸發(fā)了中斷,但尚未傳遞到目標CPU,在電平觸發(fā)模式下,產(chǎn)生中斷的同時保持pending狀態(tài);

  • Active:發(fā)生了中斷并將其傳遞給目標CPU,并且目標CPU可以處理該中斷;

  • Active and pending:發(fā)生了中斷并將其傳遞給目標CPU,同時發(fā)生了相同的中斷并且該中斷正在等待處理;

GIC檢測中斷流程如下:

  1. GIC捕獲中斷信號,中斷信號assert,標記為pending狀態(tài);

  2. Distributor確定好目標CPU后,將中斷信號發(fā)送到目標CPU上,同時,對于每個CPU,Distributor會從pending信號中選擇最高優(yōu)先級中斷發(fā)送至CPU Interface;

  3. CPU Interface來決定是否將中斷信號發(fā)送至目標CPU;

  4. CPU完成中斷處理后,發(fā)送一個完成信號EOI(End of Interrupt)給GIC;

3. GIC驅(qū)動分析

3.1 設(shè)備信息添加

ARM平臺的設(shè)備信息,都是通過Device Tree設(shè)備樹來添加,設(shè)備樹信息放置在arch/arm64/boot/dts/

下圖就是一個中斷控制器的設(shè)備樹信息:

圖片
  • compatible字段:用于與具體的驅(qū)動來進行匹配,比如圖片中arm, gic-400,可以根據(jù)這個名字去匹配對應(yīng)的驅(qū)動程序;

  • interrupt-cells字段:用于指定編碼一個中斷源所需要的單元個數(shù),這個值為3。比如在外設(shè)在設(shè)備樹中添加中斷信號時,通常能看到類似interrupts = <0 23 4>;的信息,第一個單元0,表示的是中斷類型(1:PPI,0:SPI),第二個單元23表示的是中斷號,第三個單元4表示的是中斷觸發(fā)的類型;

  • reg字段:描述中斷控制器的地址信息以及地址范圍,比如圖片中分別制定了GIC Distributor(GICD)GIC CPU Interface(GICC)的地址信息;

  • interrupt-controller字段:表示該設(shè)備是一個中斷控制器,外設(shè)可以連接在該中斷控制器上;

  • 關(guān)于設(shè)備數(shù)的各個字段含義,詳細可以參考Documentation/devicetree/bindings下的對應(yīng)信息;

設(shè)備樹的信息,是怎么添加到系統(tǒng)中的呢?Device Tree最終會編譯成dtb文件,并通過Uboot傳遞給內(nèi)核,在內(nèi)核啟動后會將dtb文件解析成device_node結(jié)構(gòu)。關(guān)于設(shè)備樹的相關(guān)知識,本文先不展開,后續(xù)再找機會補充。來一張圖,先簡要介紹下關(guān)鍵路徑:

圖片
  • 設(shè)備樹的節(jié)點信息,最終會變成device_node結(jié)構(gòu),在內(nèi)存中維持一個樹狀結(jié)構(gòu);

  • 設(shè)備與驅(qū)動,會根據(jù)compatible字段進行匹配;

3.2 驅(qū)動流程分析

GIC驅(qū)動的執(zhí)行流程如下圖所示:

圖片
  • 首先需要了解一下鏈接腳本vmlinux.lds,腳本中定義了一個__irqchip_of_table段,該段用于存放中斷控制器信息,用于最終來匹配設(shè)備;

  • 在GIC驅(qū)動程序中,使用IRQCHIP_DECLARE宏來聲明結(jié)構(gòu)信息,包括compatible字段和回調(diào)函數(shù),該宏會將這個結(jié)構(gòu)放置到__irqchip_of_table字段中;

  • 在內(nèi)核啟動初始化中斷的函數(shù)中,of_irq_init函數(shù)會去查找設(shè)備節(jié)點信息,該函數(shù)的傳入?yún)?shù)就是__irqchip_of_table段,由于IRQCHIP_DECLARE已經(jīng)將信息填充好了,of_irq_init函數(shù)會根據(jù)arm,gic-400去查找對應(yīng)的設(shè)備節(jié)點,并獲取設(shè)備的信息。中斷控制器也存在級聯(lián)的情況,of_irq_init函數(shù)中也處理了這種情況;

  • or_irq_init函數(shù)中,最終會回調(diào)IRQCHIP_DECLARE聲明的回調(diào)函數(shù),也就是gic_of_init,而這個函數(shù)就是GIC驅(qū)動的初始化入口函數(shù)了;

  • GIC的工作,本質(zhì)上是由中斷信號來驅(qū)動,因此驅(qū)動本身的工作就是完成各類信息的初始化,注冊好相應(yīng)的回調(diào)函數(shù),以便能在信號到來之時去執(zhí)行;

  • set_smp_process_call設(shè)置__smp_cross_call函數(shù)指向gic_raise_softirq,本質(zhì)上就是通過軟件來觸發(fā)GIC的SGI中斷,用于核間交互;

  • cpuhp_setup_state_nocalls函數(shù),設(shè)置好CPU進行熱插拔時GIC的回調(diào)函數(shù),以便在CPU熱插拔時做相應(yīng)處理;

  • set_handle_irq函數(shù)的設(shè)置很關(guān)鍵,它將全局函數(shù)指針handle_arch_irq指向了gic_handle_irq,而處理器在進入中斷異常時,會跳轉(zhuǎn)到handle_arch_irq執(zhí)行,所以,可以認為它就是中斷處理的入口函數(shù)了;

  • 驅(qū)動中完成了各類函數(shù)的注冊,此外還完成了irq_chip,?irq_domain等結(jié)構(gòu)體的初始化,這些結(jié)構(gòu)在下文會進一步分析;

  • 最后,完成GIC硬件模塊的初始化設(shè)置,以及電源管理相關(guān)的注冊等工作;

3.3 數(shù)據(jù)結(jié)構(gòu)分析

先來張圖:

圖片
  • GIC驅(qū)動中,使用struct gic_chip_data結(jié)構(gòu)體來描述GIC控制器的信息,整個驅(qū)動都是圍繞著該結(jié)構(gòu)體的初始化,驅(qū)動中將函數(shù)指針都初始化好,實際的工作是由中斷信號觸發(fā),也就是在中斷來臨的時候去進行回調(diào);

  • struct irq_chip結(jié)構(gòu),描述的是中斷控制器的底層操作函數(shù)集,這些函數(shù)集最終完成對控制器硬件的操作;

  • struct irq_domain結(jié)構(gòu),用于硬件中斷號和Linux IRQ中斷號(virq,虛擬中斷號)之間的映射;

還是上一下具體的數(shù)據(jù)結(jié)構(gòu)代碼吧,關(guān)鍵注釋如下:

3.3.1 IRQ domain

IRQ domain用于將硬件的中斷號,轉(zhuǎn)換成Linux系統(tǒng)中的中斷號(virtual irq, virq),來張圖:

圖片
  • 每個中斷控制器都對應(yīng)一個IRQ Domain;

  • 中斷控制器驅(qū)動通過irq_domain_add_*()接口來創(chuàng)建IRQ Domain;

  • IRQ Domain支持三種映射方式:linear map(線性映射),tree map(樹映射),no map(不映射);

    1. linear map:維護固定大小的表,索引是硬件中斷號,如果硬件中斷最大數(shù)量固定,并且數(shù)值不大,可以選擇線性映射;

    2. tree map:硬件中斷號可能很大,可以選擇樹映射;

    3. no map:硬件中斷號直接就是Linux的中斷號;

三種映射的方式如下圖:

圖片
  • 圖中描述了三個中斷控制器,對應(yīng)到三種不同的映射方式;

  • 各個控制器的硬件中斷號可以一樣,最終在Linux內(nèi)核中映射的中斷號是唯一的;

4. Arch-speicific代碼分析

  • 中斷也是異常模式的一種,當外設(shè)觸發(fā)中斷時,處理器會切換到特定的異常模式進行處理,而這部分代碼都是架構(gòu)相關(guān)的;ARM64的代碼位于arch/arm64/kernel/entry.S

  • ARM64處理器有四個異常級別Exception Level:0~3,EL0級對應(yīng)用戶態(tài)程序,EL1級對應(yīng)操作系統(tǒng)內(nèi)核態(tài),EL2級對應(yīng)Hypervisor,EL3級對應(yīng)Secure Monitor;

  • 異常觸發(fā)時,處理器進行切換,并且跳轉(zhuǎn)到異常向量表開始執(zhí)行,針對中斷異常,最終會跳轉(zhuǎn)到irq_handler中;

代碼比較簡單,如下:

來張圖:

圖片
  • 中斷觸發(fā),處理器去異常向量表找到對應(yīng)的入口,比如EL0的中斷跳轉(zhuǎn)到el0_irq處,EL1則跳轉(zhuǎn)到el1_irq處;

  • 在GIC驅(qū)動中,會調(diào)用set_handle_irq接口來設(shè)置handle_arch_irq的函數(shù)指針,讓它指向gic_handle_irq,因此中斷觸發(fā)的時候會跳轉(zhuǎn)到gic_handle_irq處執(zhí)行;

  • gic_handle_irq函數(shù)處理時,分為兩種情況,一種是外設(shè)觸發(fā)的中斷,硬件中斷號在16 ~ 1020之間,一種是軟件觸發(fā)的中斷,用于處理器之間的交互,硬件中斷號在16以內(nèi);

  • 外設(shè)觸發(fā)中斷后,根據(jù)irq domain去查找對應(yīng)的Linux IRQ中斷號,進而得到中斷描述符irq_desc,最終也就能調(diào)用到外設(shè)的中斷處理函數(shù)了;

原文作者:LoyenWang



深入分析Linux中斷子系統(tǒng)之中斷控制器及驅(qū)動的評論 (共 條)

分享到微博請遵守國家法律
郓城县| 神木县| 普安县| 永春县| 班戈县| 呼伦贝尔市| 黎川县| 西乌珠穆沁旗| 玛沁县| 桃园县| 海阳市| 丁青县| 浑源县| 东兰县| 碌曲县| 宜州市| 邵东县| 长岭县| 泗阳县| 瑞丽市| 澳门| 清水河县| 永顺县| 石棉县| 雅江县| 同仁县| 华坪县| 台南市| 德令哈市| 广元市| 康定县| 云霄县| 灵寿县| 商城县| 扎囊县| 西畴县| 康马县| 阿坝| 吉安县| 石河子市| 台东县|