1. 程式人生 > >深入淺出MIPS 四 MIPS的異常與中斷

深入淺出MIPS 四 MIPS的異常與中斷

原文網址:http://www.kernelchina.org/node/278

MIPS的異常和中斷,同其他體系結構,例如Intel的IA32架構下的中斷/呼叫門/陷阱機制類似,其目的主要有三:
一,提供一個合法地從使用者態到核心態的切換通道,使得程式能夠訪問如CP0、KSeg等平時被保護的資源;
二,處理一些非法的操作,如TLB Miss/Address Error等;
三,處理外部和內部的中斷。與IA32架構區別的是,所有的中斷均來自0號Exception。

《See MIPS Run》中,將MIPS的異常機制稱為“精確異常”。用通俗的語言解釋之,由於異常是執行指令時同步發生,因此,在造成異常的指令之前執行的指令,無疑均是有效的。然而,由於MIPS的高度流水體系結構,在引發異常的指令執行時,後面一條指令已經完成了讀取和譯碼的預備工作,萬事俱備,只待ALU部件空閒即執行之。當異常產生時,這些預備工作便被廢棄。CPU從異常中返回時,再重新做讀取和譯碼的工作。
因此,我們就可以保證,在異常發生時,異常指令之後所有的指令均不會被執行。這樣,就不需要在MIPS的異常處理例程(Exception Handler)中為延遲槽(Delay Slot)指令而煩惱了。

MIPS的異常型別,在前文中已經有所提及。為了方便讀者閱讀,先再次給出一個概覽,然後再詳解一些常見的異常。
MIPS異常型別總共有:
0: Interrupt,中斷;
1: TLB Modified,試圖修改TLB中對映為只讀的記憶體地址;
2: TLB Miss Load,試圖讀取一個沒有在TLB中對映到實體地址的虛擬地址;
3: TLB Miss Store,試圖向一個沒有在TLB中對映到實體地址的虛擬地址存入資料;
4: Address Error Load,試圖從一個非對齊的地址讀取資訊;
5: Address Error Store,試圖向一個非對齊的地址寫入資訊;
6: Instruction Bus Error,一般是指令Cache出錯;
7: Data Bus Error,一般是資料Cache出錯;
8: Syscall,由syscall指令產生。作業系統下,通用的由使用者態進入核心態的方法。可以類比IA32的“呼叫門”理解;
9: Break Point,由break指令產生。最常見的bp指令,是由編譯器產生的,在除法運算時插入一個break point指令,以達到在除0時丟擲錯誤資訊的目的。因此,如果在定位問題時發現了一個Break Point異常,且它的異常分程式碼為07,應當考慮是出現了除0的情形;
10: RI,保留指令。在CPU執行到一條沒有定義的指令時,進入此異常;
11: Co-processor Unavilible,協處理器不可用。這個異常是由於試圖對不存在的協處理器進行操作引起的。特別的,在沒有浮點協處理器的處理器上執行這條命令,會導致這個異常。隨之,作業系統會呼叫模擬浮點的lib庫,來實現軟體的浮點運算;
12: Overflow,算術溢位。只有帶符號的運算會引起這個異常;
13: Trap,這個異常來源於trap指令。和syscall指令類似地,trap指令也會引起一個異常,但trap指令可以附帶一些條件,這樣可以用於除錯程式用。
14: VCEI,指令快取記憶體中的虛地址一致性錯誤。(沒明白怎麼回事,還有待高手補充)
15: Float Point Exception,浮點異常;
16: Co-processor 2 Exception,協處理器2的異常;
17~22,留作將來的擴充套件;
23: Watch,記憶體斷點異常。當設定了WatchLo/WatchHi兩個暫存器時起作用。當load/store的虛擬地址和WatchLo/WatchHi中匹配時,會引發這樣一個異常;/* 這個地方經典著作《See MIPS Run》犯了一個錯誤,將虛擬地址寫成了實體地址 */
24~30,留作將來的擴充套件;

其中,Exception 0-5, 8-11, 13, 23這幾個異常型別較為常見。
Exception 0:Interrupt,外部中斷。它是唯一一個非同步發生的異常。之所以說中斷是非同步發生的,是因為相對於其他異常來說,從時序上看,中斷的發生是不可預料的,無法確定中斷的發生是在流水線的哪一個階段。MIPS的五級流水線設計如下:
IF, RD, ALU, MEM, WB。MIPS處理器的中斷控制部分有這樣的設計:在中斷髮生時,如果該指令已經完成了MEM階段的操作,則保證該指令執行完畢。反之,則丟棄流水線對這條指令的工作。除NMI外,所有的內部或外部硬體中斷(Hardware Interrupt)均共用這一個異常向量(Exception Vector)。前面提到的CP0中的Counter/Compare這一對計數暫存器,當Counter計數值和Compare門限值相等時,即觸發一個硬體中斷。

Exception 1:TLB Modified,記憶體修改異常。如果一塊記憶體在TLB對映時,其屬性設定為Read Only,那麼,在試圖修改這塊記憶體內容時,處理器就會進入這個異常。顯然,這個異常是在Memory階段發生的。但是,按“精確異常”的原則,在異常發生時,ALU階段的操作均無效,也就是說,向記憶體地址中的寫入操作,實際上是不會被真正執行的。這一判斷原則,也適用於後面的記憶體讀寫相關的異常,包括TLB Miss/Address Error/Watch等。
Exception 2/3:TLB Miss Load/Write,如果試圖訪問沒有在MMU的TLB中對映的記憶體地址,會觸發這個異常。在支援虛擬記憶體的作業系統中,這會觸發記憶體的頁面倒換,系統的Exception Handler會將所需要的記憶體頁從虛擬記憶體中調入實體記憶體,並更新相應的TLB表項。
Exception 4/5:Address Error Load/Write,如果試圖訪問一個非對齊的地址,例如lw/sw指令的地址非4位元組對齊,或lh/sh的地址非2位元組對齊,就會觸發這個異常。一般地,作業系統在Exception Handler中對這個異常的處理,是分開兩次讀取/寫入這個地址。雖然一般的作業系統核心都處理了這個異常,最後能夠完成期待的操作,但是由於會引起使用者態到核心態的切換,以及異常的退出,當這樣非對齊操作較多時會嚴重影響程式的執行效率。因此,編譯器在定義區域性和全域性變數時,都會自動考慮到對齊的情況,而程式設計師在設計資料結構時,則需要對對齊做特別的斟酌。
Exception 6/7:Instruction/Data Bus Error,一般地原因是Cache尚未初始化的時候訪問了Cached的記憶體空間所致。因此,要注意在系統上電後,Cache初始化之前,只訪問Uncached的地址空間,也就是0xA0000000-0xBFFFFFFF這一段。預設地,上電初始化的入口點0xBFC00000就位於這一段。(某些MIPS實現中可以通過外部硬線連線修改入口點地址,但為了不引發無法預料的問題,不要將入口點地址修改為Uncached段以外的地址)
Exception 8:Syscall,系統呼叫的正規入口,也就是在使用者模式下進入核心態的正規方式。我們可以類比x86下Linux的系統呼叫0x80來理解它。它是由一條專用指令syscall觸發的。
Exception 9:Break Point,絕對斷點指令。和syscall指令類似,它也是由專用指令break觸發的。它指示了系統的一些異常情況,程式設計人員可以在某些不應當出現的異常分支裡面加入這個指令,便於及早發現問題和除錯。我們可以用高階語言中的assert機制來類比理解它。最常見的Break異常的子型別為0x07,它是編譯器在編譯除法運算時自動加入的。如果除數為0則執行一條break 0x07指令。這樣,當出現被0除的情況時,系統就會丟擲一個異常,並執行Coredump,以便於程式設計師定位除0錯誤的根因。
Exception 10:RI,執行了沒有定義的指令,系統就會發生這個異常。
Exception 11,Co-Processor Unaviliable,試圖訪問的協處理器不存在。比如,在沒有實現CP2的處理器上執行對CP2的操作,就會觸發這個異常。
Exception 12,Overflow,算術溢位。會引起這個異常的指令,僅限於加減法中的帶符號運算,如add/addi這樣的指令。因此,一般地,編譯器總是將加減法運算編譯為addiu這樣的無符號指令。由於MIPS處理異常需要一定的開銷,這樣可以避免浪費。
Exception 13,Trap,條件斷點指令。它由trap系列指令引發。與Break指令不同的是,只有滿足斷點指令中的條件,才會觸發這個異常。我們可以類比x86下的int 3斷點異常來理解它。
Exception 14,VCEI,(不明白!誰知道是幹嘛使的?)
Exceotion 15,Float Point Exception,浮點協處理器1的異常。它由CP1自行定義,與CP1的具體實現相關。其實就是專門為CP1保留的異常入口。
Exception 16,協處理器2的異常,和前一個異常一樣,是和CP2的具體實現相關的。
Exception 23,Watch異常。前面講到Watch暫存器可以監控一段記憶體,當訪問/修改這段記憶體時,就會觸發這個異常。在異常處理例程中,通過異常棧可以反推出是什麼地方對這段記憶體進行了讀/寫操作。這個異常是用來定位記憶體意外寫壞問題的一柄利器。

異常發生的時候,系統會完成一個從使用者態到核心態的切換。我們前面提到,對系統某些資源的訪問(如CP0等協處理器,Kernel Segment記憶體),是必須在核心態進行的。因此,如果希望使系統從使用者態進入核心態,那麼,就必須產生一個異常。
MIPS的異常處理,通常來說,和其他體系結構的異常/中斷/陷阱處理,沒有太多的區別,總的來說分為三段:
1,儲存現場暫存器組(Register File)。在堆疊中開闢一段區域,將32個通用暫存器和CP0的相關暫存器,如Status,BadVaddr,Cause等,儲存在這段記憶體中。其中尤為重要的是EPC,EPC指向引發異常時的指令。
在這個步驟中,首先儲存的應該是通用暫存器組,隨後是epc/cause/status/badvaddr這幾個epc0中的暫存器。從cp0到記憶體的資料傳輸必須通過通用暫存器。一般地,程式設計時的約定是使用k0和k1這兩個暫存器暫存。如下例:(適用於32位MIPS模式)

sw zero, 0(sp)
sw at, 4(sp)
sw v0, 8(sp)
...
sw ra, 124(sp) /*先儲存通用暫存器組*/
mfc k0, epc
nop /* mfc太慢,要在延遲槽中加一個nop */
sw k0, 128(sp)
mfc k0, cause
nop
sw k0, 132(sp)
...

2,異常處理部分。以Address Error異常為例,當異常發生時,根據儲存的BadVaddr,呼叫兩次非對齊載入/儲存指令,對記憶體地址進行資料的讀寫操作。
3,返回。將儲存在堆疊中的暫存器組內容恢復。
從異常狀態返回的這個動作,是由硬體完成的。它必須同時完成三個操作:
1,將SR暫存器恢復;2,返回到EPC暫存器所指向的地址繼續執行;3,恢復到使用者態。如《See MIPS Run》提到的,如果這三個過程沒有能夠“原子地”執行完畢,那麼將會導致一個安全漏洞,使用者有可能在某種情況下僭越CPU核心態設定的壁壘,從而非法獲得管理員許可權。
在MIPS I和MIPS II處理器中,使用rfe這條指令,來進行“從異常中恢復”,也就是恢復SR暫存器,並且將系統從核心態恢復到使用者態。但這條指令並沒有將執行的指令地址返回到異常發生的指令處。這項工作應當由在此之前的一條JR指令來執行。這樣,從異常中返回的相關彙編程式碼應當為:
mfc k0, epc
jr k0
rfe /* 在上一條jr指令的延遲槽中執行,這樣可以保證原子性 */

在MIPS III及以後的處理器中,從異常中返回不再需要這樣的繁文縟節,只需要一條eret指令便萬事俱備了。


相關推薦

深入淺出MIPS MIPS異常中斷

原文網址:http://www.kernelchina.org/node/278 MIPS的異常和中斷,同其他體系結構,例如Intel的IA32架構下的中斷/呼叫門/陷阱機制類似,其目的主要有三: 一,提供一個合法地從使用者態到核心態的切換通道,使得程式能夠訪問如CP0、K

中斷詳解() ——異常異常處理

ENTRY(divide_error) RING0_INT_FRAME pushl $0 # no error code CFI_ADJUST_CFA_OFFSET 4 pushl $do_divide_error CFI_ADJUST_CFA_O

mips下的異常中斷

什麼是異常 在mips中,中斷、陷阱、系統呼叫和任何可以中斷程式正常執行流的情況都稱異常 1. 外部事件  ——中斷 2. 記憶體翻譯異常 3. 其他不太常見的核心修改的程式條件 4. 程式或硬體探測到的錯誤 5. 資料完整性錯誤 6. 系統呼叫和陷入 精確異常 在執行流程

ARM學習筆記——異常中斷——指令ldr及.word偽指令用法

在ARM彙編指令中,ldr是一條常用的記憶體訪問指令,如: ldr r1, [r2] //將地址為r2的記憶體單元位資料讀取到r1中 它也可以作為大範圍的地址讀取偽指令,如: ldr r1, =label //r1=label的地址 label:

ARM異常中斷

http://blog.chinaunix.net/uid-28458801-id-3780127.html先mark,有的地發還沒有完全消化。總結一下中斷配置步驟:中斷涉及:中斷源 中斷控制器  ARM核中斷相關內容1.中斷源配置:    (1)禁止中斷     (2)清除

[嵌入式]異常中斷(下)

異常與中斷 6.5  S5PV210的中斷程式設計 中斷跳轉流程 ARM處理器響應中斷的時候,總是從固定的中斷異常向量取地址開始的,而在高階語言環境下開發中斷服務程式時,無法控制從固定地址處開始至中

[嵌入式]異常中斷(上)

異常與中斷 6.1  概述     嵌入式系統中,微處理器控制I/O埠或部件的資料傳送方式有2種:程式查詢方式和中斷方式。程式查詢方式是由微處理器週期性地執行一段查詢程式來讀取I/O埠或部件中狀態暫存

STM32F10xxx_異常中斷

STM32F10xxx_異常與中斷 [TOC] 更新記錄 version status description date author V1.0 C Create Document 201

學習筆記——ARM Cortex-M0 異常中斷

異常型別及編號 Cortex-M0的每個異常源都有一個單獨的編號: 1~15內部系統異常:Reset(1), NMI(2), H/W Error(3), SVC(11), PndSV(14), S

Thrift第課 連接中斷異常處理

while循環 copy app cal 客戶端 pan all per 機制 場景 Thrift框架采用了異常處理機制,當客戶端異常斷開連接,服務端這個時候嘗試發送數據給客戶端,Thrift庫會拋出異常,導致進程中斷。這種情況是非常正常的,服務器端應該捕獲異常的發生,但是

Linux 網路協議棧之核心鎖()—— 程序上下文中斷上下文的理解

一.什麼是核心態和使用者態 核心態:在核心空間執行,通常是驅動程式,中斷相關程式,核心排程程式,記憶體管理及其操作程式。 使用者態:使用者程式執行空間。 二.什麼是程序上下文與中斷上下文 1.程序上下文: (1)程序上文:其是指程序由使用者態切換到核心態是需

深入淺出MIPSMIPS的記憶體對映 .

二 MIPS的記憶體對映 在32位MIPS體系結構下,最多可定址4GB地址空間。這4GB空間的分配是怎樣的呢?讓我們看下面這張圖: +----------------------------------------------+ | | 0xFFFFFFFF | |

X86中斷/異常APIC

異常(exception)是由軟體或硬體產生的,分為**同步異常**和**非同步異常**。**同步異常**即CPU執行指令期間同步產生的異常,比如常見的除零錯誤、訪問不在RAM中的記憶體 、MMU 發現當前虛擬地址沒有對應的實體地址,於是觸發一個異常,系統呼叫等。**非同步異常**即平時所說的**中斷**(i

數據庫類型空間效率探索()-tinyintenumset

數據 ngs truncate 類型 column 效率 select name type mysql> select count(*) from userinfo;+----------+| count(*) |+----------+| 115597 |+--

深入淺出JMS()--Spring和ActiveMQ整合的完整實例

訂閱 實例 schema -i 同步和異步 生產 技術分享 .com factor 第一篇博文深入淺出JMS(一)–JMS基本概念,我們介紹了JMS的兩種消息模型:點對點和發布訂閱模型,以及消息被消費的兩個方式:同步和異步,JMS編程模型的對象,最後說了JMS的優點。 第二

用戶空間內核空間,進程上下文中斷上下文[總結]【轉】

存儲器 com ont article 模式 tab 用戶代碼 ssi 而在 轉自:http://blog.csdn.net/lizuobin2/article/details/51791863 本文轉載自:http://www.cnblogs.com/Anker/p/3

MongoDB初探系列之:MongoDBJava共舞

ever 文件 basic query find man mongodb next() 入學 因為版本號不同,可能API也有所不同。本次學習用的是3.0版本號。 1、使用的mongodb的jdbc驅動版本號為:mongo-java-driver-3.0.0.jar

最近遇到的異常錯誤總結

reference dstat 異常 總結 ria num 空指針 格式化 first 異常 NumberFormatException 數字格式化異常 ArithmeticException 算術異常 ArrayIndexOutOfBoundsException 數組

菜鳥調錯()——SpringDWR集成,配置文件報錯

microsoft his www data editors bing ces myeclipse java 背景簡單介紹:該項目是市信用辦的一個系統,之前好像是一個石家莊的公司負責的。我屬於是半路接手。拿到源代碼後。依據他們給的簡(shao)單(de)明(ke)了(l

[js高手之路]深入淺出webpack系列1-安裝基本打包用法和命令參數

查看 2-2 gre colors 令行 一起 切換 json round webpack,我想大家應該都知道或者聽過,Webpack是前端一個工具,可以讓各個模塊進行加載,預處理,再進行打包。現代的前端開發很多環境都依賴webpack構建,比如vue官方就推薦使用webp