《Cortex™-A系列編程者指南(V3.0)》第12章筆記


  在本章,我們看看ARM處理器如何響應異常。異常是任何需要掛起正常執行轉而運行與每個異常類型相關聯軟件(稱爲異常處理程序)的條件。


12.1 異常的類型


  如我們在第四章看到,A系列和R系列架構支持七種處理器模式,六種特權模式(稱爲快速中斷模式外部中斷模式管理模式中止模式未定義模式系統模式),一種非特權模式(用戶模式)。如果虛擬化擴展和安全擴展被實現,Hyp和Monitor模式可以被添加到列表。當前模式在軟件控制下處理一個異常時修改。


  然而,非特權的用戶模式只能通過產生一個異常來切換到另一個模式


  當一個異常發生,處理器保存當前狀態和返回地址,進入一個指定的模式,並且可能會禁止硬件中斷。執行從一個稱爲異常向量的固定的內存地址恢復。這自動地發生,不在編程者的直接控制之下。

  有下列異常類型存在:


<中斷>

  ARMv7-A處理器上有兩種類型的中斷,稱爲IRQ和FIQ。FIQ比IRQ優先級高。FIQ有些潛在地速度優勢,歸因於它在向量表中的位置和在FIQ模式中可獲取到更高數目的分組寄存器。這潛在地節省處理器在處理句柄中壓入寄存器到堆棧的時鐘週期。這類異常都典型地與處理器上的輸入引腳相關聯 --- 假設中斷沒有被禁止,外部硬件發出一箇中斷請求,在當前指令完成執行時,相應的異常類型被引發。


<中止>

  中止可以從指令獲取失敗(預取中止)數據訪問失敗(數據中止)中產生。它們可以來自外部存儲器系統在存儲器訪問時給予一個錯誤響應(表示可能指定的地址與系統中實際內存不對應)。或者,中止可能會由處理器的內存管理單元(MMU)產生。操作系統可以使用MMU中止來動態分配內存給應用

  一個指令當它被獲取時,可以在流水線中被標記爲中止。預取中止異常在處理器確實嘗試去執行它時。異常在指令實際執行前產生。如果流水線在中止指令到達流水線執行階段之前被清空,中止異常不會發生。數據中止異常在加載或存儲指令執行時發生,被認爲在數據讀或寫已經嘗試之後發生。

  如果中止作爲指令流執行或嘗試執行後的結果,它被描述爲同步的返回地址會提供引起異常指令的細節。異步中止不是由正在執行指令產生的,同時返回地址可能不總是提供引起中止的細節。

  ARMv7架構區分精確與不精確的異步中止。由MMU產生的中止總是同步的。架構不需要外部中止訪問的特定類型是同步的。

  例如,在一個特定的處理器實現上,它可能是這樣的,報道了一個頁表的步行外部中止被視爲精確的,但對於所有的處理器,這不是必須的。對於精確的異步中止,中止處理程序可以確定哪個指令引起了中止,沒有後續指令在那個指令之後被執行。這與不精確的異步中止作對比,它是外部存儲器系統在一個無法識別的訪問上報告一個錯誤時的結果。

  在這種情況下,中止處理函數不能確定那個指令引起了這個問題(引起中止產生的指令之後的指令可能已經執行)。例如,如果一個緩衝的寫從外部存儲器系統接收到一個錯誤響應,後續指令會在存儲之後已被執行。這意味着對於中止處理函數,修復問題並返回給應用程序是不可能的。所有它能做的就是殺死引起這個問題的應用。因此設備檢測需要特殊的處理,因爲在讀取不到的區域中,外部報告的中止會產生不精確的同步中止,甚至在這樣的內存被標記爲強排序的或設備。

  異步中止的檢測由CPSR的A位控制。如果A位置位,來自外部存儲器系統的異步中止會被處理器識別,中止異常不會立即產生。反而,處理器保持中止掛起直到A位被清除並在那時獲取一個異常。典型地內核代碼會確保(通過使用一個屏障指令)掛起的異步中止會確認正確的應用程序。如果一個線程由於一個不精確的中止已被殺死,它需要是正確的一個。


<復位>

  所有的處理器都有一個復位輸入,並且會在它們被複位後立即產生復位異常。這是最高優先級的異常,不能被屏蔽


<異常指令>

  在ARM處理器上,有兩類指令會引起異常。第一種是超級用戶調用(Supervisor Call ,SVC),以前被稱爲軟件中斷(Software Interrupt,SWI)典型地,這被用於提供一種機制用戶模式程序可以傳遞控制到特權的操作系統中的內核代碼,來執行操作系統級任務。第二種是未定義指令。架構定義了特定位模式與未定義操作碼對應。嘗試其中之一會引起一個未定義指令異常的產生。另外,對於沒有相應協處理器硬件執行的協處理器指令,也會引起這一陷阱產生。一些指令只能在特權模式被執行,在用戶模式執行這些指令會引起未定義指令異常。


  當一個異常發生時,代碼執行傳遞到一個被稱爲向量表的內存區域在表內,每一種異常類型只分配了一個字,通常包含一個到實際異常處理函數的分支指令。這個行爲與大多數其它的架構不同,其它的架構通常在異常表中存儲一個執行地址,而不是一條指令。


  你可以在ARM或Thumb代碼中編寫異常處理函數。CP15 SCTLR.TE位被用於指定異常處理函數是否會使用ARM或Thumb。當異常處理時,先前處理器的模式、狀態和寄存器必須保藏,從而使程序在異常處理之後可以恢復。


12.2 異常模式總結


  表12.1列出了中斷的狀態,在進入一個異常處理韓式時禁止了CPSR的I和F位。



12.2.1 異常優先級


  因爲一些異常類型會同時發生,處理器爲每個異常賦予一個固定的優先級。未定義指令預取中止超級用戶調用由於一個指令(有爲未定義模式和SVC模式位操作碼的特定位模式)的執行,因而不會同時發生。因此它們具有相同的優先級。


  注意:ARM架構並未定義何時異步異常發生。因此,異步異常的優先級相對於其它優先級,同步和異步,是實現定義的。


  異常的優先級實際異常處理代碼之間作區分是重要的,這發生在多個異常同時請求時。表12-1包含一列講述FIQ和IRQ如何自動被一些異常禁止。(所有的異常禁止IRQ,只有FIQ和復位禁止了FIQ。)這由處理器自動設置CPSR I(IRQ)和F(FIQ)位完成。


  因此,一個FIQ異常可以中斷一箇中止處理函數或IRQ異常。在數據中止和FIQ同時發生時,數據中止(具有更高優先級)首先進行。這允許處理器記錄數據中止的返回地址。但是因爲FIQ不能被數據中止禁止,我們然後立即接受FIQ的異常。在FIQ的最後,我們返回到數據中止處理函數。


  超過一個異常可能潛在地同時發生,但是一些組合是相互排斥的。一個預取中止標記一條指令是無效的,因此不可能同時發生作爲未定義指令或SVC(當然,SVC指令也不能是一條未定義指令)。這些指令不能引起任何內存訪問,因此不會引起數據中止。架構未定義異步異常,FIQ,IRQ,或異步中止何時必須接受,但事實上,接受一個IRQ或數據中止異常並未禁止FIQ異常,意味着FIQ異常會相對IRQ或異步中止處理優先被考慮。


12.3 進入一個異常處理程序


  當一個異常發生時,ARM處理器自動地做下列事情:
 > 在新模式的鏈接寄存器(LR)中,保存下一條指令的地址
 > 拷貝CPSR到SPSR,SPSR是分組寄存器中的一個,特定於每種(非用戶)操作模式。
 > 修改CPSR模式位到與異常類型相關聯的一個模式。其它的CPSR模式位的值設置由CP15系統控制寄存器決定。T位由CP15的TE位設置。J位被清除,E位(字節序)設置爲EE(Exception Endianness,異常字節序)位的值。這使得異常總是運行在ARM或Thumb狀態,小端或大端,相對於異常前的處理器狀態。
 > 強制PC指向異常向量表中相應的指令


  對於異常處理軟件,在異常入口立即保存寄存器值到堆棧總是必要的。(FIQ模式具有跟多的專用寄存器,因此一個簡單的處理函數可能能夠以不需要使用堆棧的形式被編寫。)


  一條特殊的彙編語言指令提供協助,以節省必要的寄存器,被稱爲SRS(Store Return State)。這條指令使得LR和SPSR進入任何模式的堆棧;使用哪個堆棧由指令操作數指定。


12.4 從異常處理程序離開


  爲了從異常處理程序離開,兩個獨立地操作必須原子地進行:
 > 從保存的SPSR恢復CPSR
 > 設置PC爲返回地址偏移


  在ARM架構中,這可以通過使用RFE指令任何以PC作爲目的寄存器的標誌設置數據處理操作(以S作爲後綴)實現,例如,SUBS PC,LR,#offset(注意S)。異常返回(Return From Exception, RFE)指令從當前模式棧內pop鏈接寄存器和SPSR


12.5 向量表


  表12-1中的第1列給出了與特定類型異常相關聯的向量表中的向量偏移。這是ARM處理器在異常拋出時跳轉的指令表。這些指令位於內存中的特定位置。正常的向量基地址是0x00000000,但是絕大多數ARM處理器允許向量基地址被移動到0xFFFF0000(或HIVECS)。所有的Cortex-A系列處理器允許這點,並且這是Linux內核選擇的默認地址。實現安全擴展的處理器可以額外地設置向量基地址,分別爲安全和非安全狀態,使用CP15向量基地址寄存器。


  你會注意到只有一個單一字的地址與每種異常類型相關聯。因此,每種異常只有一個單一的指令可以被放在向量表中(儘管,理論上,兩個16位的Thumb指令可以被使用)。FIQ是不同的。因此,向量表入口幾乎總是包含各種形式的分支之一。


B<label>

這執行了相對PC的分支。這對於調用在內存中足夠近的異常處理代碼是合適的,因爲分支指令中提供的24位域足夠大來編碼這個偏移。

LDR PC, [PC, #offset]

從一個相對異常指令地址定義的內存位置加載PC。這讓異常處理程序被放置在全32位內存空間中的任意地址(相對前面簡單的分支,花費一些額外的週期)。


12.6 返回指令


  鏈接寄存器(LR)在異常處理之後被用於存儲PC合適的返回地址。它的值需要如表12-1那樣被修改,依賴於異常發生的類型。《ARM架構參考手冊》(ARM Architecture Reference Manual)合適地定義了LR的值(這些定義來源的值,爲的是早期硬件實現的方便)。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章