一、前言
先前有客戶遇到了藍屏死機(BSOD)的問題,懷疑是安裝我們家的驅動導致。於是向前線要了客戶的memory dump。以下會透過Windbg來釐清問題的主因並推測可能的兇手。
先前有客戶遇到了藍屏死機(BSOD)的問題,懷疑是安裝我們家的驅動導致。於是向前線要了客戶的memory dump。以下會透過Windbg來釐清問題的主因並推測可能的兇手。
二、問題分析
1. !analyze -v
Dump初判為CLOCK_WATCHDOG_TIMEOUT(101)的Bugcheck code,表示在MP(Multi processor)系統下有一個處理器在時間內沒有回應一個處理器的中斷,通常的原因是這個處理器可能在一個死鎖或是運行在高IRQLs的狀態下,才會導致中斷遮罩。
2. !cpuinfo
檢查目標電腦的硬體資訊,有四顆處理器,每個實體處理器有2核心,可以產生2個邏輯處理器,應該是沒有支援或關閉HT(Hyper thread)。
3. !prcb ID
檢查各處理器的狀態,獲得irql與thread address等資訊。這裡發現出現問題的prcb位址905001205正好是處理器2,與之前的資訊吻合。
檢查各處理器的狀態,獲得irql與thread address等資訊。這裡發現出現問題的prcb位址905001205正好是處理器2,與之前的資訊吻合。
4. Trace call stack
(4-1)針對相關的處理器進行追蹤。#0 透過kv可以得到call stack和trapFrame。trapFrame可以讓我們得到在中斷(Clock interrupt)前的暫存器狀態,對我們trace code很有幫助。
我們知道在中斷前的函式是KeFlushMultipleRangeTb和KeFlushPteList這兩個函式,主要是用作更新TLB(Translation Lookaside Buffer) cache (#1),在處理器更新自己的TLB後,處理器也會通知其他處理器,你們該刷新一下自己的TLB cahce了,所以會透過發送IPI packet來中斷其他處理器。由下圖知道Inter-processor
interrupt的中斷層級是相當高的,所以除非目標處理器運行在這個中斷層級之上(30 - 31),才有可能屏蔽掉這個要求,讓插斷進入佇列。
有個疑問,發送IPI端的處理器本身的IRQL當下是位於哪一層,本身怎們不會被屏蔽。答案如下就是Synch(27),所以出事的是在別顆處理器而不是自己,由於等待IPI的回應太久導致中斷超時,才會收到Clock中斷,所以我們可以看到處理器當時的IRQL會在28就是這個原因。
更進一步反匯編KeFlushMultipleRangeTb,配合Call Stack落點位址(nt!KeFlushMultipleRangeTb+0x2d5
(8407c452))可以知道當下處理器1正在等待IPI回應。
再一次確認各處理器的IPI狀態,可以再一次確定處理器2跟處理器3正在接收IPI packet,但是處理器2並沒有回應。
(4-2)#2這裡會檢查thread2的行為,先利用指令dps將thread所有的行為展開,再來追蹤幾個函式前後看有沒有在運行階段將IRQLs提升到29(Inter-processor interrupt)之上。但結果是底層核心幾乎都在處理網路傳輸,幾乎就是協議驅動(TCPIP.sys)與NDIS與網卡驅動間的動作。反匯的函式幾乎也都是運行在DPC level和Sync之間,但在這個中斷層級區間並不會遮罩IPI,所以可以推斷問題與核心以及網卡驅動間的關聯較小。由於底層驅動並沒有透過TDI來發送網路封包,而是間接的使用socket去傳輸,所以在kernel stack裡看不到我們的蹤跡,而事情的起因的確由我們而起,但造成問題的主因應該不在於我們。
三、結論
我們透過socket進行大量的網路傳輸。而追蹤結果在核心內的確是有大量的網路行為,這會產生大量的PTE變更,進而產生IPI與FlushTb等動作,有可能就會加速問題的產生。最後是核心與網卡之間並沒有異常的IRQL變化,所以也不太可能是底層(OS與網卡)的問題。所以我的建議是應該再檢查一下硬體有沒有其他的問題,例如CPU過熱或是電壓等其他的問題。
四、補充
#1 TLB(Translation Lookaside Buffer)
我們知道不管核心程式或是使用者的process都是使用虛擬位址。但事實上處理器真正使用的是實體位址。所以Memory manager的工作之一就是協助處理器處理記憶體轉譯的工作。將我們看到的邏輯位址映射至實體頁(Page frame)。在32位元下。轉譯的過程中,這樣的動作需要查表兩次,一次是從Page directory找到Page Table,接著再從Page Table找到PTE (由PFN與Page的旗標組成)。最後透過PFN與byte index來訪問實體頁。如果每次轉譯都要經過這樣的步驟,其實系統的效能是不高的。所以才會有TLB的產生,CPU會將每次轉譯的結果快取下來,一旦處理相同的位址,直接查表就可以了。
沒有留言:
張貼留言