问题描述
以下代码来自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处理器存在一个错误,其中可以通过对WC类型的位置进行更早的内存访问来对存储到UC类型的存储位置进行重新排序. x86内存一致性模型.解决方法是,可以在UC存储之前使用正确实现的内存序列化指令.在Pentium Pro处理器上,下列任何一项都可以完成工作:(1)cpuid
,(2)UC加载或(3)前缀为lock
的指令.
Linux内核中的flush_write_buffers
为此精确地使用了lock
前缀的指令.为此,cpuid
是最昂贵且不必要的. UC加载需要使用UC类型的内存位置,这通常不太方便.因此,可以选择使用lock
前缀的指令.
如函数名所示,它的目的是等待直到写入缓冲区(在这种情况下,也称为存储缓冲区)中所有未决的写入变为全局可观察到.缓存不受影响.
此错误仅影响Pentium Pro,必须使用CONFIG_X86_PPRO_FENCE
编译内核才能启用解决方法.但是,要确保在内核中应该使用该替代方法的所有地方都很难使用该替代方法,这是很困难的.而且,CONFIG_X86_PPRO_FENCE
不仅影响flush_write_buffers
的操作,而且影响其他构造,因此可能导致性能显着下降.最终,它从v4.16-rc7开始被从内核中丢弃. >
The following code is from include/asm-i386/io.h
, and it is invoked from dma_map_single()
. My understanding is that flush_write_buffers()
is supposed to flush CPU memory cache before mapping the memory for DMA. But how does this assembly code flush CPU cache?
static inline void flush_write_buffers(void)
{
__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory");
}
The Intel Pentium Pro processors had a bug wherein a store to a memory location of type UC may be reordered with earlier memory accesses to locations of type WC, which violates the x86 memory consistency model. As a workaround, a correctly implemented memory serializing instruction can be used just before the UC store. On the Pentium Pro processors, any the following would do the job: (1) cpuid
, (2) a UC load, or (3) a lock
-prefixed instruction.
The flush_write_buffers
in the Linux kernel uses a lock
-prefixed instruction for precisely this purpose. cpuid
is the most expensive and unnecessary for this purpose. A UC load requires a memory location of type UC, which is a little inconvenient in general. Hence, the choice of using a lock
-prefixed instruction.
As the name of the function indicates, the purpose of it is to wait until all pending writes in the write buffer (a.k.a. store buffer, in this context) become globally observable. The caches are not affected.
This bug only affects Pentium Pro and the kernel had to be compiled with CONFIG_X86_PPRO_FENCE
for the workaround to be enabled. It was difficult, though, to be sure that the workaround is used in all the places in the kernel where it's supposed to be used. Moreover, CONFIG_X86_PPRO_FENCE
didn't only affect the operation of flush_write_buffers
, but also other constructs, so it can cause significant performance degradation. Eventually, it was dropped from the kernel starting with v4.16-rc7.
这篇关于Linux内核flush_write_buffers()在x86上如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!