——————————————————————異常第一步(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屏蔽位,置位後對應中斷不能發生。
終於完了,
雖然廢話連篇,
但是從我讀別人的東西的體驗來看,凡是非常正式正規精確地語言描述的原理,我看起來都非常費勁,
並且這並不是在寫手冊或論文,所以我希望可以寫的不那麼無聊,
當然如果要形而上學到我寫文檔不行的話。。。咳咳,是的,我是寫文檔不行,我承認。