1. 程式人生 > >Spectre/Meltdown演義--專業篇(1)

Spectre/Meltdown演義--專業篇(1)

微信公眾號  MindShare思享



CPU Speculation

 

 上文說過為了提高CPU的效能,CPU會有speculation的行為,Speculation可以以很多方式實現,比如Speculation memory access,Speculation instruction execution等。

 

Speculation memory access 可以是speculativecache preload, speculation load.


Cache speculative prefetch

為了提供CPU的memory 訪問效率,特別是比較大塊的資料訪問,比如memcpy。通常可以假設資料訪問時有規則的,比如是連續資料訪問,或是以固定的地址間隔(stride)訪問。這樣的話CPU的cache hardware可以做一些優化。在很多的CPU裡(幾乎所有的Cortex-A CPU)中cache會自動監測CPU訪問的pattern,在下面的例子裡,如果程式碼的前三個LDR都導致了cache miss,那麼cache hardware就會開始推測software是想做連續的訪問,在做第三個LDR的時候(還不知道後面software code會不會真的繼續連續訪問),CPU會開始預取(speculative prefetch)第四個cache line資料。

 

大多數情況下,這是成立的,因為實際的軟體裡的確很多類似memcpy的大塊資料訪問。因此這種硬體優化在Intel,Arm的CPU裡非常常見。


除了監測連續的訪問,Cache還可以監測隔幾個cache lines的stride訪問方式,比如

  •  Addr,

  •  Addr+2*cache_line_size,

  •  Addr+4*cache_line_size,

更有甚者,Cache還可以同時監測幾個pattern的訪問,比如一個隔2個stride和一個隔5的stride.


Speculative load instruction execution

很多時候軟體程式碼裡有control dependency, 導致一些hazard,

在上面的程式碼裡先從memory裡read一個值,再比較這個值是否是0,

   如果不是的話跳到else地方執行,

   如果是的話從r4的地址裡讀出一個值。

如果不幸第一load出現TLB miss或是cache miss,那麼比較和跳轉指令就可能不能繼續了,出現pipeline stall.

幸好我們有out of order和speculation技術,它基本上要利用register renaming來實現。


Register Renaming

有了register renaming可以減少register dependency帶來的hazard, 實現方式是,

程式碼裡的暫存器比如r0, 它只是architecture 暫存器,當指令被fetech, decode後,到了dispatch階段,architecture暫存器會被map到真正的physical registers上,通常physical register個數會比architecture 暫存器多不少。


在Dispatch階段,可以做如下的architecture register到physical register的map,


         MapTable


r1

r2

r3

  原始指令


Map後的指令

p1

p2

p3

add r2,r3,r1


add p2,p3,p4

p4

p2

p3

sub r2,r1,r3


sub p2,p4,p5

p4

p2

p5

mul r2,r3,r3


mul p2,p5,p6

p4

p2

p6

div r1,4,r1


div p4,4,p7



我們可以通過這樣的辦法對上面的指令做這樣的map,


這樣的話我們就可以speculative執行第二個LDR,因為speculative執行只會改變physical暫存器的值,如果之後條件不滿足,只是去掉這個map,不回寫就好了。

但記住資料確實進入過cache,雖然最終程式沒看到這個資料。


需要注意的是,一般來說只會做speculative的讀(load)操作,而不會做speculative的寫操作。因為讀的結果比較容易放棄,但是寫speculation的話,比較能將speculation做的事情放棄,代價會比較高。

 

下節將介紹cacheside channel attack.