Messages in this thread | | | Date | Wed, 11 Feb 2015 14:24:02 -0800 | From | "H. Peter Anvin" <> | Subject | Re: [PATCH v3 1/2] x86: Add support for the pcommit instruction |
| |
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 <hpa@linux.intel.com>
| |