推測執行(speculative execution)
想像你開車駛向一個岔路,而導航還在重新計算。你不會猛然停住,而是做出最佳猜測,繼續沿較可能的那條岔路開;猜對就省了時間,猜錯就掉頭。推測執行就是 CPU 在做這件事:當它遇到一個結果尚未知曉的分支(或任何不確定)時,它預測可能的路徑,並立刻沿著它開始執行指令,遠在能確定這些指令到底該不該執行之前。
具體來說,一道條件分支被提取時,分支預測器猜「跳」或「不跳」,前端便沿著預測路徑繼續提取與執行。這些推測指令照常通過保留站與執行單元,但它們的結果被扣在重排序緩衝區裡、並不提交——不正式生效——直到分支真正解出為止。若預測正確,這些指令早已完成,只要按順序提交即可,省下大把時間。若預測錯誤,機器就壓掉(丟棄)ROB 裡所有推測指令,把更名與其他狀態還原到分支那一點,再沿正確路徑重新開始提取。因為沒有任何推測結果被提交,可見狀態毫髮無傷。
推測,配上良好的分支預測,正是讓一條深的亂序管線能跨越真實程式碼中頻繁分支而保持滿載的東西——沒有它,機器會在每個分支前停下來等待方向。誠實且如今聲名大噪的提醒:雖然推測工作會從架構狀態被回捲,它仍會留下微架構痕跡——最著名的是它能把資料拉進快取。Spectre 與 Meltdown 利用的正是這一點,透過量測快取時序,讀出推測碰過、卻號稱「從未發生」的祕密。推測本是效能功能,結果竟成了一個真實、可被利用的安全面。
迴圈的分支被預測為「跳」,於是核心在分支條件還在計算時,就推測地執行下一個迭代的本體。若真的跳,這些工作就是白賺;若沒跳,那些指令就從 ROB 被壓掉,永不可見。
提早沿預測路徑執行;若猜錯就把工作丟掉。
壓掉錯誤路徑的工作會撤銷它的架構效果,卻撤不掉它的微架構足跡(例如快取狀態)。Spectre/Meltdown 證明這留下的足跡是一個真實、可被利用的側通道——而非理論上的顧慮。