什么是确定英特尔Kaby Lake架构上最后一级缓存未命中数的确切代码

cry*_*oob 8 c++ x86 caching reverse-engineering perf

我读了一篇有趣的论文,名为"对最后一级缓存的高分辨率侧通道攻击",并希望找到我自己机器的索引哈希函数 - 即Intel Core i7-7500U(Kaby Lake架构) - 遵循这项工作的线索.

为了对散列函数进行逆向工程,本文提到了第一步:

 for (n=16; ; n++) 
 {
   // ignore any miss on first run
   for (fill=0; !fill; fill++) 
   {
     // set pmc to count LLC miss
     reset_pmc();
     for (a=0; a<n; a++)
       // set_count*line_size=2^19
       load(a*2^19);
   }

   // get the LLC miss count
   if (read_pmc()>0) 
   {
     min = n;
     break;
   }
 }
Run Code Online (Sandbox Code Playgroud)

我如何编写代码reset_pmc(),并read_pmc()在C++?从我到目前为止在线阅读的所有内容来看,我认为它需要内联汇编代码,但我不知道用什么指令来获取LLC未命中数.如果有人可以为这两个步骤指定代码,我将不得不承担责任.

我在VMware工作站上运行Ubuntu 16.04.1(64位).

PS:我发现这些记载LONGEST_LAT_CACHE.REFERENCESLONGEST_LAT_CACHE.MISSES在第18的的3B卷英特尔架构软件开发手册,但我不知道如何使用它们.

Bee*_*ope 8

您可以使用perfCody建议来测量代码外部的事件,但我怀疑您的代码示例中需要对性能计数器进行细粒度的编程访问.

要做到这一点,您需要启用计数器的用户模式读取,并且还可以对它们进行编程.由于这些是受限制的操作,因此至少需要操作系统内核的一些帮助才能做到这一点.滚动你自己的解决方案将非常困难,但幸运的是,Ubunty 16.04有几个现有的解决方案:

  • Andi Kleen的jevents库,其中包括让您从用户空间读取PMU事件.我没有亲自使用这部分pmu-tools,但我使用过的东西质量很高.它似乎使用现有的perf_events系统调用进行计数器编程,因此不需要内核模型.
  • libpfc库是一个从划痕执行内核模块和用户空间的代码,使性能计数器的用户态阅读.我用过这个,效果很好.您安装了允许您对PMU进行编程的内核模块,然后使用libpfc公开的API从用户空间读取计数器(调用归结为rdpmc指令).它是读取计数器的最准确和最精确的方法,它包括"开销减法"功能,通过减去由PMU读取代码本身引起的事件,可以为您提供测量区域的真实PMU计数.您需要固定到单个核心以使计数有意义,如果您的过程中断,您将会伪造结果.
  • 英特尔的开源处理器计数器监控库.我没有在Linux上试过这个,但是我使用了它的前身库,在Windows上命名为1 Performance Counter Monitor,它起作用了.在Windows上,它需要内核驱动程序,但在Linux上,您似乎可以使用驱动器或让它通过perf_events.
  • 使用likwid库的Marker API功能.Likwid已经存在了一段时间,似乎得到了很好的支持.我过去曾使用过likwid,但仅用于测量perf stat与标记API 相似而不是标记API的整个过程.要使用标记API,您仍然需要将您的过程作为可能的测量过程的子项运行,但您可以通过编程方式读取过程中的计数器值,这正是您所需要的(据我所知).我不确定在使用标记API时设置和读取计数器有多么可取.

所以你有很多选择!我认为所有这些都可以工作,但我可以亲自担保,libpfc因为我自己在Ubuntu 16.04上使用它同样的目的.该项目正在积极开发,可能是上述最准确(最少开销)的项目.所以我可能从那个开始.

上述所有解决方案都应该能够适用于Kaby Lake,因为每个连续的"性能监控架构"的功能似乎通常都是前一个的超集,并且通常会保留API.libpfc但是,在这种情况下,作者限制为仅支持Haswell的体系结构(PMA v3),但您只需在本地更改一行代码即可解决此问题.


1实际上,它们通常都被称为PCM,我怀疑新项目只是旧PCM项目的官方开源延续(也可以源形式提供,但没有社区贡献机制) .