【问题标题】:Disabling cache in a kernel module on a Raspberry Pi 3?在 Raspberry Pi 3 的内核模块中禁用缓存?
【发布时间】:2020-07-19 21:49:00
【问题描述】:

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

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

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

【问题讨论】:

  • MMU 决定一个区域是否可缓存。您可以更改类型编码以使区域不可缓存。

标签: linux-kernel arm raspberry-pi3


【解决方案1】:

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

6.3.8 非临时加载和存储对

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

来自Programmer’s Guide for ARMv8-A。

这两条指令的语法是

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

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


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

终于有可能停用整个缓存,但这里已经有一篇关于此及其后果的帖子:Disable CPU caches (L1/L2) on ARMv8-A Linux。

【讨论】:

  • 谢谢。您知道 MMU 方法的任何参考/示例代码吗?我应该研究哪些功能?
  • 我现在想不出一个例子,但在ARM Cortex-A Programmer's Guide for ARMv8-A的第12.4章中有描述。不需要在 MMU 本身上做任何事情,只需要在操作系统创建的转换表上做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 2022-10-05
  • 1970-01-01
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多