以下代码来自 include/asm-i386/io.h
,它是从 dma_map_single()
调用的.我的理解是flush_write_buffers()
应该在为 DMA 映射内存之前刷新 CPU 内存缓存。但是这个汇编代码是如何刷新 CPU 缓存的呢?
static inline void flush_write_buffers(void)
{
__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
}
最佳答案
Intel Pentium Pro 处理器存在一个错误,其中存储到 UC 类型的内存位置可能会与较早的对 WC 类型位置的内存访问进行重新排序,这违反了 x86 内存一致性模型。作为一种变通方法,可以在 UC 存储之前使用正确实现的内存序列化指令。在 Pentium Pro 处理器上,以下任何一项都可以完成这项工作: (1) cpuid
, (2) UC 负载,或 (3) lock
- 前缀指令。flush_write_buffers
在 Linux 内核中使用 lock
- 前缀指令正是为此目的。 cpuid
为此目的是最昂贵和不必要的。 UC 负载需要 UC 类型的内存位置,这通常有点不方便。因此,选择使用 lock
- 前缀指令。
正如函数名称所示,它的目的是等待直到写入缓冲区(在此上下文中也称为存储缓冲区)中的所有挂起写入变得全局可观察。缓存不受影响。
此错误仅影响 Pentium Pro,内核必须使用 CONFIG_X86_PPRO_FENCE
编译以启用解决方法。但是,很难确保在内核中所有应该使用它的地方都使用了该变通方法。此外,CONFIG_X86_PPRO_FENCE
不仅影响了flush_write_buffers
的运行,还有其他结构,因此它可能会导致性能显着下降。最终,它是 dropped从 v4.16-rc7 开始的内核。
关于c - Linux 内核 flush_write_buffers() 如何在 x86 上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59990276/