奔騰(R) 4 處理器主題自我修改程式碼清除

執行緒特定性TS

由於自我修改程式碼問題而清除機器的整個管道的次數。

對程式碼段中目前已在處理器中快取的記憶體位置進行寫入操作時,會導致關聯的快取線失效。此檢查基於指令的實體地址。此外,P6 系列與英特爾(R) 奔騰(R) 處理器還會檢查對程式碼段的寫入是否會修改已經預取(以便執行)的指令。如果寫入會影響預取的指令,則預取佇列將失效。后一種檢查基於指令的線性地址。對於奔騰 4 處理器,對目標指令已經解碼並儲存在跟蹤快取中的程式碼段進行寫入操作,或是嗅探其中的指令,將使整個跟蹤快取失效。后一種行為表示,在奔騰 4 處理器上執行程式時,自我修改程式碼可能會導致效能嚴重下降。關於嗅探的詳細資訊:

如果處理器 A 在跟蹤快取中有一條快取線,處理器 B 希望讀取該快取線(不論是當作程式碼還是數據),則它將嗅探處理器 A 的快取。這種“讀取嗅探”不影響處理器 A。不過,如果處理器 B 試圖寫入該快取線,則它會以“寫入嗅探”的方式嗅探處理器 A 的快取,並導致跟蹤快取被清除。因此,在奔騰 4 處理器上,此處理器或任何處理器對快取線的寫入操作,都將清除跟蹤快取。任何處理器對該快取線的讀取操作都不影響效能。

實際上,線性地址檢查應該不會在 IA-32 處理器之間產生相容性問題。包含自我修改程式碼的應用程式使用相同的線性地址修改與獲取指令。系統軟體(如偵錯程式)可能會使用不同於獲取指令時的線性地址修改指令,在執行修改的指令之前,系統軟體會執行序列化操作(如 CPUID 指令),以便自動重新同步指令快取與預取佇列。對於 Intel486(TM) 處理器,對快取中的指令進行寫入操作時,將同時在快取與記憶體中修改它,但如果在寫入之前已經預取該指令,則會執行舊版本的指令。要避免執行舊指令,可以在修改指令的寫入操作後面,緊接著編寫一條跳轉指令,以便清除指令預取單元。

處理自我修改與交叉修改程式碼

處理器將數據寫入目前正在執行的程式碼段,並將這些數據當作程式碼來執行,這種程式碼稱為自我修改程式碼。執行自我修改程式碼時,IA-32 處理器的行為取決於型號,具體取決於在目前執行指針之前多遠的位置修改程式碼。隨著處理器體系結構變得越來越複雜,並開始在失效點之前憑推測執行程式碼(在奔騰 4 與 P6 系列處理器中就是這樣),有關應該執行哪些程式碼、先修改還是后修改等等規則也變得模糊不清。