xinzha:
通常來說軟件人員并不關(guān)心流水線的細(xì)節(jié),尤其是上層軟件程序員,甚至驅(qū)動(dòng)工程師都不需要了解流水線,但是對(duì)于一個(gè)真正的系統(tǒng)底層工程師來說,了解流水線的一個(gè)比較重要的意義就是當(dāng)出現(xiàn)問題時(shí),能夠精確定位到產(chǎn)生問題的那條指令,從而精確跟蹤問題,還有就是異常處理程序執(zhí)行完成后根據(jù)LR寄存器的值來正確返回也需要對(duì)流水線的了解。不過有些情況下體制就不能保證精確定位,比如說有writebuffer的時(shí)候,你的寫指令即使會(huì)發(fā)生錯(cuò)誤(例如地址錯(cuò)誤、權(quán)限錯(cuò)誤、器件錯(cuò)誤等),也是在數(shù)個(gè)周期之后,當(dāng)寫指令真正出現(xiàn)在總線上時(shí)才會(huì)激起異常,其原因是因?yàn)樗俣绕ヅ鋯栴},寫數(shù)據(jù)需要通過writebuffer來完成,發(fā)生異常的時(shí)刻已經(jīng)離發(fā)出寫指令的時(shí)刻不匹配了。當(dāng)發(fā)生異常的時(shí)候,犯罪分子和發(fā)生異常時(shí)所在模式的pc的匹配關(guān)系如下:Dataabortpc-8,因?yàn)閐ataabort只有進(jìn)入執(zhí)行階段才能被發(fā)現(xiàn),這時(shí)第三條指令已經(jīng)被取指。IRQpc-8,IRQ發(fā)生時(shí)刻不可預(yù)知,在當(dāng)前指令執(zhí)行完之后響應(yīng),所以pc也是第三條的地址。FIQpc-8,原理同上。PrefetchAbortpc-4,這個(gè)最繞,是預(yù)取指時(shí)發(fā)生錯(cuò)誤造成的,但是如果這條指令不進(jìn)入執(zhí)行階段就不會(huì)造成異常,比如說前面一條是jmp。所以我猜測(cè)在它進(jìn)入執(zhí)行之前,kernel已經(jīng)知道出錯(cuò),pc不再更新,保持為它下一條指令的位置。SWI和UNDEF和上一條一樣,都是在譯碼階段kernel已經(jīng)知道會(huì)發(fā)生異常,不再更新pc,但是進(jìn)入執(zhí)行階段才會(huì)激起異常,所以異常地址也都是pc-4。今天來討論一下對(duì)齊問題,在ARM7,即armv4中,規(guī)定如果訪問int類型數(shù)據(jù)時(shí)給出的指針地址的低2位不為0的話,系統(tǒng)會(huì)自動(dòng)將低兩位的1抹平,即強(qiáng)制四字節(jié)對(duì)其,這樣的問題就是如果你的數(shù)據(jù)偏偏就是不對(duì)齊的,cpu拿到的數(shù)據(jù)就是不正確的,bug由此產(chǎn)生。在ARM9(我接觸的是arm926ejs)中,如果訪問int型數(shù)據(jù),低2位不為0,那么cpu直接掛住,一個(gè)dataabort。在ARM11之后的版本中支持了非對(duì)齊訪問,是在總線上拆分然后拼接來實(shí)現(xiàn)的,也就是說如果你訪問int時(shí)給出的地址不是4字節(jié)對(duì)齊,那么總線上會(huì)出現(xiàn)兩個(gè)int訪問,然后把數(shù)據(jù)拼接起來送給cpu,這些對(duì)于cpu是不可見的,但是會(huì)導(dǎo)致速度下降,總線占用率上升。此功能可以通過修改cp15中來關(guān)閉,實(shí)現(xiàn)跟以前版本一樣的對(duì)齊方式。需要說明的是這里的int是4字節(jié)而不是2字節(jié)。另外一點(diǎn)是對(duì)齊問題并不是專指四字節(jié)對(duì)齊,很多初學(xué)者或者有一定經(jīng)驗(yàn)的人都會(huì)犯這個(gè)錯(cuò)誤,認(rèn)為只有四字節(jié)對(duì)齊才會(huì)出問題。實(shí)際上對(duì)齊指的是數(shù)據(jù)邊界對(duì)齊,也就是說longlong數(shù)據(jù)要8字節(jié)對(duì)齊,int要4字節(jié)對(duì)齊,short要2字節(jié)對(duì)齊,byte自然是怎么對(duì)都齊了。