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

Disabling cache in a kernel module on a Raspberry Pi 3?

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

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

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

如果只是不应该在此处强制缓存,而是允许缓存,您可以使用非时间提示来实现此目的:

6.3.8 Non-temporal load and store pair

A new concept in ARMv8 is the non-temporal load and store. These are the LDNP and STNP instructions that perform a read or write of a pair of register values. They also give a hint to the memory system that caching is not useful for this data. The hint does not prohibit memory system activity such as caching of the address, preload, or gathering. However, it indicates that caching is unlikely to increase performance. A typical use case might be streaming data, but take note that effective use of these instructions requires an approach specific to the microarchitecture.

From The Programmer’s Guide for ARMv8-A.

这两条指令的语法是

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

这些是关于寄存器对的指令,但是立即数也可以有单个寄存器的宽度(那么只需使用WZRXZR作为第二个寄存器)。正如描述所说,这里可能还是使用了缓存。但是,这个方法可以直接从用户模式使用。


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

最终有可能停用整个缓存,但是已经有关于此的 post 以及这里的后果: