WBINVD指令用法
我正在尝试在linux上使用WBINV指令来清除处理器的L1缓存。
以下程序编译,但在我尝试运行它时会产生分段错误。
int main() {asm ("wbinvd"); return 1;}
我正在使用gcc 4.4.3并在我的x86机器上运行Linux内核2.6.32-33。
处理器信息:Intel(R)Core(TM)2 Duo CPU T5270 @ 1.40GHz
我按如下方式构建了程序:
$ gcc
$ ./a.out
分段故障
有人能告诉我我做错了什么吗? 我如何让它运行?
PS:我正在运行一些性能测试,并希望确保处理器缓存的先前内容不会影响结果。
引自英特尔®64和IA-32架构软件开发人员手册合并卷2A和2B:指令集参考,AZ :
WBINVD指令是特权指令。 当处理器在保护模式下运行时,程序或过程的CPL必须为0才能执行该指令。
换句话说,只允许内核模式代码执行它。
编辑:以前关于清除缓存的SO讨论:
“C”以编程方式清除Linux机器上的L2缓存
如何在x86 Windows中执行CPU缓存刷新?
如何清除CPU L1和L2缓存
https://stackoverflow.com/questions/3443130/how-to-clear-cpu-l1-and-l2-cache
正如user786653所写, wbinvd
是一个特权指令,它在非内核代码中进行段错误。
你应该避免使用wbinvd
进行基准测试,因为它会强制所有类型的总线锁定周期,管道序列化并增加从内核到用户空间等的开销,这很可能不会发生在你的真实世界程序中。
因此,您的测量将不会更精确,它将包含各种工件。 读取L2缓存大小的数据块将产生更好的结果。
您可以阅读用于测量时钟周期和性能监控的测试程序下的源代码,以了解其他人如何获得有用的结果。
实际上,如果在用户空间(环3)中执行特权指令,则会得到一个SIGIL,其子代码为ILL_PRVOPC(signal(7)manpage)。
SIGSEGV保留用于涉及内存的exception,例如戳到尚未映射的虚拟地址,或尝试写入只读页面。
有人需要告诉linux有关posix标准的信息。