那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

UEFI中的中斷處理流程

冬至子 ? 來源:UEFI社區 ? 作者:Wolf ? 2023-06-30 11:48 ? 次閱讀

1

中斷向量表

你有沒有好奇過,0內存地址開始放了些什么東西呢?畢竟是最開始就要用的東西,一定非常重要!沒錯,那里就是中斷向量表的家。在8086開始,中斷向量表就占據這里,甚至在我們最新時髦的酷睿x代,它們還在這里。想不想看看這個頑固的家伙的樣子?寫個簡單的 程序:

long *p = (long *) 0;

printf(“%x”, *p);

運行下看看。不出所料你的程序將產生一個異常,導致被強制關閉。還記得我們前面講過地址轉換,這個0地址是虛擬地址而不是物理地址,在保護模式下0的虛擬地址訪問會產生一個異常,你是訪問不到物理0地址的。我們在內核模式使用一些技巧或者我們進入實模式,我們才能看到它們。每個中斷向量(vector)占據4個字節,Intel定義了256個向量,共用去1KB的內存空間。每個向量樸實無華,就是一個地址,指向該中斷(INT)處理函數的入口,這也是它起名vector的原因。整個中斷向量表就是一個大函數指針表,一個中斷發生,CPU硬件就來這里查表,跳到相應地址就行了,好方便!實際情況稍微復雜點,CPU還要保護現場,將當前環境保存起來(一些寄存器和返回地址等壓棧),以便處理完后返回現場繼續執行。不過相對于我們接下來的保護模式的中斷處理簡單很多。沒錯,這個史前遺跡只在實模式發揮作用,我們只草草看看它的樣子就行了:

圖片

這里主要是異常處理

圖片

硬件中斷向量一區。和我們上文的8259連接兩相對照一下:

圖片

沒錯,這里就是主8259的IRQ的中斷向量區。接下來就是BIOS保留區,作為介紹BIOS的專區,這里必須看一下:

圖片

PC傳統Legacy BIOS的服務例程都在這里。看到它們不勝唏噓,曾經INT 10H打字和INT 13H讀寫磁盤的美(YUAN)好(SHI)日子又浮現在眼前。。。不好,這是個暴露年齡的話題,后面我們就不講了,下課。

開個玩笑,不過中斷向量表今天也只在UEFI BIOS為了兼容傳統OS啟動的CSM模塊中起作用,我們大致了解一下其中的原理即可。

2

中斷描述符

在PC進入保護模式,一個復雜但有很多妙處的機制代替了中斷向量表,它就是中斷描述符表(IDT,interrupt Descriptor Table)。IDT將每個中斷或者異常與它的服務例程連接起來。IDT不再固定放在某個位置,而是可以放在IDTR寄存器指向的任意內存(說是任意,也不能太隨性,有些小要求,如8字節對齊等),IDT的表項也從4個字節擴展到8個字節,大小也可以不滿256,IDTR也指出了它的最大限制。如圖:

圖片

IDT除了和中斷向量一樣指向一個例程地址之外,還包括其他一些信息

圖片

其中的DPL(描述符特權級)與CS寄存器的CPL完成特權級的檢查,可以避免低特權級的代碼通過軟件中斷形式提權。它的運作形式和中斷向量表類似,更多的是安全檢查和可能的執行環境切換(例如ring 3 -> ring 0)。

3

中斷和異常

ARM體系中斷和異常是單獨處理的,IRQ中斷只是異常列表里的一項而已。X86中斷和異常處理卻混雜在一起,使用同一套機制,看似比較混亂。其實異常往往是處理器內部發生的,是同步的;而中斷卻是外部事件,是異步的。而它們的分布也是不同的,0到31號向量保留給異常,而更高的則往往是硬件中斷和軟件中斷。異常分為三種:錯誤,陷阱和中止。這三種類型CPU對它們有不同的處理原則:錯誤往往是可以恢復的,錯誤修正后再執行剛才的錯誤就不會出問題了,改了就是好同志嘛!例如常用于內存管理的缺頁異常,OS常常把內存換出到硬盤,它會在頁表上動些手腳,CPU再次訪問這塊內存會發生異常,OS頁面錯誤異常例程捕獲到后趕緊把內存換回來,然后返回原處執行,就像沒事發生一樣。陷阱是留給軟件挖坑的,CPU希望軟件自己挖的坑自己能填上,它可以裝作沒看見,從下條繼續。典型的例子是INT 3,我們的幾乎所有調試工具(VS,windbg,甚至UEFI的source level debugger)都用它添加軟件斷點。中止就嚴重了,意味著發生硬件錯誤了,它往往能造成Windows藍屏,linux panic等。異常一覽表如下:

圖片

20到31被預留將來使用。硬件中斷往往就從32開始。

4

中斷優先級

PIC模式IRQ數目越低就意味著優先級越高。而在APIC模式下,IOAPIC連接的24個IRQ是平權的,先后并不關乎優先級高低。決定中斷優先級的是它對應的中斷向量的大小,X86體系有256個vector, 中斷優先級的計算公式是:

優先級 = vector num / 16

即每16個中斷一組,共享一個優先級,共16個。因為32以下vector被異常和保留占據,2到15是中斷的優先級。數字越大越高優先級。中斷優先級的控制是靠LAPIC的TPR(Task Priority Register,任務優先級寄存器)來控制的,它的結構如下:

圖片

TR只有4位標識可以接受的中斷優先級,即16個。CPU內核只處理優先級比TR大的中斷,也意味著TR每提高一個數字,就有16個中斷被遮蔽!看來我們的中斷要想被趕快處理,必須占個好位置。那么是不是IRQ數目越大,vector就越大呢?這是誰來決定的呢?這事可不由BIOS做主,OS是設置vector的主人。而不同的OS的處理也不近相同,我們具體看一下。

中斷處理實踐

Windows、Linux和BIOS在處理中斷上有很多區別。我們從幾個方面浮光掠影了解一二。

1

中斷向量設置

PIC如何設置中斷向量已經過時,我們就不提了。這里只介紹APIC模式,如果你還記得上節關于IOAPIC的內容,其中最重要的PRT表,它由24個RTE( RedirectionTableEntry)項組成,每一項對應一個IRQ引腳。它的內容除了上節介紹過的Destination Field之外,最低8位是該IRQ對應的vector,可以表示256個vector。OS根據自己的策略,為IRQ分配不同的vector。

1. Windows:

Windows的HAL在設置vector時是根據系統枚舉硬件時挨個設置的,因為先枚舉的設備其IRQ的大小不確定,所以優先級并無一定之規。從vector不能推導IRQ,IRQ也不能推導vector,可以說全憑運氣。為硬件IRQ分配的vector往往從0x31開始分配,應該是為了配合Windows的IRQL概念。大家可以在windbg里輸入命令

!idt -a

查看一下自己機器的vector分配情況。這個IRQL比較讓人混淆,實際上它并不是個硬件概念,和中斷優先級并不同,它是微軟定義的一套軟件優先級方案。Windows用0到31來表示優先級,數值越大,優先級越高。如下圖:

圖片

其中DPC/Dispatch是個分水嶺,運行在這個優先級的線程不會被其他線程搶占。其上3到26是為了外圍硬件保留的。最高的31顯得很高大上,誰的地位這么高?你一定見過它,它就是在Windows藍屏時的IRQL。HAL會把IRQL翻譯到不同的硬件平臺上,它和X86的中斷優先級不是一個概念。

2. Linux:

Linux沒有IRQL的概念,他的vector就從0x20(32)開始分配,但是因為0x80(128)因為歷史原因,被保留做系統調用(后改用sysenter指令,但為了兼容,還是保留),整個空間被一份為二。后面到0xee(238)為止。因為vector的大小關系到優先級,分配的時候為了保證對各個IOAPIC公平,分配的時候在各個IOAPIC間輪流分配。大家可以在shell里輸入以下命令查看一下中斷向量的分配情況:

cat /proc/interrupts

2

IRQ在多處理器的分發

還有個問題十分重要。某個vector由哪個CPU內核負責處理呢?Linux為了公平起見,并不會對BSP(bootstrap processor)另眼看待,所有內核一視同仁。Linux通過填寫IOAPIC的RTE中的Delivery mode選擇最低優先級策略,讓TRP都被初始化做固定值,因此IRQ信號就可以公平的在CPU之間分發。感覺很民主有沒有?(分分鐘被Linus的獨裁作風打臉)。有時為了優化性能,我們可以通過Linux的IRQ親緣性來讓特定內核為我們服務。我們可以通過命令

cat /proc/irq/xx/smp_affinity

查看xx IRQ由誰處理,如果是f的話代表是缺省策略,即大家都可以處理。我們可以通過下面命令分配個專有內核處理

echo 2 >/proc/irq/xx/smp_affinity

讓APIC ID為2的內核處理。或者通過一些Irqbalance類似的工具來幫我們配置。

3

UEFI固件中的中斷

UEFI固件內核中對異常和中斷都有處理,還包含很多使用IPI調度內核的源程序,程序短小精干,包括大量注釋。感興趣的同學可以通過它學習中斷處理和CPU內核調度。

1. 異常

UEFI內核對IDT的初始化程序在UefiCpuPkg的Library/CpuExceptionHandlerLib下。內核為所有的的中斷和異常都分配了統一的入口CommonExceptionHandler。它對任何中斷和異常沒有任何特殊處理,如果沒有人對該中斷或異常做處理就會dump一些現在的CPU狀態如APIC ID, 異常類型等,然后調用CpuDeadLoop陷入死循環,這也是UEFI工程師常見的畫面。UEFI驅動可以在自己關心的異常中添加自己的處理函數,如支持通過串口和USB源程序級調試UEFI程序的Source Level Debugger就是個典型的例子,它Hook住了很多異常,用于調試和捕捉錯誤,

2. 中斷

UEFI的CSM模塊還兼容以前BIOS使用的INT x軟中斷方式調用BIOS服務。隨著UEFI的廣泛推廣和傳統OS的漸漸淘汰,CSM也日薄西山,有些僅僅面向最新OS的項目都不含CSM的支持,所以關于它的內容這里略過。在保護模式下,UEFI內核僅僅對時鐘中斷進行了處理,并通過Timer Architectural Protocol開放出來供所有UEFI程序調用。也許你會好奇,那么多種USB設備和網卡等等的UEFI驅動難道不需要中斷處理?是的,他們的中斷在UEFI階段都沒有開啟,他們的驅動通過Timer加Polling的方式來處理。舉個例子,我們在UEFI Shell 下插入鍵盤,它能立刻起作用不是如在OS中USB控制器產生了中斷。而是USB驅動注冊了個Timer,過一會就Poll一下看看有沒有新設備插入。就是這個Timer發現了新插入的鍵盤的。

這種僅僅依靠Timer的做法在OS階段是行不通的,會帶來嚴重的效能和功耗問題。但是在Boot階段卻問題不大,而且這樣做保證了UEFI內核的簡潔性。事實上,UEFI并不禁止驅動自己開啟中斷,但開啟中斷需要處理的中斷共享、IOAPIC設置等等問題需要驅動自己解決,UEFI并不提供支持。

3. IPI

內核可以通過寫自己LAPIC的ICR(Interrupt Command Register)發出IPI((Inter-Processor Interrupt)調度別的內核完成任務,這也是任務調度的基本方法。事實上,因為APIC ID的不連續性,我們正是通過發送IPI的方法來統計內核的數量。BSP在啟動時需要統計系統中可用的內核時,發送廣播IPI,讓大家都來報道,BSP開始點數,1,2,3。。。并一一記錄在案。在啟動OS前,通過ACPI table告訴OS有多少個內核。OS不應該自己統計內核數目,事實上固件可以通過瞞報內核的方式將部分內核挪作他用,但誰會這么做呢?

如何發起IPI在CPU package里有大量實例和庫,大家可以參考。

其他

一些容易混淆的名詞這里要特別說明一下

IRQ x:起源于PIC,指中斷引腳,后在APIC時代沿用,泛指中斷號。

Vector x/INT x: X是中斷向量,如前文所說 IRQ不等于INT和vector.

PIRQ : PCI IRQ。它是描述南橋內部PCI設備的IRQ配置關系的。我們下一篇文章介紹。

GSI :Global System Interrupt,是ACPI spec規定的全局中斷表。它為多IOAPIC情況下確定了系統唯一的一個中斷號。例如IOAPIC1有24個IRQ,IOAPIC2也有24個IRQ,則IOAPIC2 的GSI是從24開始,GSI = 24 + IRQ(IOAPIC2)。

SCI :System Control Interrupt,系統控制中斷,是ACPI定義的,專用于ACPI電源管理的一個IRQ。它在Intel平臺上常常與南橋的電源管理模塊一起,當外部EC等發生Event后會引發SCI。Windows的SCI ISR程序就是著名的acpi.sys。acpi.sys在收到SCI后會檢查GPE狀態寄存器以確定是誰引發的event,然后按照ACPI spec要求調用相應Method。詳情請參照ACPI spec。可以認為SCI是ACPI定義的所有電源管理事件的總入口,它對應的IRQ在一般情況下是不能修改的。SCI是如何報告和簡單的GPE method我們在下一篇中會詳細介紹。

結語

說了這么多,如果我們從硬件和軟件方面,梳理整個中斷設置和處理的鏈條,會發現還有個環節沒有解決。那就設備的IRQ是誰來決定的?是硬件hard wired?還是軟件可以配置?OS是如何知道這些信息的呢?OS又是怎么知道IOAPIC的數目和位置的呢?這些都是UEFI固件需要解決的問題,我們在下一篇文章中會詳細說明。在此之前,如以往一樣,有幾個思考問題可以讓大家加深對中斷和UEFI的理解:

1.中斷的引入,必然帶來了代碼重入的問題。我們知道,這可以通過設定優先級、信號量/臨界區等等辦法來解決。UEFI是通過什么方法呢?TPL和IRQL的相似和區別又是什么呢?

2.UEFI內核還不支持多線程,我們如果需要增加多線程調度,僅僅依靠時鐘中斷,夠不夠用呢?

3.OS利用缺頁異常可以調度內存到硬盤上和實現Lazy loading等等實用的功能。UEFI的SMM內核也開啟了缺頁異常,但是卻為了另外一個目的,你能看出是為了什么嗎?

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5363

    瀏覽量

    121198
  • ARM處理器
    +關注

    關注

    6

    文章

    361

    瀏覽量

    41942
  • 中斷處理
    +關注

    關注

    0

    文章

    94

    瀏覽量

    11016
  • Linux驅動
    +關注

    關注

    0

    文章

    43

    瀏覽量

    10015
  • DPL芯片
    +關注

    關注

    0

    文章

    2

    瀏覽量

    5769
收藏 人收藏

    評論

    相關推薦

    ARM系統預引導固件的新機遇-UEFI

    固件之間的接口。此外,UEFI的平臺初始化(PI)負責定義固件到芯片之間和固件內部的接口。 UEFI處理器架構無關。  ARM公司,蘋果,惠普和微軟的專家們一起確定了UEFI的ARM
    發表于 08-23 09:06

    UEFI有什么定義?

     EFI的出現第一次被正式提出,是在2000年的Intel春季IDF上,經過幾次修訂,現在已經到了EFI 1.10版,而2.0版正由UEFI這個組織制定(故EFI也現稱為UEFI)。
    發表于 10-30 09:12

    如何切換BIOS啟動與UEFI啟動 bios與uefi切換方法

    1.首先進入BIOS,電腦開機時按你電腦對應的鍵進入BIOS,不知道按鍵可以看下表查詢。或者在電腦開機時有屏幕有短暫的提示按鍵,看下自己的電腦按鍵是哪個就行。2.開啟UEFI方法以下的設置項有的
    發表于 06-05 11:54

    結合生活例子,講講中斷處理流程

    的事件打斷了。仔細研究一下生活中斷,對于我們學習單片機的中斷也很有好處。中斷處理流程可以分
    發表于 08-28 07:41

    HAL庫外部中斷處理流程

    文章目錄一、中斷1、中斷全過程2、中斷優先級3、HAL庫外部中斷處理流程4、
    發表于 01-12 07:33

    中斷處理函數(IRQHandler)的標準流程

      大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是以i.MXRT的GPIO模塊為例談談中斷處理函數(IRQHandler)的標準流程。  在痞子衡舊文 《串口(UART)自動波
    發表于 02-09 07:10

    8253中斷服務程序流程

    8253中斷服務程序流程圖 希望發電機P =
    發表于 05-03 00:12 ?4949次閱讀
    8253<b class='flag-5'>中斷</b>服務程序<b class='flag-5'>流程</b>圖

    linux中斷處理之IRQ中斷

    在前一個專題里曾分析過所有IRQ中斷處理流程,經過SAVE_ALL保存硬件環境后,都會進入do_IRQ()進行處理,今天接著分析do_IRQ()處理
    發表于 05-10 10:57 ?2677次閱讀

    處理異常和中斷解決

    異常是能夠引起程序流偏離正常流程的事件,當異常發生時,正在執行的程序就會被掛起,處理器轉而執行一塊與該事件相關的代碼(異常處理)。事件可以是外部輸入,也可以是內部產生的,外部產生的事件通常被稱作
    的頭像 發表于 10-12 17:14 ?5184次閱讀

    STM32中斷系統的工作流程

    一、前言 在之前的STM32的中斷系統理論基礎知識之基本原理及NVIC,分別中斷的基本原理,中斷的管理機制和中斷
    的頭像 發表于 06-22 09:17 ?2723次閱讀
    STM32<b class='flag-5'>中斷</b>系統的工作<b class='flag-5'>流程</b>

    中斷的完整流程是什么樣子

    Service Routine, ISR)。這個函數是用于處理特定中斷的程序,當發生中斷時,處理器會跳轉到這個函數執行相應的操作。 ?將中斷
    的頭像 發表于 10-30 17:12 ?1212次閱讀

    中斷及ARM體系中斷處理

    今天來看一下中斷及ARM體系中斷處理,直接進入正題。 中斷是指計算機運行過程,出現某些意
    的頭像 發表于 11-07 17:11 ?813次閱讀
    <b class='flag-5'>中斷</b>及ARM體系<b class='flag-5'>中</b>對<b class='flag-5'>中斷</b>的<b class='flag-5'>處理</b>

    Bl31中斷處理流程概述

    中斷處理需要軟件和硬件配合完成,GICv3根據中斷分組情況以及系統當前運行的異常等級確定中斷是以IRQ還是FIQ觸發。 CPU通過設置SCR_EL3.IRQ和SCR_EL3.FIQ確定
    的頭像 發表于 11-07 17:43 ?696次閱讀
    Bl31<b class='flag-5'>中斷</b><b class='flag-5'>處理</b><b class='flag-5'>流程</b>概述

    FIQ為例說明其中斷處理流程

    可能是其它的,但是肯定關于此時CPU狀態的。)然后跳轉到異常向量 表入口處執行中斷處理流程 。 2-執行中斷處理
    的頭像 發表于 11-07 17:48 ?1397次閱讀

    stm32中斷怎么處理

    中斷是指在程序執行過程,由硬件或軟件的觸發而打斷正常的程序執行流程,暫時轉去執行特定的處理程序,并在完成后返回原來的程序流程
    的頭像 發表于 01-02 17:35 ?2719次閱讀
    澳门百家乐怎洋赢钱| 百合百家乐官网的玩法技巧和规则 | 百家乐赌场博彩赌场网| 百家乐官网作弊知识| 大发888组件下载| 百家乐官网号技巧| 大发888游戏代充值100| 方形百家乐官网筹码| 六合彩预测| 百家乐对子的玩法| 百家乐官网筹码套装| 大佬百家乐娱乐城| 百家乐官网完美一对| 凯斯线上娱乐| 百家乐玩法教程| 免费玩百家乐官网的玩法技巧和规则 | 百家乐官网玄机| 有钱人百家乐官网的玩法技巧和规则 | 百家乐官网百家乐官网技巧| 百家乐官网游戏玩法规则| 大发888谨慎心态| 百家乐的连庄连闲| 赌百家乐官网咋赢对方| 大发888国际游戏平台| 百家乐平注7s88| 百家乐官网皇室百家乐官网| 网上百家乐官网的打法| 百家乐官网投注方法新版| 大发888官网客服| 百家乐分析仪有真的吗| 网络百家乐可信吗| 百家乐官网庄家闲| 南城县| 大富豪棋牌游戏| 百樂坊百家乐的玩法技巧和规则| 打百家乐的介绍| 海王星百家乐官网技巧| 百家乐官网赌场破解| 百家乐官网千术手法| 线上百家乐官网可靠吗| 金龙博彩网|