異常,就是可以打斷cpu正常執行流程的一些事情,比如外部中斷、未定義指令、試圖修改唯讀的資料、執行swi指令(software interrupt instruction ,軟體中斷指令)等。當這些事情發生時,cpu暫停當前的程式,先處理異常事件,然後再繼續執行被中斷的程式。作業系統中經常通過異常來完成一些特定的功能。其中的中斷也占有很大的一部分。例如下面的這幾種情況:
在原先的核心版本中,核心在start_kernel函式(原始碼在init/main.c中)中呼叫trap_init、init_irq兩個函式來設定異常和處理函式。在linux2.6.32.2的核心版本中(也許在之前的版本就有變化),trap_init函式的內容發生了變化,在trap.c中,
void __init trap_init(
void
)
在這個檔案中還有乙個函式,
void __init early_trap_init(
void
)
這個函式才是真正要用到的,在init/mian.c中可以找到,呼叫了trap_init(),而early_trap_init()函式在setup_arch(&command_line)函式中呼叫。在
linux
/arch
/arm
/kernel
/setup.c
698void __init setup_arch(
char
**cmdline_p)
699
這樣我們就明白了trap_init()函式的具體呼叫過程了。下面我們具體來看一下這個trap_init()函式,確切的說是earl_trap_init()函式。
earl_tarp_init函式(**在arch/arm/kernel/traps.c中)被用來設定各種異常的處理向量,包括中斷向量。所謂「向量」,就是一些被安放在固定位置的**,當發生異常時,cpu會自動執行這些固定位置上的指令。arm架構的cpu的異常向量基址可以是0x00000000,也可以是0xffff0000,linux核心使用後者。
earl_trap_init函式將異常向量複製到0xffff0000處,我們可以在該函式中看到下面的兩行**。
memcpy((
void
*)vectors, __vectors_start, __vectors_end- __vectors_start)
;memcpy((
void
*)vectors + 0x200, __stubs_start, __stubs_end- __stubs_start)
;
vectors等於0xffff0000。位址__vectors_start ~ __vectors_end之間的**就是異常向量,在arch/arm/kernel/entry-armv.s中定義,它們複製到位址0xffff0000處。異常向量的**很簡單,它們只是一些跳轉指令。發生異常時,cpu自動執行這些指令,跳轉去執行更複雜的**,比如儲存被中斷程式的執行環境,呼叫異常處理函式,恢復被中斷程式的執行環境並重新執行。這些「更複雜的**」在位址__stubs_start ~__stubs_end之間,它們在arch/arm/kernel/entry-armv.s中定義。將它們複製到位址0xffff0000+0x200處。
異常向量、異常向量跳去執行的**都是使用彙編寫的,它們在arch/arm/kernel/entry-armv.s中。異常向量的**如下,其中的「stubs_offset」用來重新定位跳轉的位置(向量被複製到位址0xffff0000
處,跳轉的目的**被複製到位址0xffff0000+0x200處)。
.
equ stubs_offset, __vectors_start+ 0x200 - __stubs_start
.globl __vectors_start
__vectors_start:
arm( swi sys_error0 ) //復位是,cpu將執行這條指令
thumb( svc #0 )
thumb(
nop)
w(b) vector_und+ stubs_offset//未定義異常時,cpu將執行這條指令
w(ldr) pc,
.lcvswi + stubs_offset//swi異常
w(b) vector_pabt+ stubs_offset//指令預取中止
w(b) vector_dabt+ stubs_offset//資料訪問中止
w(b) vector_addrexcptn+ stubs_offset//沒有用到
w(b) vector_irq+ stubs_offset//irq異常
w(b) vector_fiq+ stubs_offset// fiq 異常
.globl __vectors_end
__vectors_end:
其中,vector_und、vector_pabt等表示要跳轉去執行的**。以vector_und為例,它仍在arch/arm/kernel/entry-armv.s中,通過vector_stub巨集來定義,
vector_stub und, und_mode
.long __und_usr @ 0 (usr_26 / usr_32) 在使用者模式執行了未定
義指令.long __und_invalid @ 1 (fiq_26 / fiq_32)在fiq模式執行了未定義指令
.long __und_invalid @ 2 (irq_26 / irq_32)在irq模式下執行了未定義指令
.long __und_svc @ 3 (svc_26 / svc_32)在管理模式下執行了未定義指令
.long __und_invalid @ 4
.long __und_invalid @ 5
.long __und_invalid @ 6
.long __und_invalid @ 7
.long __und_invalid @ 8
.long __und_invalid @ 9
.long __und_invalid @ a
.long __und_invalid @ b
.long __und_invalid @ c
.long __und_invalid @ d
.long __und_invalid @ e
.long __und_invalid @ f
vector_stub是乙個巨集,它根據後面的引數"und,und_mode"定義了以「vector_und」為標號的一段**。
後進行管理模式,最後根據被中斷的工作模式呼叫下面的某個跳轉分支。當發生異常時,cpu會根據異常
的型別進入某個工作模式,但是很快vector_stub巨集又會強制cpu進行管理模式,在管理模式下進行後續處
理,這種方法簡化了程式的設計,使得異常發生前的工作模式根毛是使用者模式,要麼是管理模式。
**表示在各個工作模式下執行未定義指令時,發生異常的處理分支。比如__und_usr表示在使用者模式下
執行未定義指令時,所發生的未定義異常將由它來處理;__und_svc表示在管理模式下執行未定義指令時,
所發生的未定義異常將由它來處理。在其他工作模式下不可能發生未定義指令異常,否則使用
「__und_invalid」來處理錯誤。arm架構cpu中使用4位資料來表示工作模式,所以共有16個跳轉分支,目
前只有7個工作模式。
不同的跳轉分支只是在它們的入口下(比如儲存被中斷程式的暫存器)稍有差別,後續的處理大體相同,都在呼叫相應的c函式,比如未定義指令異常發生時,最終會呼叫c函式do_undefinstr來進行處理。各種異常c處理函式可以分為5類,它們分布在不同的檔案中
(1)在arch/arm/kernel/traps.c中
未定義指令異常的c處理函式在這個檔案中定義,總入口函式為do_undefinstr
(2)在arch/arm/mm/fault.c中
與記憶體訪問相關的異常c處理函式在這個檔案中定義,比如資料訪問中止異常、指令預取中止異常。總入口函式為do_dataabort、do_prefetchabort。
(3)在arch/arm/mm/irq.c中
中斷處理函式的在這個檔案中定義,總入口函式為asm_do_irq,它呼叫其他檔案註冊的中斷處理函式
(4)在arch/arm/kernel/calls.s
在這個檔案中,swi異常的處理函式指標被組織成乙個**;swi指令機器碼的位[23:0]被用來作為索引。這樣,通過不同的swi index指令就可以呼叫不同的swi異常處理函式,它們被稱為系統呼叫,比如sys_open、sys_read等。
(5)沒有使用的異常
沒有使用fiq異常
trap_init函式搭建了各類異常的處理框架。當發生異常時,各種c處理函式會被呼叫。這些c函式還要進
一步細分異常發生的情況,分別呼叫更具體的處理函式。
2.init_irq函式分析
中斷也是一種異常,之所以把它單獨的列出來,是因為中斷的處理與具體的開發板密切相關,除一些必須
、共用的中斷(比如系統時鐘中斷、片內外設uart中斷)外,必須由驅動開發者提供處理函式。核心提煉
出中斷處理的共性,搭建乙個非常容易擴充的中斷處理體系。
init_irq函式(**在arch/arm/kernel/irq.c中)被用來初始化中斷和處理框架,設定各種中斷的預設
處理函式。當發生中斷時,中斷總入口函式asm_do_irq就可以呼叫這些函式進行下一步處理。
ClearQuest體系結構分析
關鍵字clearquest 體系結構分析 clearquest是按照標準的三層結構設計的,包括資料層 功能層 業務層 表示層。下面分別說明三層的構造和相互的關係。clearquest的根本在資料庫,所有的內容都儲存在資料庫中。在使用cq資料庫的時候,一定要記住一點 必須先建立空白的資料庫再進行cq的...
ARM學習之中斷體系結構
今天下午和晚上研究了一直在研究s3c2410中斷體系結構,雖然以前老師上課也接觸過,考試也考過,但仔細研究起來,還是有不少收穫的。現記述如下 1.什麼是中斷?答 中斷是cpu保證併發程式的一種機制。它使得cpu在執行程式的時候能夠響應異常的情況發生。其實,在cpu在執行的過程中,如何知道各類外設發生...
ARM學習之中斷體系結構
1.什麼是中斷?答 中斷是cpu保證併發程式的一種機制。它使得cpu在執行程式的時候能夠響應異常的情況發生。其實,在cpu在執行的過程中,如何知道各類外設發生了某些沒預期的事,比如說串列埠接受到了資料 usb介面中插入了裝置 按下了某個按鍵。有兩種方法,乙個是前面所說的中斷 另乙個就是輪詢方式。就是...