CPU的自我控制之(4)-異常的SPSR

——————————————————————異常第一步(xx紙尿褲) SPSR—————————————————————

 

好了,題外背景總算是磕磕絆絆的描述完了,終於可以說點本文主題相關的事兒。

 

當進入一次異常,首先是PSTATE,

進入異常將要用的PSTATE,即PE狀態會被放在異常等級對應的SPSR_ELx(估計會被複制到PSTATE裏),

x是EL等級,當然也就是會有多個SPSR_ELx寄存器,

準確的說是3個,可憐的EL0連個SPSR都混不上,不過。。。好像混上也沒啥用,EL0就是傻傻的執行,沒有異常,也不會處理。

很明顯,估計沒有人想讓我在這裏列出SPSR_ELx各個bit的定義,但是不說由不足以滿足我的裝逼屬性,

那就揀兩樣(這個詞是在仿照紅樓夢語氣,就是小丫鬟問主人吃啥點心的時候,"揀兩樣好吃的上吧~",~ 表示慵懶語氣)

可能有人關心的說吧。

挑出算術計算相關的N Z C V等狀態標誌不說。

挑出aarch32相關的 Q IT J不說。

挑出PAN。。。等等,PAN得說了。。。

 

PAN全名叫Privileged Access Never,置1後,效用是EL0通過虛擬內存地址能訪問的特權數據(原本是EL1/EL2特權數據),

都會在1階段地址轉換產生權限失敗,或者說產生1階段地址轉換失敗。

我很想簡要的說明PAN的設計目的,可惜知識量並不足以使我簡潔精確地指出,於是就照書唸了。

 

UAO也得說,UAO全名叫User Access Override,

就是在EL1或EL2(HCR_EL2.{E2H=1,TGE=1})下執行unprivileged Load/Store 指令(LDTR/STTR...)時,

這些無特權的Load/Store指令能訪問EL1/2特權等級下的內存空間了,

不然的話,它們是在EL0的吧;不過我並不是說進入異常後就會置位UAO,相反,它會被置0。

 

SS 是debuger相關的,不說。

 

IL比較牛逼,IL全名叫Illegal Execution state,

這個bit內容很豐富呀。。。好想跳過,可是這個位太特麼沒有跳過的理由了。。。

於是。。就一點一點說吧(爲啥是一點一點說,因爲,要說的東西分爲兩點!哈哈哈哈)。。。

首先要說的是,IL置1後,執行任何指令命令都會引起Illegal Execution state異常,

我認爲這在本質上是一個保護,主要是硬件自動動作過程中置的位(也可以人工置位)。

其清除是自動的。

然後我們就可以說一下,它是如何被置位、清零的。

有兩種情況IL位會被置位,一種是非法返回,一種是合法返回(這話。。簡直了):

對於非法返回產生IL位置位的情況包含三種,

一種是執行了ERET指令,

另外兩種是DEBUG相關的(跳過)。

ERET產生非法返回的情況有6中(。。我數了一下),

大概包含異常返回時,返到更高級異常去了;

返回某異常等級時,這個異常等級沒開;

EL3下往EL2返;

還有32位64位間出的一些錯。(相信不會有人要我把細節一條一條列出來的,畢竟大多數人英語還是比我好的)

對於合法返回產生IL位置位的情況,就是返回時複製到PSTATE的(恢復現場?)。

清零就比較簡單了,一執行異常IL就被清零了。

 

nRW 指示當前執行狀態aarch32或64

EL 指示當前異常等級,需要兩個bit

 

SP。。。

SP有點熟呀,SP不是棧指針寄存器麼,

這裏搞了一個bit。。。

乍一看這個位我還是有點懵逼的,

直到看見了SP_EL0、SP_EL1、SP_EL2、SP_EL3。。。 於是我就可以很自然的說這是個棧指針寄存器選擇位了,

需要注意的是,對於aarch32它是有不同的定義的,但是我並不十分關心,就不說了。

對於Aarch64,棧指針寄存器有四個,很明顯EL0/1/2/3都能勻上一個,

但要是那麼簡單的話我肯定不會在這兒絮叨了,

畢竟,要看到SP位就1bit,而EL等級有四個的重特大問題,

SP肯定不是編碼了四個寄存器的選擇,

其實它只指示了使用SP_EL0還是SP_ELx,

可憐的小EL0終於感受到了一點優待。

那EL1/2/3三個棧指針是怎麼選擇的?

當然。。。是異常來選的(驚喜不驚喜~意外不意外~哈哈哈哈)。

當異常發生,

棧指針叮的一下,就選到了對應的異常等級的棧指針SP_ELx(x>0,從EL的那兩bit中確定),

一般異常等級裏執行程序時,都會再將SP位清零,也就是繼續用SP_EL0,

可憐的小EL0的棧指針寄存器就這樣被佔用了。

於是爲什麼不直接用SP_ELx呢?

這麼敗家好像寄存器是免費的一樣,

很明顯ARM的大神兒們不會像我一樣傻。。。

想象這樣一種情況,

當ELx的異常發生了,

然後用上了棧指針寄存器SP_ELx,

然後就開始執行處理的指令流,

然後正在處理過程中,

又發生了一個同級的異常。。。

棧指針叮的一下,就選到了對應的異常等級的棧指針,

哎呦我去,這不就正用的這哥們兒呢麼,懵逼了,當真此刻是:懵逼樹上懵逼果,懵逼樹下你和我。

新發生的這個異常就如同樹葉一樣輕輕飄過。。。

對,這就是爲啥小EL0的SP棧指針寄存器單獨用了一個標誌位來表示。

其實有人可能會想,當SP_ELx正用着,還沒轉換過來的時候,來一下同級異常,叮一下。。。

(是不是想讓我寫點啥,哈哈哈哈,我正在懵逼樹下修煉,練成再來告訴你)

 

我們繼續走,讓那個傻子在懵逼樹下繼續修煉去吧。

最後還有個A I F位,分別爲SError、IRQ、FIQ屏蔽位,置位後對應中斷不能發生。

 

終於完了,

雖然廢話連篇,

但是從我讀別人的東西的體驗來看,凡是非常正式正規精確地語言描述的原理,我看起來都非常費勁,

並且這並不是在寫手冊或論文,所以我希望可以寫的不那麼無聊,

當然如果要形而上學到我寫文檔不行的話。。。咳咳,是的,我是寫文檔不行,我承認。

 

發佈了37 篇原創文章 · 獲贊 4 · 訪問量 3388
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章