c - Linux 内核 flush_write_buffers() 如何在 x86 上工作?

标签 c assembly linux-kernel x86 dma

以下代码来自 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/

相关文章:

c - 操作系统 : proc_pidinfo returns 0 for other user's processes

c - 将字符串插入二叉搜索树 C

c++ - 在 C++ 中观察汇编器中虚函数的后期绑定(bind)调用

c++ - MSVC 2013 : crash at addpd xmm6, xmmword ptr [rax+rbx*8]

c - 我的系统调用无法正常工作

c++ - CvIPL 定义

CFStringCreateWithCString 对于少于 10 个字符的字符串返回 null

assembly - x86-64 MOV r/m64,imm32 = io?

linux - .function() 和 .function().call 在 systemtap 中的区别

c - 填充 skb 中的 header 字段