ARMLinux中斷源碼分析2中斷處理流程_第1頁
ARMLinux中斷源碼分析2中斷處理流程_第2頁
ARMLinux中斷源碼分析2中斷處理流程_第3頁
ARMLinux中斷源碼分析2中斷處理流程_第4頁
ARMLinux中斷源碼分析2中斷處理流程_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

/""中斷源碼分析(2)——中斷處理流程支持7類異常中斷,所以中斷向量表設(shè)8個條目,每個條目4字節(jié),共32字節(jié)。

異常名稱中斷向量異常中斷模式優(yōu)先級復(fù)位0x0特權(quán)模式1未定義的指令0x4未定義指令中止模式6軟件中斷0x8特權(quán)模式6指令預(yù)取中止0x0c中止模式5數(shù)據(jù)訪問中止0x10中止模式2保留0x14

外部中斷請求0x18模式4快速中斷請求0x1c模式3

回顧第一節(jié)所講的內(nèi)容,當(dāng)一個異?;蛑袛喟l(fā)生時,處理器會將設(shè)置為特定地址,從而跳轉(zhuǎn)到已經(jīng)初始化好的異常向量表。因此,要理清中斷處理流程,先從異常向量表開始。對于而言,異常向量表和異常處理程序都存在匯編文件中。異常向量表點(diǎn)擊(此處)折疊或打開

:

0

b

+

,

+

b

+

b

+

b

+

b

+

@中斷入口,

b

+

:為中斷的入口點(diǎn),此處之所以要加上,是為了實(shí)現(xiàn)位置無關(guān)編程。首先分析一下(宏)是如何計算的:

,+0x200-在第3節(jié)中已經(jīng)提到,內(nèi)核啟動時會將異常向量表拷貝到00000,將異常向量處理程序的拷貝到00200。圖5-1描述了異常向量表和異常處理程序搬移前后的內(nèi)存布局。圖5-1

異常向量表和異常處理程序搬移前后對比當(dāng)匯編器看到B指令后會把要跳轉(zhuǎn)的標(biāo)簽轉(zhuǎn)化為相對于當(dāng)前的偏移量(±32M)寫入指令碼。由于內(nèi)核啟動時中斷向量表和都發(fā)生了代碼搬移,所以如果中斷向量表中仍然寫成b,那么實(shí)際執(zhí)行的時候就無法跳轉(zhuǎn)到搬移后的處,因為指令碼里寫的是原來的偏移量,所以需要把指令碼中的偏移量寫成搬移后的。設(shè)搬移后的偏移量為,如圖5-1所示,=L12

=[0x200-(-)]+(-)

=[0x200-(-)]+(-)

=0x200-++-

=+(+0x200-)-令=+0x200-則=+-,所以中斷入口點(diǎn)為“b

+”,其中減去是由匯編器在編譯時完成的。處理函數(shù)在分析處理函數(shù)之前,先了解一下當(dāng)一個異常或中斷導(dǎo)致處理器模式改變時,處理器內(nèi)核的處理流程如下圖所示:

中斷剛發(fā)生時,處理器處于模式。在和之間找到處理函數(shù)的定義,,4,其中是一個宏(在中定義),為了分析更直觀,我們將宏展開如下:

/*

*

*/

:

4

,

,

#4

@在中斷發(fā)生時,指向最后執(zhí)行的指令地址加上8。只有在當(dāng)前指令執(zhí)行完畢后,才進(jìn)入中斷處理,所以返回地址應(yīng)指向下一條指令,即(4)處。

@

@r0,

<>

()

<>

@

()

@

,

{r0,

}

@保存r0,

到模式下的棧中

,

,

[,

#8]

@保存到模式下的棧中

@

@

32.

.

@

r0,

r0,

r0,

#(

^)

@設(shè)置成模式,但未切換

,

r0@保存到中

@

@

@

,

,

#0x0f存儲著上一個處理器模式的值,

=

&0x0f取出用于判斷發(fā)生中斷前是用戶態(tài)還是核心態(tài)的信息,該值用于下面跳轉(zhuǎn)表的索引。

r0,

@將模式下的保存到r0,作為參數(shù)傳遞給即將調(diào)用的或

,

[,

,

#2]

指向當(dāng)前執(zhí)行指令地址加8,即跳轉(zhuǎn)表的基址。作為索引,由于是4字節(jié)對齊,所以

=

<<

2.

,

@

@當(dāng)指令后加“s”且目標(biāo)寄存器為時,當(dāng)前模式下的會被復(fù)制到,從而完成模式切換(從模式切換到模式)并且跳轉(zhuǎn)到指向的指令繼續(xù)執(zhí)行()

@0

(26/32)

@1

(26/32)

@2

(26/32)

@3

(26/32)

@4

@5

@6

@7

@8

@9

@a

@b

@c

@d

@e

@f如果發(fā)生中斷前處于用戶態(tài)則進(jìn)入,其定義如下():

5

:

@保存中斷上下文,稍后分析

@獲取當(dāng)前進(jìn)程的進(jìn)程描述符中的成員變量的地址,并將該地址保存到寄存器(r9)(在中定義)@如果定義了搶占,增加搶占數(shù)值

r8,

[,

]

@獲取計數(shù)器值

r7,

r8,

#1

@加1,標(biāo)識禁止搶占

r7,

[,

]

@將加1后的結(jié)果寫入進(jìn)程內(nèi)核棧的變量中

@調(diào)用中斷處理程序,稍后分析

r0,

[,

]

@獲取計數(shù)器值

r8,

[,

]

@將恢復(fù)到中斷前的值

r0,

r7@比較中斷前后是否相等

r0,

[r0,

0]

@如果不等,則產(chǎn)生異常(向地址0寫入數(shù)據(jù))?

,

#08=0

b

@中斷處理完成,恢復(fù)中斷上下文并返回中斷產(chǎn)生的位置,稍后分析

(

)()宏定義(保護(hù)上下文到棧)上面代碼中的是一個宏定義,主要用于保護(hù)上下文到棧中:

(

)

(

)

@

,

,

中,堆棧被定義為遞減式滿堆棧,所以首先讓向下移動(結(jié)構(gòu)體),準(zhǔn)備向棧中存放數(shù)據(jù)。此處的是模式下的棧指針。

,

{r1

-

r12}

r0,

{r1

-

r3}

r0,

,

@

r4,

1

@

""

""

""

""

r1,

[]

@

""

r0

@

@

@

:

@

@r2

-

<>,

@r3

-

<>

@r4

-

0

(

)

@

@,

@

r0,

{r2

-

r4}

r0,

{,

}^@將模式下的和保存到模式的棧中

@

@

@

r0

@

@

@

上面的這段代碼主要是在填充結(jié)構(gòu)體,在中定義:

{

[18];};

[16]

[15]

[14]

[13]

[12]

[11]10

[10]9

[9]8

[8]7

[7]6

[6]5

[5]4

[4]3

[3]2

[2]1

[1]0

[0]0

[17]宏填充結(jié)構(gòu)體的過程如圖5-2所示,先將r1~r12保存到1~(綠色部分),然后將產(chǎn)生中斷時的r0寄存器內(nèi)容保存到0(藍(lán)色部分),接下來將產(chǎn)生中斷時的下一條指令地址、和r4保存到、和0(紅色部分),最后將用戶模式下的和保存到

中。圖5-2宏填充結(jié)構(gòu)體如果發(fā)生中斷前處于核心態(tài)則進(jìn)入,其定義如下():

5

:

@保存中斷上下文

r8,

[,

]

@獲取計數(shù)器值

r7,

r8,

#1

@加1,標(biāo)識禁止搶占

r7,

[,

]

@將加1后的結(jié)果寫入進(jìn)程內(nèi)核棧的變量中

@調(diào)用中斷處理程序,稍后分析

r8,

[,

]

@恢復(fù)中斷前的計數(shù)器

r0,

[,

]

@獲取

r8,

#0

@判斷是否等于0

r0,

#0

@如果不等于0,r0=0

r0,

@將r0與做“與操作”

@如果不等于0,說明發(fā)生內(nèi)核搶占,需要重新調(diào)度。

r0,

[,

]

@

,

r0

r0,

r4

@恢復(fù)中斷上下文,稍后分析。

(

)()宏定義(保護(hù)中斷上下文到棧)其中是一個宏定義,主要用于保護(hù)中斷上下文到棧中。主要是在當(dāng)前堆棧上分配一個結(jié)構(gòu),把r015以及等保存到這個結(jié)構(gòu)中,在進(jìn)入時,指向底端:

,

0

(

)

({r0

-

}

)

,

,

#(

+

\)

(

,

#4

)

(

,

,

#4

)

,

{r1

-

r12}

r0,

{r1

-

r3}

r5,

,

@

r4,

1

@

""

""

""

""

r0,

,

#(

+

\)

(

r0,

r0,

#4

)

r1,

[]

@

""

r0

@

r1,

@

@

:

@

@r0

-

@r1

-

@r2

-

<>,

@r3

-

<>

@r4

-

0

(

)

@

r5,

{r0

-

r4}

宏填充結(jié)構(gòu)體的過程如圖5-2所示,先將r1~r12保存到1~(綠色部分),然后將產(chǎn)生中斷時的r0寄存器內(nèi)容保存到0(藍(lán)色部分),由于是在模式下產(chǎn)生的中斷,所以最后將、、、和r4保存到、、、和0(紅色部分)。圖5-3宏填充結(jié)構(gòu)體上述的中斷上下文保存過程共涉及了3種棧指針,分別是:用戶空間棧指針,內(nèi)核空間棧指針和模式下的棧棧指針。指向在函數(shù)中創(chuàng)建的用戶空間棧。指向在函數(shù)中創(chuàng)建的內(nèi)核空間棧。在函數(shù)中被賦值,指向全局變量[0]。附錄1,體系下結(jié)構(gòu)

{

[18];

};

[0]-[17]分別對應(yīng),r0-r15,,0

附錄1,中斷時堆棧的變化

,中斷返回地址,修正后的

r0

<-進(jìn)入之前,的值,也是r0的值

<-進(jìn)入后,的值(中斷處理程序)保存中斷上下文后則進(jìn)入中斷處理程序——,定義在文件中:

r5,

1:

r0,

r6,

r5,

@獲取中斷號,存到r0中,稍后分析

r1,

@如果中斷號不等于0,將r1,即結(jié)構(gòu)體首地址

@

@r0

=

,

r1

=

*

@

,

1b@如果r0(中斷號)不等于0,(返回地址)等于標(biāo)號1處,即r0,

r6,

r5,

的那行,即循環(huán)處理所有的中斷。

@進(jìn)入中斷處理,稍后分析?!?/p>

用于判斷當(dāng)前發(fā)生的中斷號(與緊密相關(guān)),此處不再分析。如果獲取的中斷號不等于0,則將中斷號存入r0寄存器作為第一個參數(shù),結(jié)構(gòu)體地址存入r1寄存器作為第二個參數(shù),跳轉(zhuǎn)到c語言函數(shù)做進(jìn)一步處理。為了不讓大家在匯編語言和C語言之間來回切換,還是先把最后一點(diǎn)匯編語言代碼(中斷返回匯編代碼)分析了再去分析吧?;乜春蜆?biāo)號處的代碼,在完成了中斷處理函數(shù)后,要完成從中斷異常處理程序返回到中斷點(diǎn)的工作。如果中斷產(chǎn)生于用戶空間,則調(diào)用來恢復(fù)中斷現(xiàn)場并返回用戶空間繼續(xù)運(yùn)行:

():

@,此處不明白,應(yīng)該接受中斷號作為參數(shù),來禁止指定的號中斷線。但是此處調(diào)用之前并沒有將中斷號存入r0寄存器,這是為什么?

r1,

[,

]

@獲取>

r1,

@判斷是否有待處理的

@如果有,則進(jìn)入進(jìn)一步處理,主要是完成用戶進(jìn)程搶占相關(guān)處理。:

@如果沒有待處理,則準(zhǔn)備恢復(fù)中斷現(xiàn)場,返回用戶空間。

/*

*/

r1,

@調(diào)用體系結(jié)構(gòu)相關(guān)的代碼

=

0,

=

0@調(diào)用()以下是恢復(fù)中斷現(xiàn)場寄存器的宏,就是將發(fā)生中斷時保存在內(nèi)核空間堆棧上的寄存器還原,可以對照圖5-2所示的內(nèi)核空間堆棧保存的內(nèi)容來理解下面代碼:

,

=

0,

=

0

r1,

[,

#\

+

]

@從內(nèi)核棧中獲取發(fā)生中斷時的值

,

[,

#\

+

]!

@從內(nèi)核棧中獲取發(fā)生中斷時的下一條指令地址

,

r1

@將r1保存到

(32v6K)

@

(6)

r1,

r2,

[]

@

\

,

{r1

-

}^

@r1

-

,

{r0

-

}^@存在^,所以將內(nèi)核棧保存的內(nèi)容恢復(fù)到用戶空間的r0~寄存器

,

,

-

,

@將發(fā)生中斷時的下一條指令地址存入,從而返回中斷點(diǎn)繼續(xù)執(zhí)行,并且將發(fā)生中斷時的內(nèi)容恢復(fù)到寄存器中(開啟中斷)。

如果中斷產(chǎn)生于內(nèi)核空間,則調(diào)用來恢復(fù)中斷現(xiàn)場:

,

,

\

(32v6K)

@

,

{r0

-

}^

@r0

-

,

(6)

r0,

[]

r1,

r2,

[]

@

,

{r1

-

}^

@r1

-

,

,

{r0

-

}^

@返回內(nèi)核空間時,恢復(fù)中斷現(xiàn)場比較簡單,就是將r0以及恢復(fù)即可,同時中斷也被開啟。

函數(shù),分析完所有與中斷相關(guān)的匯編語言代碼后,下面開始分析C語言代碼:在文件中找到函數(shù)定義:(

,

*)

{

/*保存新的寄存器集合指針到全局變量,方便后續(xù)處理程序訪問寄存器集合。*/

*

=

();

();

/*

*

.

*

,

.

*/

((

>=

))

{判斷中斷號

(())

(

"\n",

);

();

}

{

();

調(diào)用中斷處理函數(shù)

}

/*

91

*/

();

();

();}是中斷處理的C入口函數(shù),主要負(fù)責(zé)調(diào)用注冊的中斷處理函數(shù),其流程如圖5-4所示:圖5-4流程1、

=

()其中,將指向寄存器結(jié)構(gòu)體的指針保存在一個全局的變量中,后續(xù)的程序可以通過該變量訪問寄存器結(jié)構(gòu)體。所以在進(jìn)入中斷處理前,先將全局變量中保存的舊指針保留下來,等到中斷處理結(jié)束后再將其恢復(fù)。2、負(fù)責(zé)更新一些統(tǒng)計量:<>

(){

=

();

();

(()

())

{

();

();

}

();}如果系統(tǒng)開啟動態(tài)時鐘特性且很長時間沒有產(chǎn)生時鐘中斷,則調(diào)用更新全局變量(關(guān)于動態(tài)時鐘特性,在后續(xù)的總結(jié)中再進(jìn)行分析)。宏()定義如下:()

\

{

\

();

\

();

\

();

\

}

(0)()使表示中斷處理程序嵌套層次的計數(shù)器加1。計數(shù)器保存在當(dāng)前進(jìn)程結(jié)構(gòu)的字段中:圖5-5結(jié)構(gòu)內(nèi)核將分成5部分:0~7與相關(guān),8~15用作軟中斷計數(shù)器,16~25用作硬中斷計數(shù)器,26用作不可屏蔽中斷計數(shù)器,28用作標(biāo)志。3、是體系結(jié)構(gòu)無關(guān)函數(shù),用來調(diào)用>,該函數(shù)指針在中斷初始化時指向了電流處理函數(shù)(或),針對不同的中斷觸發(fā)類型(邊沿觸發(fā)或電平觸發(fā))做相應(yīng)的處理。然后調(diào)用遍歷鏈表從而調(diào)用該中斷號對應(yīng)的一個或多個中斷處理程序>,而>就是通過初始化的。首先分析一下函數(shù):<>

(

,

*){

*;

;

(>);

/*訪問內(nèi)容之前先加自旋鎖*/

(,

);

/*屏蔽與號對應(yīng)的中斷線

*//*

在多處理器系統(tǒng)上,為了避免多同時處理同一中斷。*當(dāng)>包含標(biāo)志時,說明該中斷*正在另一個上處理,因此當(dāng)前可以直接放棄處理。*/

((>

&

))

;

>

~(

|

);

(,

);

/*

*如果沒有對該中斷注冊處理程序,即>為。

*

或者>設(shè)置為,表示該中斷是被禁止的。

*

以上兩種情況只要出現(xiàn)一種即可放棄處理。*/

=

>;

((

(>

&

)))

;

>

;

/*標(biāo)識中斷狀態(tài)為正在處理*/

(>);

/*釋放自旋鎖*/

/*調(diào)用由注冊的處理函數(shù),稍后分析。*/

=

(,

);

()

(,

,

);

(>);

/*訪問內(nèi)容前加自旋鎖*/

>

;

/*清除“正在處理”的標(biāo)識*//*如果>包含,*則將>設(shè)置為,使該中斷仍處于被屏蔽狀態(tài)。

*/

((>

&

))

>

;/*如果中斷處理函數(shù)中未對>設(shè)置為,*且>>不為空,則>>所指向的芯片相關(guān)函數(shù),*解除對該中斷的屏蔽。

*/

(!(>

&

)

>>)

>>();:

(>);

/*釋放自旋鎖*/}再來介紹一下函數(shù),相對于要復(fù)雜一點(diǎn):<>

(

,

*){

(>);

>

~(

|

);

/*

*

如果該中斷正在被其他處理,或者是該中斷已被禁止,

*

則不處理該中斷,但要將其標(biāo)識為狀態(tài)且屏蔽該中斷以便后續(xù)處理

*/

(((>

&

(

|

))

>))

{

>

(

|

);

(,

);

;

}

(,

);

/*

*/

(>>)

>>();

/*

標(biāo)識該中斷狀態(tài)為“正在處理”*/

>

;

{

*

=

>;

;

(())

{

>>();

;

}

/*

*

如果當(dāng)處理該中斷時有另一個中斷到達(dá),

*

那么當(dāng)時可能屏蔽了該中斷。

*

如果該中斷沒有被禁止,則解除對該中斷的屏蔽。

*/

(((>

&

(

|

|

))

(

|

)))

{

>>();

>

;

}

>

;

(>);

/*調(diào)用由注冊的處理函數(shù),稍后分析。*/

=

(,

);

()

(,

,

);

(>);

/*如果該中斷沒有被禁止,并且有其他中斷等待處理(),*則循環(huán)處理其他中斷。*/

}

((>

&

(

|

))

);

>

;:

(>);}不管是電平觸發(fā)還是邊沿觸發(fā),最終都會通過來調(diào)用注冊的中斷處理函數(shù)。<>

(

,

*){

,

=

;

=

0;/*如果注冊中斷時沒有設(shè)置標(biāo)志,則在此處開啟硬中斷!開啟后允許硬中斷嵌套。從2.6.36版本內(nèi)核開始,標(biāo)志被廢除,此處不再開啟硬中斷,以防止中斷嵌套可能造成棧溢出的潛在風(fēng)險。詳細(xì)信息參見:*/

(!(>

&

))

();

{

(,

);

/*調(diào)用由注冊的中斷處理函數(shù)*/

=

>(,

>);

(,

,

);

()

{

*進(jìn)行中斷線程化處理*/

/*

*

*

.

*/

=

;

((>))

{

(,

);

;

}

(((,

>)))

{

(,

>);

/*喚醒由注冊的中斷處理線程*/

(>);

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論