我们正在尝试使用Intel CLFLUSH指令在用户空间中刷新Linux中进程的缓存内容.
我们创建了一个非常简单的C程序,它首先访问一个大型数组,然后调用CLFLUSH来刷新整个数组的虚拟地址空间.我们测量CLFLUSH刷新整个阵列所需的延迟.程序中阵列的大小是一个输入,我们将输入从1MB变为40MB,步长为2MB.
根据我们的理解,CLFLUSH应该刷新缓存中的内容.所以我们期望看到整个阵列的刷新延迟首先在阵列大小方面线性增加,然后在阵列大小大于20MB(这是我们程序的LLC的大小)之后延迟应该停止增加.
然而,实验结果非常令人惊讶,如图所示.数组大小超过20MB后,延迟不会停止增加.
我们想知道如果地址不在缓存中,CLFLUSH是否可能在CLFLUSH将地址刷出缓存之前引入地址?我们还试图在英特尔软件开发人员手册中搜索,但没有找到任何解释,如果地址不在缓存中,CLFLUSH会做什么.
以下是我们用于绘制图形的数据.第一列是以KB为单位的数组大小,第二列是以秒为单位刷新整个数组的延迟.
任何建议/建议都不仅仅是值得赞赏的.
[改性]
以前的代码是不必要的.尽管CLFLUSH具有相似的性能,但它可以更容易地在用户空间中完成.所以我删除了凌乱的代码以避免混淆.
SCENARIO=Read Only
1024,.00158601000000000000
3072,.00299244000000000000
5120,.00464945000000000000
7168,.00630479000000000000
9216,.00796194000000000000
11264,.00961576000000000000
13312,.01126760000000000000
15360,.01300500000000000000
17408,.01480760000000000000
19456,.01696180000000000000
21504,.01968410000000000000
23552,.02300760000000000000
25600,.02634970000000000000
27648,.02990350000000000000
29696,.03403090000000000000
31744,.03749210000000000000
33792,.04092470000000000000
35840,.04438390000000000000
37888,.04780050000000000000
39936,.05163220000000000000
SCENARIO=Read and Write
1024,.00200558000000000000
3072,.00488687000000000000
5120,.00775943000000000000
7168,.01064760000000000000
9216,.01352920000000000000
11264,.01641430000000000000
13312,.01929260000000000000
15360,.02217750000000000000
17408,.02516330000000000000
19456,.02837180000000000000
21504,.03183180000000000000
23552,.03509240000000000000
25600,.03845220000000000000
27648,.04178440000000000000
29696,.04519920000000000000
31744,.04858340000000000000
33792,.05197220000000000000
35840,.05526950000000000000
37888,.05865630000000000000
39936,.06202170000000000000
Run Code Online (Sandbox Code Playgroud) 我正在尝试在Linux内核空间中禁用/启用缓存.
我使用的代码是
__asm__ __volatile__(
"pushw %eax\n\t" /*line 646*/
"movl %cr0,%eax\n\t"
"orl $0x40000000,%eax\n\t"
"movl %eax,%cr0\n\t"
"wbinvd\n\t"
"pop %eax");
Run Code Online (Sandbox Code Playgroud)
编译后,我得到如下错误信息:
memory.c: Assembler messages:
memory.c:645: Error: operand type mismatch for `push'
memory.c:646: Error: unsupported for `mov'
memory.c:648: Error: unsupported for `mov'
memory.c:650: Error: operand type mismatch for `pop'
make[4]: *** [memory.o] Error 1
Run Code Online (Sandbox Code Playgroud)
我的机器是Intel(R)Xeon(R)CPU E5-1650 v2 @ 3.50GHz.64位机器.
任何人都可以帮我指出哪个部分不正确以及我如何解决它?
我猜这是因为指令与寄存器的不匹配.但我对如何解决它感到困惑.:(
提前致谢!
我正在尝试在Xen中禁用我的机器Intel(R)Xeon(R)CPU E5-1650 v2 @ 3.50GHz的所有级别的缓存.我编写了一个工具来调用以下汇编代码来禁用/启用缓存并显示CR0寄存器的值.
case XENMEM_disable_cache:
__asm__ __volatile__(
"pushq %%rax\n\t"
"movq %%cr0,%%rax\n\t"
"orq $0x40000000,%%rax\n\t"
"movq %%rax,%%cr0\n\t"
"movq %%cr0, %0\n\t"
"wbinvd\n\t"
"popq %%rax"
: "=r"(cr0)
:
:);
// gdprintk(XENLOG_WARNING, "gdprintk:XENMEM_disable_cache disable cache!
// TODO IMPLEMENT\n");
printk("<1>printk: disable cache! cr0=%#018lx\n", cr0);
rc = 0;
break;
case XENMEM_enable_cache:
__asm__ __volatile__(
"pushq %%rax\n\t"
"movq %%cr0,%%rax\n\t"
"andq $0xffffffffbfffffff,%%rax\n\t" /*~0x4000000*/
"movq %%rax,%%cr0\n\t"
"movq %%cr0, %0\n\t"
"popq %%rax"
: "=r"(cr0)
:
:);
printk("<1>printk: enable cache; cr0=%#018lx\n", cr0);
rc = 0;
break;
case XENMEM_show_cache:
__asm__ __volatile__(
"pushq …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,似乎 XXXXXX 要求生成随机字符来替换它。这里的XXXXXX是什么意思呢?这是 中的一些特殊保留符号吗sprintf?
sprintf(tempName, "/tmp/%s-XXXXXX", filename.c_str());
Run Code Online (Sandbox Code Playgroud) 在我的MIT OS课程(686)中,我发现了一些我不理解的代码。我想了解指令inb $0x64, %al的启动 / boot.S。我的理解是它正在从数据端口0x64读一个字节到AL,端口0x64是什么?正在测试哪个设备或机制忙?我对代码忙中的注释感到困惑吗?评论是什么意思,它指的是什么?
# Enable A20:
# For fascinating historical reasons (related to the fact that
# the earliest 8086-based PCs could only address 1MB of physical memory
# and subsequent 80286-based PCs wanted to retain maximum compatibility),
# physical address line 20 is tied to low when the machine boots.
# Obviously this a bit of a drag for us, especially when trying to …Run Code Online (Sandbox Code Playgroud) 在Xen代码./xen/include/asm-x86/config.h中,我看到内存布局代码是:
/*
137 * Meng: Xen-definitive guide: P81
138 * Memory layout:
139 * 0x0000000000000000 - 0x00007fffffffffff [128TB, 2^47 bytes, PML4:0-255]
140 * Guest-defined use (see below for compatibility mode guests).
141 * 0x0000800000000000 - 0xffff7fffffffffff [16EB]
142 * Inaccessible: current arch only supports 48-bit sign-extended VAs.
143 * 0xffff800000000000 - 0xffff803fffffffff [256GB, 2^38 bytes, PML4:256]
Run Code Online (Sandbox Code Playgroud)
我对PML4的简称非常困惑.我确实知道x86_64只使用64位中的48位.但PML4的缩写是什么?它可以帮助我理解它背后的数字.
谢谢!
我知道如何在Intel IvyBridge CPU上禁用所有三级缓存.我只需要为所有CPU将CR0寄存器的CD位设置为1.
但是,我想仅在Intel IvyBridget或SandyBridge CPU上禁用最后一级缓存(L3缓存),并继续在芯片缓存上使用L1和L2.
我之所以要做这个实验,是因为我想测试L3缓存的性能,并希望看到不使用L3缓存的效果.
任何人都可以给我一个指针或一些如何实现这一目标的见解?
我正在尝试在Linux 上的专用核心上运行程序.(我知道Jailhouse是一个很好的方法,但我必须使用现成的Linux.:-()
其他进程(例如中断处理程序,内核线程,服务进程)也可能偶尔在专用核心上运行.我想尽可能多地禁用这样的进程.为此,我需要首先确定可能在专用内核上运行的进程列表.
我的问题是:
是否有任何现有工具可用于跟踪在一段时间间隔内在特定核心上运行的PID或进程列表?
非常感谢您在这个问题上的时间和帮助!
我想监视最后一级缓存中的缓存请求编号.我写了一个Linux模块,根据这里的教程获取这些信息.
它可以编译和运行,但输出结果总是0.换句话说,当我使用时rdmsr,它总是给我edx = 0,eax = 0.我甚至尝试了教程中的演示代码,输出仍为0.
我坚持这个问题整整一个星期.谁能帮助我指出我在程序中犯的错误?
我知道有一些现有程序在做同样的事情,但我必须知道如何自己编写代码,因为我想在Xen管理程序中监视缓存请求.我不能在Xen中使用这些工具,除非我将这些工具合并到Xen的管理程序中,这似乎更有用.
/*
* Record the cache miss rate of Intel Sandybridge cpu
* To confirm the event is correctly set!
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
/*4 Performance Counters Selector for %ecx in insn wrmsr*/
#define PERFEVTSEL0 0x186
#define PERFEVTSEL1 0x187
#define PERFEVTSEL2 0x188
#define PERFEVTSEL3 0x189
/*4 MSR Performance Counter for the above selector*/
#define PMC0 …Run Code Online (Sandbox Code Playgroud) 我希望到grep中的所有关键字.h和.c文件的当前目录下./,但不包括两个目录./stubdom,并./dist在输出中.
我搜查,试过并测试了几个命令; 最后我认为一个shell工作:
find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -o -regex '.*\.\(h\|c\)$' -print | xargs grep map_foreign_range
Run Code Online (Sandbox Code Playgroud)
此shell正在查找所有.h和.c文件并排除./stubdom/和./dist路径:
find . -type d \( -path "./stubdom/*" -o -path "./dist/*" \) -prune -regex '.*\.\(h\|c\)$' -print | xargs grep map_foreign_range
Run Code Online (Sandbox Code Playgroud)
但是,上面的命令不起作用!
(我在正则表达式之前删除-o以获得AND操作!)
但是,我不太明白为什么会这样.我有几个问题:
\( -path "./stubdom/*" -o -path "./dist/*" \) 这是一个find的动作,但它是如何工作的?以及它为什么不是\( -path "./stubdom/*" -o -path "./dist/*" -o \)(我在最后添加另一个-o).
如果我把它放在-regex之前-type,它将打印出.o文件,这意味着-regex如果它放在之前它不起作用 …