存糾錯(cuò)與UE排障:從“顯示2”到MBIST驗(yàn)證實(shí)戰(zhàn)解析)
寫這一段內(nèi)容時(shí)我心里其實(shí)先想到的是兩年前半夜處理一臺(tái)存儲(chǔ)節(jié)點(diǎn)告警的場(chǎng)景帶外管理頁(yè)面里那段Uncorrected ECC Error Count: 2以及第二塊DIMM槽位上那根看似全新、實(shí)際已經(jīng)悄悄壞掉的內(nèi)存條。也就是從那個(gè)顯示2開(kāi)始我把ECC相關(guān)的日志解析、寄存器和MBIST測(cè)試鏈路整個(gè)翻了一遍才慢慢把這個(gè)領(lǐng)域里容易被忽略的細(xì)節(jié)串成體系。這篇東西不是教科書是我把ECC從原理到排障、再到芯片驗(yàn)證側(cè)與MBIST交互踩過(guò)的所有坑一次性整理出來(lái)給同樣被這個(gè)2困擾過(guò)的運(yùn)維和驗(yàn)證工程師省點(diǎn)時(shí)間。1. 項(xiàng)目整體思路拆解ECC到底在解決什么問(wèn)題1.1 從顯示2說(shuō)起ECC不是玄學(xué)是一個(gè)現(xiàn)實(shí)交換打開(kāi)服務(wù)器日志最讓人心頭一緊的不是CECorrectable Error而是UEUncorrectable Error尤其當(dāng)帶外管理面板上赫然寫著uncorr. ecc 顯示2。很多人第一反應(yīng)是完了內(nèi)存要炸其實(shí)這個(gè)2代表的是在這臺(tái)機(jī)器運(yùn)行周期內(nèi)EEC引擎檢測(cè)到了兩次它自己也無(wú)法糾正的、發(fā)生在內(nèi)存讀路徑上的錯(cuò)誤。ECC的全稱是Error Correcting Code糾錯(cuò)碼。它和防錯(cuò)完全是兩回事。DRAM存儲(chǔ)單元本質(zhì)是一個(gè)電容加一個(gè)晶體管電容漏電導(dǎo)致bit翻轉(zhuǎn)是它的物理宿命。ECC能做的是當(dāng)數(shù)據(jù)從內(nèi)存讀出來(lái)時(shí)通過(guò)一組額外的校驗(yàn)位和數(shù)學(xué)運(yùn)算判斷這一拍讀出來(lái)的數(shù)據(jù)有沒(méi)有錯(cuò)以及如果只錯(cuò)了一個(gè)bit能不能反推出原來(lái)的值。因此ECC并不是阻止錯(cuò)誤發(fā)生而是在錯(cuò)誤發(fā)生的那一刻把它兜住避免錯(cuò)誤數(shù)據(jù)落入CPU的計(jì)算管線。有代價(jià)就有取舍。ECC需要額外的DRAM顆粒來(lái)存放校驗(yàn)位典型DDR4 ECC方案下72位物理位寬中只有64位是數(shù)據(jù)位剩下的8位全部用于校驗(yàn)。這意味著內(nèi)存控制器要處理更寬的內(nèi)部總線、更復(fù)雜的時(shí)序以及每一次讀寫都要多走一套編解碼電路。1.2 ECC的三大落地場(chǎng)景ECC其實(shí)不是內(nèi)存的專屬詞。從消費(fèi)級(jí)到企業(yè)級(jí)從CPU內(nèi)部緩存到SSD主控再到PCIe鏈路到處都有它的身影。梳理下來(lái)核心場(chǎng)景可以分成三類內(nèi)存ECC最經(jīng)典也最被人熟知。用于糾正DRAM顆粒內(nèi)部的隨機(jī)bit翻轉(zhuǎn)。根據(jù)能力不同分為單bit糾錯(cuò)SEC和單bit糾錯(cuò)加雙bit檢錯(cuò)SEC-DED這是服務(wù)器內(nèi)存的基本盤。存儲(chǔ)介質(zhì)ECCSSD里的NAND Flash、機(jī)械硬盤里的扇區(qū)數(shù)據(jù)都會(huì)用LDPC或BCH這類更有攻擊性的糾錯(cuò)碼。它們面對(duì)的錯(cuò)誤形態(tài)更復(fù)雜比如NAND的電荷泄漏、寫干擾引起的連續(xù)多位錯(cuò)誤。傳輸鏈路ECCPCIe、DDR總線上傳輸?shù)臄?shù)據(jù)也帶CRC或ECC類型的保護(hù)用來(lái)對(duì)抗信號(hào)完整性問(wèn)題導(dǎo)致的位錯(cuò)誤。這三個(gè)場(chǎng)景往往是聯(lián)動(dòng)出現(xiàn)的內(nèi)存ECC掛了報(bào)出來(lái)的錯(cuò)誤可能會(huì)被上層存儲(chǔ)的ECC再次兜住也可能直接流到CPU觸發(fā)Machine Check。理解這一點(diǎn)對(duì)后續(xù)排查那條uncorr. ecc 顯示2會(huì)很有幫助。1.3 誰(shuí)需要把這篇文章看完如果你是服務(wù)器運(yùn)維、存儲(chǔ)管理員或者正在做芯片級(jí)存儲(chǔ)控制器驗(yàn)證這篇文章能幫你徹底搞清楚三件事ECC是如何在底層工作的為什么顯示2了系統(tǒng)還沒(méi)癱以及當(dāng)MBIST測(cè)試遇上ECC邏輯時(shí)那些繞不開(kāi)的設(shè)計(jì)交互。尤其是最后一點(diǎn)很多做驗(yàn)證的同事容易忽略但它往往是芯片回片后最難查的bug之一。2. ECC糾錯(cuò)原理拆解從bit翻轉(zhuǎn)到糾錯(cuò)引擎2.1 DRAM單元為什么會(huì)翻轉(zhuǎn)DRAM的最小存儲(chǔ)單元是一個(gè)晶體管加一個(gè)電容電荷存不存在由電容上的電壓決定。邏輯1對(duì)應(yīng)高電壓邏輯0對(duì)應(yīng)低電壓。電容會(huì)漏電所以DRAM必須周期性刷新這就是它名字里Dynamic的由來(lái)。如果一次刷新間隔內(nèi)有高能粒子擊穿電容介質(zhì)或者鄰近單元讀寫在位線上耦合出足夠大的噪聲干擾單元里的電荷狀態(tài)就會(huì)改變這就是我們說(shuō)的bit翻轉(zhuǎn)bit flip。在芯片工藝還在90nm甚至更高的年代alpha粒子封裝材料中的微量放射性元素衰變產(chǎn)生是主要元兇。工藝到28nm以下后中子引發(fā)的單粒子效應(yīng)SEE比重開(kāi)始上升。這些微觀層面的物理過(guò)程無(wú)法徹底消除ECC的意義就在于與其祈禱粒子不砸中存儲(chǔ)單元不如設(shè)計(jì)一套機(jī)制讓砸中之后系統(tǒng)還能繼續(xù)正確運(yùn)行。2.2 SEC-DED的數(shù)學(xué)底牌ECC內(nèi)存最常用的方案是SEC-DEDSingle Error Correction, Double Error Detection也就是單bit糾錯(cuò)、雙bit檢錯(cuò)。這里有一個(gè)被很多人問(wèn)爛了的問(wèn)題64位數(shù)據(jù)為什么需要8位校驗(yàn)位這要用漢明碼的編碼原理來(lái)解釋。假設(shè)我們需要給64位數(shù)據(jù)附加r位校驗(yàn)位那么這r位校驗(yàn)位需要有足夠多的組合狀態(tài)來(lái)同時(shí)完成兩件事一是定位出哪一位出錯(cuò)如果沒(méi)錯(cuò)也作為一種狀態(tài)二是保證任意一個(gè)bit翻轉(zhuǎn)都能被圈出來(lái)修正。對(duì)于單bit糾錯(cuò)校驗(yàn)位需要滿足一個(gè)不等式2^r m r 1其中m是數(shù)據(jù)位寬r是校驗(yàn)位寬。m64時(shí)r6可以算出2^664而64617164不滿足大于等于71不夠r7時(shí)2^7128128647172滿足。所以理論上有7位校驗(yàn)位就夠了。但這是純漢明碼的SEC能力它無(wú)法可靠區(qū)分單個(gè)數(shù)據(jù)位翻轉(zhuǎn)和兩個(gè)數(shù)據(jù)位同時(shí)翻轉(zhuǎn)。為了做到雙bit檢錯(cuò)DED要在漢明碼的基礎(chǔ)上額外加上一位奇偶校驗(yàn)位覆蓋整體碼字的所有位這樣如果發(fā)生了雙bit翻轉(zhuǎn)糾正邏輯會(huì)因?yàn)樾r?yàn)方程矛盾而放棄糾錯(cuò)并上報(bào)一個(gè)不可糾正錯(cuò)誤UE。這就是為什么我們看到的內(nèi)存ECC物理位寬是64872位。還有一個(gè)算起來(lái)很直觀的對(duì)比如果只做奇偶校驗(yàn)parity1位錯(cuò)誤的檢測(cè)率是100%但沒(méi)有任何糾錯(cuò)能力一旦檢測(cè)到錯(cuò)誤只能panic重啟。ECC則把檢測(cè)到錯(cuò)誤和糾正錯(cuò)誤之間的鴻溝填上了一半。2.3 編解碼流程和延遲代價(jià)ECC編碼和解碼發(fā)生在內(nèi)存控制器的數(shù)據(jù)通路上。寫入路徑上控制器把64位數(shù)據(jù)送進(jìn)編碼器算出8位校驗(yàn)位連同數(shù)據(jù)一起寫入DRAM讀取路徑上控制器把72位數(shù)據(jù)數(shù)據(jù)校驗(yàn)一起讀回送進(jìn)解碼器。解碼器內(nèi)部會(huì)重新對(duì)64位數(shù)據(jù)做一次編碼得到新的8位校驗(yàn)位然后用新的校驗(yàn)位與存儲(chǔ)的8位校驗(yàn)位做XOR運(yùn)算得到一個(gè)8位綜合征syndrome。綜合征全0讀取過(guò)程沒(méi)有出錯(cuò)。綜合征非0說(shuō)明數(shù)據(jù)或校驗(yàn)位產(chǎn)生了變化。通過(guò)綜合征與碼字中每位的對(duì)應(yīng)關(guān)系可以定位出哪一位翻轉(zhuǎn)然后直接把它求反完成糾正。如果綜合征表明翻轉(zhuǎn)位置與奇偶校驗(yàn)方程沖突說(shuō)明至少兩個(gè)bit同時(shí)出錯(cuò)無(wú)法定位上報(bào)UE。這里需要補(bǔ)充一個(gè)容易被誤解的點(diǎn)SEC-DED能糾正的錯(cuò)誤前提是同一個(gè)碼字64位數(shù)據(jù)8位校驗(yàn)內(nèi)只發(fā)生一位翻轉(zhuǎn)。如果某個(gè)故障導(dǎo)致同一個(gè)碼字內(nèi)部有兩位翻轉(zhuǎn)ECC就只能報(bào)UE。這也是DDR4時(shí)代的Row Hammer攻擊高頻激活同一行的多個(gè)相鄰行導(dǎo)致鄰行存儲(chǔ)單元電荷泄漏讓安全界聞風(fēng)喪膽的原因——攻擊者可以刻意構(gòu)造雙bit翻轉(zhuǎn)讓ECC失效。延遲方面編解碼器雖然在內(nèi)存控制器內(nèi)部但每筆讀寫都要過(guò)一遍邏輯門DDR4時(shí)代實(shí)測(cè)下來(lái)對(duì)內(nèi)存帶寬的損耗在2%-3%左右延遲增加大約一到兩個(gè)時(shí)鐘周期。和系統(tǒng)因UE直接崩潰相比這個(gè)代價(jià)完全值得。3. 解密uncorr. ecc 顯示2日志、寄存器與應(yīng)急處理3.1 那條告警究竟代表什么如果你用的是x86平臺(tái)無(wú)論是Intel還是AMD內(nèi)存UE最終都會(huì)觸發(fā)Machine Check ArchitectureMCA機(jī)制。CPU內(nèi)部有專門的異常處理單元檢測(cè)到無(wú)法糾正的ECC錯(cuò)誤后會(huì)記錄一組錯(cuò)誤狀態(tài)到MSR寄存器Model Specific Register并可能觸發(fā)MCEMachine Check Exception。在Linux下這部分信息會(huì)通過(guò)mcelog或rasdaemon收集最終顯示在dmesg里。uncorr. ecc 顯示2字面上的意思在這臺(tái)機(jī)器歷史上內(nèi)存子系統(tǒng)上報(bào)的UE次數(shù)累計(jì)為2。別小看這個(gè)數(shù)字它并不代表系統(tǒng)已經(jīng)臨近崩潰而是代表在某兩次訪問(wèn)中ECC引擎遇到了它不能修正的錯(cuò)誤。這兩次錯(cuò)誤是否讓系統(tǒng)實(shí)際不可用取決于錯(cuò)誤發(fā)生在未被操作系統(tǒng)分配的物理頁(yè)還是已被應(yīng)用程序使用的頁(yè)錯(cuò)誤是否命中了CPU緩存未覆蓋的內(nèi)存行平臺(tái)固件是否將MCE配置為接管并終止該進(jìn)程還是直接panic。所以你會(huì)發(fā)現(xiàn)一個(gè)很有意思的現(xiàn)象有的機(jī)器ue_count顯示幾十次系統(tǒng)還好好跑著有的機(jī)器只顯示1次下一秒就panic了。這個(gè)差異在于錯(cuò)誤落點(diǎn)而不是錯(cuò)誤次數(shù)本身。3.2 Linux下怎么精確追蹤UE拿到顯示2之后第一件事不是拔內(nèi)存而是把日志的源頭搞清楚。主流手段有三個(gè)rasdaemon現(xiàn)代Linux發(fā)行版尤其RHEL/CentOS 8以上默認(rèn)用rasdaemon把MCA事件記入ras-mc-ctl。執(zhí)行ras-mc-ctl --summary可以快速看到ce_count和ue_count的匯總ras-mc-ctl --errors可以看到每次錯(cuò)誤的詳細(xì)信息包括Physical Address、DIMM槽位、內(nèi)存控制器和信道編號(hào)。mcelog老牌工具更多面向Intel平臺(tái)會(huì)把MCE事件解碼成可讀文本適合在舊系統(tǒng)上排查。EDAC/sysfs接口/sys/devices/system/edac/mc/mc0/ue_count這個(gè)文件里實(shí)時(shí)保存著不可糾正錯(cuò)誤計(jì)數(shù)。有些平臺(tái)每個(gè)mcX目錄對(duì)應(yīng)一個(gè)內(nèi)存控制器里面的ce_countcorrectable errors和ue_countuncorrectable errors可以直接cat出來(lái)。我曾經(jīng)在一臺(tái)雙路服務(wù)器上遇到過(guò)排查陷阱ue_count顯示2但ras-mc-ctl --errors里只列了一條記錄。后來(lái)發(fā)現(xiàn)是因?yàn)閡e_count在EDAC層把下一次讀取時(shí)又遇到同樣的物理壞地址合并處理了第二個(gè)錯(cuò)誤實(shí)際上是對(duì)同一個(gè)壞DIMM的重復(fù)訪問(wèn)并未產(chǎn)生新的MCA事件。所以看計(jì)數(shù)之前一定要結(jié)合錯(cuò)誤日志里的物理地址和DIMM槽位來(lái)綜合判斷。3.3 一份完整的UE應(yīng)急行動(dòng)清單當(dāng)告警出現(xiàn)在監(jiān)控屏上按下面的順序做能最大程度避免業(yè)務(wù)受損拍照留檔記錄當(dāng)前所有日志輸出包括dmesg、ras-mc-ctl --errors、帶外管理界面截圖重點(diǎn)記錄錯(cuò)誤物理地址和DIMM編號(hào)。確認(rèn)錯(cuò)誤是否持續(xù)增長(zhǎng)。如果undiected地址只出現(xiàn)過(guò)一次則暫時(shí)不恐慌觀察下一段時(shí)間看是否同一根內(nèi)存條反復(fù)出現(xiàn)新地址。定位物理DIMM槽位。根據(jù)rasdaemon或帶外管理控制器報(bào)告的信息將邏輯信道/內(nèi)存控制器編號(hào)映射到主板上的具體DIMM位置。大多數(shù)服務(wù)器主板在BIOS的Memory Ranks信息中會(huì)給出CPU、Channel、Slot編號(hào)的對(duì)應(yīng)關(guān)系。這一步做錯(cuò)了后面拔錯(cuò)內(nèi)存條會(huì)導(dǎo)致整機(jī)直接重啟很傷。安排可維護(hù)窗口進(jìn)行內(nèi)存替換。UE意味著存在不可糾正的硬錯(cuò)誤哪怕是一次性事件也說(shuō)明該內(nèi)存顆粒已經(jīng)處于不可靠狀態(tài)最好的處理方式就是更換。更新固件與微碼。有時(shí)UE是內(nèi)存控制器或時(shí)序訓(xùn)練固件的bug導(dǎo)致的針對(duì)特定型號(hào)顆粒主板廠商會(huì)發(fā)布新的BIOS或BMC固件修復(fù)對(duì)某些內(nèi)存條時(shí)序參數(shù)的識(shí)別錯(cuò)誤。執(zhí)行加壓測(cè)試。換完內(nèi)存后不要立刻上生產(chǎn)用memtest86跑一整輪完整測(cè)試確認(rèn)所有bank、所有地址模式都沒(méi)有報(bào)錯(cuò)再重新啟用設(shè)備。這里有一個(gè)從實(shí)戰(zhàn)里磨出來(lái)的經(jīng)驗(yàn)永遠(yuǎn)不要只根據(jù)ue_count數(shù)字決定要不要換件要看物理地址是否可復(fù)現(xiàn)。因?yàn)閁E一旦觸發(fā)系統(tǒng)固件很可能會(huì)屏蔽相關(guān)物理頁(yè)面后續(xù)訪問(wèn)同一地址會(huì)繼續(xù)產(chǎn)生同樣錯(cuò)誤導(dǎo)致計(jì)數(shù)疊加。這種情況下?lián)Q一塊CPU、甚至只是重新插拔一次內(nèi)存條讓固件重新做內(nèi)存初始化都可能讓計(jì)數(shù)停住。4. MBIST與ECC的相愛(ài)相殺芯片驗(yàn)證視角4.1 什么是MBIST為什么它不能取代ECCMBISTMemory Built-In Self Test是在芯片內(nèi)部、直接掛在存儲(chǔ)器端口上的自測(cè)試電路。它的目的是在制造測(cè)試或上電自檢階段快速覆蓋整片SRAM/DRAM的所有地址單元檢測(cè)stuck-at fault固定為0或1、transition fault翻轉(zhuǎn)慢、coupling fault單元間相互干擾等物理缺陷。有人會(huì)問(wèn)既然MBIST能把壞內(nèi)存顆粒測(cè)出來(lái)為什么還需要ECC答案是MBIST在出廠測(cè)試時(shí)可以找出已死的單元但物理器件的可靠性是隨時(shí)間變化的。一顆顆??赡茉诔鰪S時(shí)所有單元都是好的運(yùn)行半年后因?yàn)槟硞€(gè)defect慢慢電遷移、氧化物擊穿開(kāi)始出現(xiàn)單bit翻轉(zhuǎn)。ECC存在的目的就是應(yīng)對(duì)這種后天變壞把這位翻轉(zhuǎn)在業(yè)務(wù)無(wú)感的情況下糾正掉。反過(guò)來(lái)如果一個(gè)壞單元恰恰在MBIST測(cè)試時(shí)表現(xiàn)為可以讀寫但在某種特定的鄰近單元數(shù)據(jù)組合下才失效ECC可以兜住這種邊界錯(cuò)誤但長(zhǎng)期可靠性仍有風(fēng)險(xiǎn)。所以在成熟的SoC驗(yàn)證策略里MBIST和ECC不是替代關(guān)系而是互為補(bǔ)充——MBIST負(fù)責(zé)篩選出固定的物理缺陷ECC負(fù)責(zé)在生命周期內(nèi)吸收隨機(jī)錯(cuò)誤。驗(yàn)證工程師面臨的問(wèn)題則是如何讓這兩套機(jī)制在同一塊芯片上協(xié)同工作而不互相干擾。4.2 MBIST寫PatternECC在旁邊搗亂這是芯片驗(yàn)證里最容易翻車的一個(gè)環(huán)節(jié)。MBIST引擎為了測(cè)出存儲(chǔ)陣列的故障會(huì)用特定的算法March C-、GALPAT、Checkerboard等向目標(biāo)地址寫入特定的數(shù)據(jù)pattern再讀回比對(duì)。但如果存儲(chǔ)控制器的數(shù)據(jù)通路上有ECC編碼器問(wèn)題就來(lái)了MBIST寫入pattern的地址數(shù)據(jù)會(huì)先經(jīng)過(guò)ECC編碼器自動(dòng)生成校驗(yàn)位然后完整地一起寫入存儲(chǔ)體。這看起來(lái)沒(méi)有問(wèn)題真正的問(wèn)題在于某些故障模型需要直接對(duì)存儲(chǔ)陣列內(nèi)的原始數(shù)據(jù)做操作或者需要注入故障來(lái)驗(yàn)證ECC邏輯本身——MBIST的pattern經(jīng)編碼器扭曲后測(cè)試人員無(wú)法精確控制存儲(chǔ)體里存儲(chǔ)的位模式。舉一個(gè)實(shí)際場(chǎng)景version 1的MBIST控制器在設(shè)計(jì)時(shí)直接復(fù)用了內(nèi)存ECC的寫通道路徑。跑March C-測(cè)試時(shí)MBIST生成數(shù)據(jù)0x00000000_00000000經(jīng)ECC編碼后實(shí)際寫入存儲(chǔ)體的是72位的碼字64個(gè)數(shù)據(jù)位全08個(gè)校驗(yàn)位全0。接下來(lái)MBIST寫0xFFFFFFFF_FFFFFFFF實(shí)際寫入的碼字里有一部分校驗(yàn)位不是全1。由于MBIST希望驗(yàn)證的正是寫0讀0、寫1讀1的物理單元行為而ECC編碼后的數(shù)據(jù)對(duì)這種期望值做了二次變換一旦ECC邏輯本身有bug比如校驗(yàn)位計(jì)算錯(cuò)誤測(cè)試結(jié)果會(huì)直接判Fail但這個(gè)Fail是來(lái)自存儲(chǔ)單元還是來(lái)自ECC邏輯很難從結(jié)果里分離出來(lái)。正確的做法是在MBIST模式下通過(guò)一個(gè)獨(dú)有的旁路信號(hào)把ECC編碼器從數(shù)據(jù)通路上隔離出去。MBIST直接向存儲(chǔ)陣列寫入原始pattern不經(jīng)過(guò)任何編解碼。ECC邏輯在MBIST模式下就必須處于完全靜默的狀態(tài)。這個(gè)旁路信號(hào)需要和業(yè)務(wù)模式的開(kāi)關(guān)互鎖防止跑到一半被誤觸發(fā)。你要是問(wèn)為什么很多設(shè)計(jì)死都死在這里答案往往就是這個(gè)旁路的互鎖邏輯沒(méi)有做干凈。4.3 ECC錯(cuò)誤注入驗(yàn)證ECC邏輯的關(guān)鍵場(chǎng)景驗(yàn)證ECC邏輯本身只在MBIST中測(cè)試正常讀寫是不夠的因?yàn)镋CC的糾錯(cuò)和檢錯(cuò)路徑只有在真實(shí)發(fā)生位翻轉(zhuǎn)時(shí)才會(huì)被觸發(fā)。而芯片內(nèi)部并不會(huì)平白無(wú)故產(chǎn)生位翻轉(zhuǎn)所以驗(yàn)證階段要人為注入錯(cuò)誤。業(yè)界通用做法是在MBIST控制器或ECC引擎內(nèi)部加一套錯(cuò)誤注入邏輯Error Injection, EI。通常提供幾種注入模式注入到寫入路徑在數(shù)據(jù)從總線進(jìn)入存儲(chǔ)體之前把某一位或多位進(jìn)行翻轉(zhuǎn)。這樣存儲(chǔ)體里存的數(shù)據(jù)本身就是錯(cuò)的讀取時(shí)會(huì)觸發(fā)ECC的糾正流程。這種注入方式最貼近真實(shí)的位翻轉(zhuǎn)場(chǎng)景。注入到讀取路徑數(shù)據(jù)從存儲(chǔ)體讀出之后、進(jìn)入ECC解碼器之前做翻轉(zhuǎn)。這種方式模擬的是讀路徑數(shù)據(jù)總線上的信號(hào)完整性問(wèn)題而不是存儲(chǔ)單元的故障。注入到地址總線把讀或?qū)懖僮鞯哪繕?biāo)地址指到另一個(gè)位置用于驗(yàn)證地址譯碼器和ECC邏輯的交互這種場(chǎng)景比較少見(jiàn)但對(duì)排查數(shù)據(jù)寫不進(jìn)正確地址的bug非常有效。無(wú)論哪種注入最關(guān)鍵的一點(diǎn)是注入窗口的控制。必須精確定義從哪個(gè)cycle開(kāi)始注入、持續(xù)多少cycle、在哪個(gè)bank/row/column位生效。如果注入窗口不精確錯(cuò)誤可能落在ECC解碼器無(wú)感區(qū)比如剛剛寫完、數(shù)據(jù)還在緩沖里導(dǎo)致測(cè)試結(jié)果不穩(wěn)定。我見(jiàn)過(guò)不少驗(yàn)證團(tuán)隊(duì)在最初跑ECC error injection的時(shí)候前后跑了十幾個(gè)小時(shí)每次注入的結(jié)果都不一樣最終發(fā)現(xiàn)是注入使能信號(hào)沒(méi)有和存儲(chǔ)器的寫完成響應(yīng)做同步導(dǎo)致有時(shí)錯(cuò)誤數(shù)據(jù)沒(méi)進(jìn)存儲(chǔ)體就結(jié)束了。4.4 MBIST與ECC狀態(tài)清理的連鎖反應(yīng)MBIST測(cè)試結(jié)束之后存儲(chǔ)體里殘留了大量測(cè)試pattern其中包括一些經(jīng)過(guò)錯(cuò)誤注入的、不可糾正的碼字。如果此時(shí)直接退出MBIST模式把系統(tǒng)切到業(yè)務(wù)模式并讓ECC引擎接管存儲(chǔ)器的訪問(wèn)會(huì)發(fā)生什么答案很刺激ECC引擎在首次訪問(wèn)到某個(gè)殘留的錯(cuò)誤碼字時(shí)會(huì)立即上報(bào)一個(gè)UE。如果這個(gè)UE的控制邏輯沒(méi)有做好與系統(tǒng)上電流程的握手可能直接觸發(fā)MCE或系統(tǒng)啟動(dòng)自檢失敗。所以在真機(jī)驗(yàn)證階段MBIST模式下跑完所有故障注入用例之后必須有一個(gè)專門的存儲(chǔ)體清理序列要么重新寫一遍所有地址的已知數(shù)據(jù)要么直接對(duì)相關(guān)內(nèi)存段做一次性ECC重計(jì)算和重寫。同時(shí)還要將ECC狀態(tài)寄存器里的CE/UE計(jì)數(shù)清零防止殘留的歷史錯(cuò)誤干擾后續(xù)正式業(yè)務(wù)的數(shù)據(jù)記錄。這是一個(gè)很容易被測(cè)試用例規(guī)劃遺漏的細(xì)節(jié)。很多工程師在RTL仿真階段看不到這個(gè)問(wèn)題因?yàn)榉抡姝h(huán)境通常不會(huì)模擬MBIST和ECC同時(shí)上電的場(chǎng)景只有到了系統(tǒng)級(jí)驗(yàn)證或回片測(cè)試階段這個(gè)問(wèn)題才會(huì)以各種詭異的啟動(dòng)失敗形式冒出來(lái)。5. 常見(jiàn)問(wèn)題速查從日志到硬件的排障手冊(cè)把這些年遇到的典型問(wèn)題整理成一張速查表希望能幫你少走點(diǎn)彎路?,F(xiàn)象可能原因優(yōu)先排查動(dòng)作dmesg看到Uncorrected ECC Detected系統(tǒng)沒(méi)掛UE落在未使用的物理頁(yè)或被固件屏蔽記錄物理地址觀察計(jì)數(shù)是否持續(xù)安排內(nèi)存替換ras-mc-ctl --errors記錄的地址一直不變固件對(duì)壞頁(yè)做了屏蔽每次訪問(wèn)同一地址重復(fù)報(bào)錯(cuò)確認(rèn)是不是同一DIMM同一rank換件即可/sys里的ue_count和rasdaemon顯示不一致兩套工具統(tǒng)計(jì)口徑不同或EDAC驅(qū)動(dòng)未完全加載以帶外管理日志為準(zhǔn)同時(shí)檢查edac模塊是否加載MEMTEST86報(bào)錯(cuò)但系統(tǒng)日志無(wú)ECC記錄BIOS中ECC開(kāi)關(guān)未開(kāi)啟或內(nèi)存運(yùn)行在非ECC模式進(jìn)BIOS確認(rèn)Memory ECC選項(xiàng)為Enabled重啟后重新測(cè)試DIMM Status顯示OK但ce_count持續(xù)增長(zhǎng)單bit可糾正錯(cuò)誤持續(xù)出現(xiàn)單元存在潛在故障重視CE增長(zhǎng)趨勢(shì)盡早安排替換避免演進(jìn)為UE更換內(nèi)存條后ue_count仍然存在日志順序未徹底清理或報(bào)錯(cuò)來(lái)自另一根內(nèi)存清理日志和BMC計(jì)數(shù)后重新加壓測(cè)試觀察是否新增MBIST失敗但實(shí)際存儲(chǔ)單元完好ECC編碼器在MBIST模式下未旁路pattern被改寫確認(rèn)MBIST旁路信號(hào)是否有效在驗(yàn)證平臺(tái)中打印校檢修標(biāo)志MBIST錯(cuò)誤注入結(jié)果不穩(wěn)定注入窗口與讀寫時(shí)序未對(duì)齊檢查注入使能信號(hào)是否與有效數(shù)據(jù)同步縮小注入窗口5.1 關(guān)于CE增長(zhǎng)但UE為0要不要?jiǎng)雍芏噙\(yùn)維在ce_count不斷增長(zhǎng)的情況下因?yàn)閡e_count還是0就判定內(nèi)存沒(méi)問(wèn)題。這其實(shí)是個(gè)危險(xiǎn)的誤解。CECorrectable Error說(shuō)明發(fā)生了什么說(shuō)明ECC引擎確實(shí)糾錯(cuò)成功了——它糾正了不代表此后的每次讀都對(duì)。當(dāng)一個(gè)存儲(chǔ)單元開(kāi)始頻繁出現(xiàn)CE時(shí)它的故障率正在指數(shù)上升之后那一次UE出現(xiàn)往往就是壓垮駱駝的最后一根稻草。我個(gè)人的經(jīng)驗(yàn)法則是如果一塊DIMM的ce_count在兩周內(nèi)持續(xù)增長(zhǎng)超過(guò)一個(gè)量級(jí)即使沒(méi)有UE也應(yīng)該進(jìn)入更換流程并優(yōu)先考慮把這塊DIMM上的業(yè)務(wù)負(fù)載遷移走。很多廠商的RAS策略里也會(huì)把同一DIMM的CE到達(dá)閾值設(shè)為主動(dòng)預(yù)警條件。5.2 關(guān)于內(nèi)存條混插ECC內(nèi)存對(duì)顆粒一致性要求比普通人以為的更高。不同廠商、不同批次、甚至同一廠商不同周期的顆粒在時(shí)序培訓(xùn)時(shí)的表現(xiàn)會(huì)有細(xì)微差異?;觳蹇赡軐?dǎo)致內(nèi)存控制器只能按最差的時(shí)序參數(shù)運(yùn)行表面上看兼容性沒(méi)毛病但在長(zhǎng)時(shí)間高負(fù)載下讀寫裕量大幅下降CE/UE數(shù)量會(huì)明顯上升。盡量保持同一個(gè)DIMM槽位組內(nèi)的顆粒規(guī)格一致至少保證同一個(gè)Channel下的DIMM來(lái)自同一批次。你沒(méi)看錯(cuò)不是只要同容量同頻率就行連緩存行都細(xì)到顆粒級(jí)別的匹配才能讓時(shí)序訓(xùn)練結(jié)果更優(yōu)。5.3 服務(wù)端替換內(nèi)存后必做的三個(gè)核對(duì)核對(duì)槽位映射替換前拍照、畫圖記錄好哪根DIMM對(duì)應(yīng)哪個(gè)Channel/Rank。若插錯(cuò)槽位可能觸發(fā)內(nèi)存鏡像模式的寫入數(shù)據(jù)不一致問(wèn)題。核對(duì)BIOS內(nèi)存配置確認(rèn)ECC Mode、Mirror Mode、NUMA相關(guān)開(kāi)關(guān)與替換前一致否則性能可能莫名掉一截。核對(duì)日志時(shí)間軸新的物理內(nèi)存安裝好后記得清理BMC和rasdaemon的歷史日志避免舊的UE計(jì)數(shù)與新事件混淆。6. 一點(diǎn)額外的體會(huì)說(shuō)回開(kāi)頭那個(gè)顯示2。在處理完那臺(tái)機(jī)器、換掉壞DIMM之后我特意把整個(gè)排查過(guò)程整理成了一套標(biāo)準(zhǔn)腳本包含自動(dòng)抓取rasdaemon錯(cuò)誤摘要、定位錯(cuò)誤物理地址和DIMM槽位以及替換后自動(dòng)清零統(tǒng)計(jì)的步驟。后來(lái)團(tuán)隊(duì)每次處理類似告警都按照這套腳本來(lái)走最直接的影響是沒(méi)人再因?yàn)轱@示2這種數(shù)字而慌亂拔內(nèi)存了。ECC這個(gè)領(lǐng)域給我的感覺(jué)是它表面上是內(nèi)存控制器里的一段邏輯實(shí)際上牽扯到物理失效、體系結(jié)構(gòu)、固件策略和芯片驗(yàn)證四個(gè)維度。任何一個(gè)維度沒(méi)打通遇到問(wèn)題時(shí)都會(huì)感覺(jué)像隔著一層霧。如果你也正在被某個(gè)數(shù)字2困擾先把日志和物理地址對(duì)上再做任何硬件動(dòng)作這是我能給出的最實(shí)在的建議。