参考:
https://danluu.com/clwb-pcommit/ (14年文档)
https://blog.csdn.net/maokelong95/article/details/81362837
https://zhuanlan.zhihu.com/p/135188922?utm_source=zhihu&utm_medium=social&utm_oi=620920856499720192
clflush: 把cache line刷回内存,并且让cache
line失效。只能串行执行。
clflushopt: 功能同clflush,但是不同缓存行可以并发执行。
clwb: 除了写回后不让cache line失效,其他同clflushopt。
pcommit: 把所有落在持久化内存区域的store持久化。(已弃用?)
ntstore: 绕过CPU
cache,直接写到内存。一般用于写完就不管的情况,可以防止污染cache。
把内容写回NVMM的一般步骤:
(addr);
clwb();
sfence(); // 已弃用?
PCOMMIT();
sfence*addr = balabala;
clflushopt一般用来flush一大段地址的缓存行,Linux内核中已经给出了对应的函数:
#define mb() asm volatile("mfence":::"memory")
static void clflush_cache_range_opt(void *vaddr, unsigned int size)
{
const unsigned long clflush_size = boot_cpu_data.x86_clflush_size;
void *p = (void *)((unsigned long)vaddr & ~(clflush_size - 1));
void *vend = vaddr + size;
if (p >= vend)
return;
for (; p < vend; p += clflush_size)
(p);
clflushopt}
/**
* clflush_cache_range - flush a cache range with clflush
* @vaddr: virtual start address
* @size: number of bytes to flush
*
* CLFLUSHOPT is an unordered instruction which needs fencing with MFENCE or
* SFENCE to avoid ordering issues.
*/
void clflush_cache_range(void *vaddr, unsigned int size)
{
();
mb(vaddr, size);
clflush_cache_range_opt();
mb}
(clflush_cache_range); EXPORT_SYMBOL_GPL