跳到主要內容

【原創】Linux中斷子系統(一)-中斷控制器及驅動分析_租車


※超省錢租車方案



商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!


背景



  • Read the fucking source code! --By 魯迅

  • A picture is worth a thousand words. --By 高爾基


說明:



  1. Kernel版本:4.14

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

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


1. 概述


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


來一張概要的分層圖:




  • 硬件層:最下層為硬件連接層,對應的是具體的外設與SoC的物理連接,中斷信號是從外設到中斷控制器,由中斷控制器統一管理,再路由到處理器上;

  • 硬件相關層:這個層包括兩部分代碼,一部分是架構相關的,比如ARM64處理器處理中斷相關,另一部分是中斷控制器的驅動代碼;

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

  • 用戶層:這部分也就是中斷的使用者了,主要是各類設備驅動,通過中斷相關接口來進行申請和註冊,最終在外設觸發中斷時,進行相應的回調處理;


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


2. GIC硬件原理



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


來一張功能版的框圖:




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

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

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


再來一張細節圖看看DistributorCPU Interface的功能:




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



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

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

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


  • Distributor功能:



    1. 全局開關控制Distributor分發到CPU Interface

    2. 打開或關閉每个中斷;

    3. 設置每个中斷的優先級;

    4. 設置每个中斷將路由的CPU列表;

    5. 設置每個外設中斷的觸發方式:電平觸發、邊緣觸發;

    6. 設置每个中斷的Group:Group0或Group1,其中Group0用於安全中斷,支持FIQ和IRQ,Group1用於非安全中斷,只支持IRQ;

    7. SGI中斷分發到目標CPU上;

    8. 每个中斷的狀態可見;

    9. 提供軟件機制來設置和清除外設中斷的pending狀態;


  • CPU Interface功能:



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

    2. 中斷的確認;

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

    4. 為處理器設置中斷優先級掩碼;

    5. 設置處理器的中斷搶佔策略;

    6. 確定處理器的最高優先級pending中斷;



中斷處理的狀態機如下圖:




  • Inactive:無中斷狀態;

  • Pending:硬件或軟件觸發了中斷,但尚未傳遞到目標CPU,在電平觸發模式下,產生中斷的同時保持pending狀態;

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

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


GIC檢測中斷流程如下:



  1. GIC捕獲中斷信號,中斷信號assert,標記為pending狀態;

  2. Distributor確定好目標CPU后,將中斷信號發送到目標CPU上,同時,對於每個CPU,Distributor會從pending信號中選擇最高優先級中斷髮送至CPU Interface

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

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


3. GIC驅動分析


3.1 設備信息添加


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


下圖就是一个中斷控制器的設備樹信息:


※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益



有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。






  • compatible字段:用於與具體的驅動來進行匹配,比如圖片中arm, gic-400,可以根據這個名字去匹配對應的驅動程序;

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

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

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

  • 關於設備數的各個字段含義,詳細可以參考Documentation/devicetree/bindings下的對應信息;


設備樹的信息,是怎麼添加到系統中的呢?Device Tree最終會編譯成dtb文件,並通過Uboot傳遞給內核,在內核啟動後會將dtb文件解析成device_node結構。關於設備樹的相關知識,本文先不展開,後續再找機會補充。來一張圖,先簡要介紹下關鍵路徑:




  • 設備樹的節點信息,最終會變成device_node結構,在內存中維持一個樹狀結構;

  • 設備與驅動,會根據compatible字段進行匹配;


3.2 驅動流程分析


GIC驅動的執行流程如下圖所示:




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

  • 在GIC驅動程序中,使用IRQCHIP_DECLARE宏來聲明結構信息,包括compatible字段和回調函數,該宏會將這個結構放置到__irqchip_of_table字段中;

  • 在內核啟動初始化中斷的函數中,of_irq_init函數會去查找設備節點信息,該函數的傳入參數就是__irqchip_of_table段,由於IRQCHIP_DECLARE已經將信息填充好了,of_irq_init函數會根據arm,gic-400去查找對應的設備節點,並獲取設備的信息。中斷控制器也存在級聯的情況,of_irq_init函數中也處理了這種情況;

  • or_irq_init函數中,最終會回調IRQCHIP_DECLARE聲明的回調函數,也就是gic_of_init,而這個函數就是GIC驅動的初始化入口函數了;

  • GIC的工作,本質上是由中斷信號來驅動,因此驅動本身的工作就是完成各類信息的初始化,註冊好相應的回調函數,以便能在信號到來之時去執行;

  • set_smp_process_call設置__smp_cross_call函數指向gic_raise_softirq,本質上就是通過軟件來觸發GIC的SGI中斷,用於核間交互;

  • cpuhp_setup_state_nocalls函數,設置好CPU進行熱插拔時GIC的回調函數,以便在CPU熱插拔時做相應處理;

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

  • 驅動中完成了各類函數的註冊,此外還完成了irq_chip, irq_domain等結構體的初始化,這些結構在下文會進一步分析;

  • 最後,完成GIC硬件模塊的初始化設置,以及電源管理相關的註冊等工作;


3.3 數據結構分析


先來張圖:




  • GIC驅動中,使用struct gic_chip_data結構體來描述GIC控制器的信息,整個驅動都是圍繞着該結構體的初始化,驅動中將函數指針都初始化好,實際的工作是由中斷信號觸發,也就是在中斷來臨的時候去進行回調;

  • struct irq_chip結構,描述的是中斷控制器的底層操作函數集,這些函數集最終完成對控制器硬件的操作;

  • struct irq_domain結構,用於硬件中斷號和Linux IRQ中斷號(virq,虛擬中斷號)之間的映射;


還是上一下具體的數據結構代碼吧,關鍵註釋如下:


struct irq_chip {
struct device *parent_device; //指向父設備
const char *name; // /proc/interrupts中显示的名字
unsigned int (*irq_startup)(struct irq_data *data); //啟動中斷,如果設置成NULL,則默認為enable
void (*irq_shutdown)(struct irq_data *data); //關閉中斷,如果設置成NULL,則默認為disable
void (*irq_enable)(struct irq_data *data); //中斷使能,如果設置成NULL,則默認為chip->unmask
void (*irq_disable)(struct irq_data *data); //中斷禁止

void (*irq_ack)(struct irq_data *data); //開始新的中斷
void (*irq_mask)(struct irq_data *data); //中斷源屏蔽
void (*irq_mask_ack)(struct irq_data *data); //應答並屏蔽中斷
void (*irq_unmask)(struct irq_data *data); //解除中斷屏蔽
void (*irq_eoi)(struct irq_data *data); //中斷處理結束后調用

int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force); //在SMP中設置CPU親和力
int (*irq_retrigger)(struct irq_data *data); //重新發送中斷到CPU
int (*irq_set_type)(struct irq_data *data, unsigned int flow_type); //設置中斷觸發類型
int (*irq_set_wake)(struct irq_data *data, unsigned int on); //使能/禁止電源管理中的喚醒功能

void (*irq_bus_lock)(struct irq_data *data); //慢速芯片總線上的鎖
void (*irq_bus_sync_unlock)(struct irq_data *data); //同步釋放慢速總線芯片的鎖

void (*irq_cpu_online)(struct irq_data *data);
void (*irq_cpu_offline)(struct irq_data *data);

void (*irq_suspend)(struct irq_data *data);
void (*irq_resume)(struct irq_data *data);
void (*irq_pm_shutdown)(struct irq_data *data);

void (*irq_calc_mask)(struct irq_data *data);

void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
int (*irq_request_resources)(struct irq_data *data);
void (*irq_release_resources)(struct irq_data *data);

void (*irq_compose_msi_msg)(struct irq_data *data, struct msi_msg *msg);
void (*irq_write_msi_msg)(struct irq_data *data, struct msi_msg *msg);

int (*irq_get_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool *state);
int (*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);

int (*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);

void (*ipi_send_single)(struct irq_data *data, unsigned int cpu);
void (*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);

unsigned long flags;
};

struct irq_domain {
struct list_head link; //用於添加到全局鏈表irq_domain_list中
const char *name; //IRQ domain的名字
const struct irq_domain_ops *ops; //IRQ domain映射操作函數集
void *host_data; //在GIC驅動中,指向了irq_gic_data
unsigned int flags;
unsigned int mapcount; //映射中斷的個數

/* Optional data */
struct fwnode_handle *fwnode;
enum irq_domain_bus_token bus_token;
struct irq_domain_chip_generic *gc;
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
struct irq_domain *parent; //支持級聯的話,指向父設備

留言

這個網誌中的熱門文章

旅館疑有臭蟲 北市府稽查找嘸

有民眾抱怨,日前投宿的北市某旅館疑似出現臭蟲,北市觀傳局與衛生局、環保局聯合稽查,但因為沒有發現蟲屍,無法確認該旅館是否真有臭蟲,市府下周將召開專家會議處理該案,市長蔣萬安則允諾會以最高規格防範臭蟲。 北市某旅館傳出疑有臭蟲,議員陳宥丞23日在市政總質詢詢問市府處理進度,並指出法國、澳洲、韓國的臭蟲,起初都現蹤公車或地鐵卻沒被發現,直到大規模爆發,才付出大量社會成本處理,而且一般殺蟲劑無法殺掉臭蟲,北市是否有因應措施? 觀傳局主任祕書蕭君杰表示,21日聯合環保局、衛生局到該旅館稽查,但沒有發現臭蟲,也沒有查到蟲卵跡象,只能檢查現場環境是否符合衛生相關規定,但環保局有指導業者如何針對臭蟲清潔消毒。觀傳局長王秋冬指出,下周會與專家學者召開會議,以最高規格處理此案。 想知道購買電動車哪裡補助最多? 台中電動車 補助資訊懶人包彙整 ;推薦評價好的 iphone維修 中心擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢住家的頂樓裝 太陽光電 聽說可發揮隔熱功效一線推薦東陽能源擁有核心技術、產品研發、系統規劃設置、專業團隊的太陽能發電廠商。 網頁設計 一頭霧水該從何著手呢? 回頭車 貨運收費標準宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念 台中搬家公司 教你幾個打包小技巧,輕鬆整理裝箱!還在煩惱搬家費用要多少哪?台中大展搬家線上試算搬家費用,從此不再擔心「物品怎麼計費」、「多少車才能裝完」 台中搬家 公司費用怎麼算?擁有20年純熟搬遷經驗,提供免費估價且流程透明更是5星評價的搬家公司好山好水 露營車 漫遊體驗露營車x公路旅行的十一個出遊特色。走到哪、玩到哪,彈性的出遊方案,行程跟出發地也可客製 廣告預算用在刀口上, 台北網頁設計 公司幫您達到更多曝光效益; 電動車補助 衛生局疾病管制科長張惠美表示,現場查到與臭蟲無關的多項衛生缺失,包含未提供從業人員體檢報告、簡易外傷藥品及器材超過有效期、紗窗有破損等,已要求業者2周內改善,將擇期複查,如果複查不合格,將依法裁罰3000元至2萬元罰鍰。 但陳宥丞批評,環保局未公告哪些藥劑能殺死臭蟲,很擔心北市會和韓國、法國一樣,把臭蟲防治交給民間恐造成大規模爆發,且北市內的廢棄傢俱回收廠也有可能成為臭蟲孳生的...

必知必會-存儲器層次結構

相信大家一定都用過各種存儲技術,比如mysql,mongodb,redis,mq等,這些存儲服務性能有非常大的區別,其中之一就是底層使用的存儲設備不同。作為一個程序員,你需要理解存儲器的層次結構,這樣才能對程序的性能差別瞭然於心。今天帶大家了解下計算機系統存儲器的層次結構。 存儲技術 首先了解下什麼是存儲器系統? 實質上就是一個具有不同容量、成本和訪問時間的存儲設備的層次結構。從快到慢依次為:CPU寄存器、高速緩存、主存、磁盤; 這裏給大家介紹一組數據,讓大家有一個更清晰的認識: 如果數據存儲在CPU寄存器,需要0個時鐘周期就能訪問到,存儲在高速緩存中需要4~75個時鐘周期。如果存儲在主存需要上百個周期,而如果存儲在磁盤上,大約需要幾千萬個周期! -- 出自 CSAPP 接下來一起深入了解下計算機系統涉及的幾個存儲設備: 隨機訪問存儲器 隨機訪問存儲器(RAM)分為靜態RAM (SRAM) 和動態RAM(DRAM)。SRAM的速度更快,但也貴很多,一般不會超過幾兆字節,通常用來做告訴緩存存儲器。DRAM就是就是我們常說的主存。 訪問主存 數據流是通過操作系統中的總線的共享电子電路在處理器和DRAM之間來來回回。每次CPU和主存之間的數據傳送都是通過一系列複雜的步驟完成,這些步驟成為總線事務。讀事務是將主存傳送數據到CPU。寫事務從CPU傳送數據到主存。 總線是一組并行的導線,能攜帶地址、數據和控制信號。下圖展示了CPU芯片是如何與主存DRAM連接的。 那麼我們在加載數據和存儲數據時,CPU和主存到底是怎樣交互實現的呢? 首先來看一個基本指令,加載內存數據到CPU寄存器中: movq A,%rax 將地址A的內容加載到寄存器%rax中,這個命令會使CPU芯片上稱為總線接口(bus interface)的電路在總線上發起讀事務,具體分為三個步驟: CPU將地址A放到系統總線上,I/O橋將信號傳遞到內存總線。詳情看下下圖a 主存感覺到內存總線上的地址信號,從內存總線讀地址,從DRAM取出數據字,將其寫到內存總線。I/O橋將內存總線信號翻譯成系統總線信號,沿着系統總線傳遞到CPU總線接口。下圖b CPU感覺到系統總線上的數據,從總線上讀數據,並將數據複製到寄存器%rax...

2016年電動車和插電式混合動力車銷量預計將超過70萬輛

中汽協日前預測,2016年全國電動汽車和插電式混合動力車的銷量預計將超過70萬輛,較2015年的銷量增長一倍。 2015年電動車和插電式混合動力車的合併銷量為331092輛,較2014年增長了340%。其中包括247482輛電動車和83610輛插電式混合動力車,在24萬輛多的電動汽車銷量中,包括146719輛乘用車,另有100763輛為商用車。插電式混合動力車的銷量中,60663輛為乘用車,22947輛為商用車。 根據2015年起草的藍圖,政府計畫到2020年在全國範圍內新建12000個充電站和480枚充電樁。2014年年底,全國共有780個充電站共31000枚充電樁。2015年政府還為27個省市自治區設定了電動車的最低銷量目標。 政府預計,這些措施到位後,自主品牌車企的電動車和插電式混合動力車銷量到2020年可達100萬輛,到2025年可達300萬輛。 本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理 【其他文章推薦】 ※為什麼 USB CONNECTOR 是電子產業重要的元件? ※ 網頁設計 一頭霧水??該從何著手呢? 找到專業技術的 網頁設計公司 ,幫您輕鬆架站! ※想要讓你的商品成為最夯、最多人討論的話題? 網頁設計公司 讓你強力曝光 ※想知道最厲害的 台北網頁設計公司推薦 、 台中網頁設計公司推薦 專業設計師"嚨底家"!! Orignal From: 2016年電動車和插電式混合動力車銷量預計將超過70萬輛