On 01/27/2015 08:53 AM, Ross Zwisler wrote: > Add support for the new pcommit (persistent commit) instruction. This > instruction was announced in the document "Intel Architecture > Instruction Set Extensions Programming Reference" with reference number > 319433-022. > > https://software.intel.com/sites/default/files/managed/0d/53/319433-022.pdf > > The pcommit instruction ensures that data that has been flushed from the > processor's cache hierarchy with clwb, clflushopt or clflush is accepted to > memory and is durable on the DIMM. The primary use case for this is > persistent > memory. > > This function shows how to properly use clwb/clflushopt/clflush and > pcommit with appropriate fencing: > > void flush_and_commit_buffer(void *vaddr, unsigned int size) > { > void *vend = vaddr + size - 1; > > for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size) > clwb(vaddr); > > /* Flush any possible final partial cacheline */ > clwb(vend); > > /* > * sfence to order clwb/clflushopt/clflush cache flushes > * mfence via mb() also works > */ > wmb(); > > /* pcommit and the required sfence for ordering */ > pcommit_sfence(); > } > > After this function completes the data pointed to by vaddr is has been > accepted to memory and will be durable if the vaddr points to > persistent memory. > > Pcommit must always be ordered by an mfence or sfence, so to help > simplify things we include both the pcommit and the required sfence in > the alternatives generated by pcommit_sfence(). The other option is to > keep them separated, but on platforms that don't support pcommit this > would then turn into: > > void flush_and_commit_buffer(void *vaddr, unsigned int size) > { > void *vend = vaddr + size - 1; > > for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size) > clwb(vaddr); > > /* Flush any possible final partial cacheline */ > clwb(vend); > > /* > * sfence to order clwb/clflushopt/clflush cache flushes > * mfence via mb() also works > */ > wmb(); > > nop(); /* from pcommit(), via alternatives */ > > /* > * sfence to order pcommit > * mfence via mb() also works > */ > wmb(); > } > > This is still correct, but now you've got two fences separated by only a > nop. With the commit and the fence together in pcommit_sfence() you > avoid the final unneeded fence.
Acked-by: H. Peter Anvin <[email protected]> -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

