在Raspberry Pi 3上禁用内核模块中的缓存



在Raspberry Pi 3B+(ARMv8(上,我如何禁用内核模块中的缓存(或使用其他方法(,以便在从内存地址读取时,不会缓存其值(及其所在的页面(?如果所有的内存读取都绕过缓存,这样即使地址内容在第一次读取之前就已经缓存好了,也会被忽略
换句话说,假设p是一个指向用kmalloc分配的内存的指针,我有下面的循环,

for (i=0;i<10;i++)
mem = p[i]

我的目标是确保所有地址都是直接从RAM读取的,而不是从缓存中读取的。

如果只是这里不应该强制缓存,而是允许缓存,那么可以使用非临时提示来实现这一点:

6.3.8非临时加载和存储对

ARMv8中的一个新概念是非时间性加载和存储。这些是执行一对寄存器值的读取或写入的LDNPSTNP指令。它们还向内存系统提供了一个提示,即缓存对这些数据没有用处。提示不会禁止内存系统活动,例如缓存地址、预加载或收集。但是,这表明缓存不太可能提高性能。典型的用例可能是流式数据,但请注意,有效使用这些指令需要特定于微体系结构。

来自《ARMv8-A程序员指南》

这两条指令的语法是

LDNP <Wt1>, <Xt2>, [<Xn|SP|{, #<imm>}]
LDNP <Xt1>, <Xt2>, [<Xn|SP|{, #<imm>}]

这些是寄存器对上的指令,但立即数也可以具有单个寄存器的宽度(然后简单地使用WZRXZR作为第二个寄存器(。正如描述所说,这里可能仍然使用了缓存。但是,可以直接从用户模式使用此方法。


从内核模块还可以选择将相应的内存区域标记为不可缓存。这通常用于内存映射的I/O设备,在这些设备中,应始终直接从内存获取当前值。这应该在MMU转换表中进行配置。对我来说,这似乎是适合您情况的最佳解决方案,但它需要一些MMU和寻呼机制的知识(因此我不想在这里进一步描述(。

最后,有可能停用整个缓存,但已经有一篇关于这一点及其后果的帖子:在ARMv8-a Linux上禁用CPU缓存(L1/L2(。

最新更新