最近在了解Meltdown攻击,在网上发现了Syracuse University的Wenliang Du教授写的关于这方面的实验教程。感觉很受益,粗略地翻译了一部分,自己跟着做了实验,记录于此。
感兴趣的可以去原网址查看,讲义和代码都可以找到:https://seedsecuritylabs.org/Labs_16.04/System/Meltdown_Attack/
Task 1 :读Cache Vs. 读Memory
CPU cache的功能是降低CPU从内存读写数据的损失。从CPU cache来读写数据要比去从内存读写快得多。当数据从内存中取出时,通常会被缓存到CPU中,当相同的数据再次被使用时,就会降低取数据的时间,增加效率。因此,当CPU需要读写数据,先去看一下cache中有没有数据,如果有,就从cache拿数据。反之,再去比较远的内存去拿数据。去内存拿数据的时间要远远高于去cache拿数据的时间。大部分的现代CPU都有CPU caches。
图片来源于实验教程的讲义
在下面的代码中,我们有个数组大小为10 * 4096。我们首先访问其中的两个元素,array[3 * 4096]和array[7 * 4096]。因此,包含这两个元素的页就会被缓存。然后,我们读取array[0 * 4096] 到 array[9* 4096 ],然后测量从内存读取这些元素的时间。
#include <emmintrin.h>
#include <x86intrin.h>
uint8_t array[10*4096];
int main(int argc, const char **argv) {
int junk=0;
register uint64_t time1, time2;
volatile uint8_t *addr;
int i;
// Initialize the array
for(i=0; i<10; i++) array[i*4096]=1;
// FLUSH the array from the CPU cache
for(i=0; i<10; i++) _mm_clflush(&array[i*4096]);
// Access some of the array items
array[3*4096] = 100;
array[7*4096] = 200;
for(i=0; i<10; i++) {
addr = &array[i*4096];
time1 = __rdtscp(&junk); À
junk = *addr;
time2 = __rdtscp(&junk) - time1; Á
printf("Access time for array[%d*4096]: %d CPU cycles\n",i, (int)time2);
}
return 0;
}
实验记录
array | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Average |
---|---|---|---|---|---|---|---|---|---|---|---|
array[0*4096] | 104 | 136 | 132 | 146 | 106 | 84 | 134 | 114 | 120 | 98 | 117.4 |
array[1*4096] | 174 | 182 | 222 | 304 | 184 | 184 | 188 | 182 | 218 | 206 | 204.4 |
array[2*4096] | 172 | 184 | 208 | 180 | 188 | 184 | 188 | 182 | 212 | 190 | 188.8 |
array[3*4096] | 52 | 48 | 62 | 42 | 30 | 28 | 42 | 48 | 182 | 46 | 58 |
array[4*4096] | 274 | 166 | 204 | 184 | 188 | 182 | 798 | 166 | 202 | 188 | 255.2 |
array[5*4096] | 164 | 184 | 204 | 958 | 178 | 266 | 188 | 184 | 204 | 182 | 271.2 |
array[6*4096] | 166 | 186 | 760 | 172 | 184 | 184 | 188 | 184 | 224 | 186 | 243.4 |
array[7*4096] | 28 | 44 | 84 | 50 | 24 | 28 | 46 | 30 | 70 | 46 | 45 |
array[8*4096] | 178 | 184 | 844 | 184 | 168 | 182 | 184 | 184 | 234 | 188 | 253 |
array[9*4096] | 186 | 184 | 246 | 186 | 184 | 182 | 186 | 186 | 216 | 166 | 192.2 |