Support new pmem flush and sync instructions for POWER
Subsystems (7)
v6 cover Support new pmem flush and sync instructions for POWER
This patch series enables the usage os new pmem flush and sync instructions on POWER architecture. POWER10 introduces two new variants of dcbf instructions (dcbstps and dcbfps) that can be used to write modified locations back to persistent storage. Additionally, POWER10 also introduce phwsync and plwsync which can be used to establish order of these writes to persistent storage.
This series exposes these instructions to the rest of the kernel. The existing dcbf and hwsync instructions in P8 and P9 are adequate to enable appropriate synchronization with OpenCAPI-hosted persistent storage. Hence the new instructions are added as a variant of the old ones that old hardware won't differentiate.
On POWER10, pmem devices will be represented by a different device tree compat strings. This ensures that older kernels won't initialize pmem devices on POWER10.
With this:
1) vPMEM continues to work since it is a volatile region. That doesn't need any flush instructions.
2) pmdk and other user applications get updated to use new instructions and updated packages are made available to all distributions
3) On newer hardware, the device will appear with a new compat string. Hence older distributions won't initialize pmem on newer hardware.
Changes from v5:
* Drop CONFIG_ARCH_MAP_SYNC_DISABLE and related changes
Changes from V4:
* Add namespace specific sychronous fault control.
Changes from V3:
* Add new compat string to be used for the device.
* Use arch_pmem_flush_barrier() in dm-writecache.
Aneesh Kumar K.V (8):
powerpc/pmem: Restrict papr_scm to P8 and above. powerpc/pmem: Add new instructions for persistent storage and sync powerpc/pmem: Add flush routines using new pmem store and sync
instruction
libnvdimm/nvdimm/flush: Allow architecture to override the flush
barrier
powerpc/pmem/of_pmem: Update of_pmem to use the new barrier
instruction.
powerpc/pmem: Avoid the barrier in flush routines powerpc/pmem: Add WARN_ONCE to catch the wrong usage of pmem flush
functions.
powerpc/pmem: Initialize pmem device on newer hardware
arch/powerpc/include/asm/cacheflush.h | 10 +++++ arch/powerpc/include/asm/ppc-opcode.h | 12 ++++++ arch/powerpc/lib/pmem.c | 46 +++++++++++++++++++++-- arch/powerpc/platforms/pseries/papr_scm.c | 14 +++++++ arch/powerpc/platforms/pseries/pmem.c | 6 +++ drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/of_pmem.c | 1 + drivers/nvdimm/region_devs.c | 8 ++-- include/asm-generic/cacheflush.h | 4 ++ 9 files changed, 94 insertions(+), 9 deletions(-)
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 1/8 powerpc/pmem: Restrict papr_scm to P8 and above.
The PAPR based virtualized persistent memory devices are only supported on POWER9 and above. In the followup patch, the kernel will switch the persistent memory cache flush functions to use a new dcbf variant instruction. The new instructions even though added in ISA 3.1 works even on P8 and P9 because these are implemented as a variant of existing dcbf and hwsync and on P8 and P9 behaves as such.
Considering these devices are only supported on P8 and above, update the driver to prevent a P7-compat guest from using persistent memory devices.
We don't update of_pmem driver with the same condition, because, on bare-metal, the firmware enables pmem support only on P9 and above. There the kernel depends on OPAL firmware to restrict exposing persistent memory related device tree entries on older hardware. of_pmem.ko is written without any arch dependency and we don't want to add ppc64 specific cpu feature check in of_pmem driver.
--- arch/powerpc/platforms/pseries/pmem.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/powerpc/platforms/pseries/pmem.c +6 -0
@@ -147,6 +147,12 @@ const struct of_device_id drc_pmem_match[] = {static int pseries_pmem_init (void ) { +/* +* Only supported on POWER8 and above. +*/ +if (!cpu_has_feature (CPU_FTR_ARCH_207S )) +return 0 ; + pmem_node =of_find_node_by_type (NULL ,"ibm,persistent-memory" );if (!pmem_node)return 0 ;
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 2/8 powerpc/pmem: Add new instructions for persistent storage and sync
In reply to Aneesh Kumar K.VPOWER10 introduces two new variants of dcbf instructions (dcbstps and dcbfps) that can be used to write modified locations back to persistent storage.
Additionally, POWER10 also introduce phwsync and plwsync which can be used to establish order of these writes to persistent storage.
This patch exposes these instructions to the rest of the kernel. The existing dcbf and hwsync instructions in P8 and P9 are adequate to enable appropriate synchronization with OpenCAPI-hosted persistent storage. Hence the new instructions are added as a variant of the old ones that old hardware won't differentiate.
--- arch/powerpc/include/asm/ppc-opcode.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/powerpc/include/asm/ppc-opcode.h +12 -0
@@ -219,6 +219,8 @@#define PPC_INST_STWCX 0x7c00012d#define PPC_INST_LWSYNC 0x7c2004ac#define PPC_INST_SYNC 0x7c0004ac +#define PPC_INST_PHWSYNC 0x7c8004ac +#define PPC_INST_PLWSYNC 0x7ca004ac#define PPC_INST_SYNC_MASK 0xfc0007fe#define PPC_INST_ISYNC 0x4c00012c#define PPC_INST_LXVD2X 0x7c000698
@@ -284,6 +286,8 @@#define PPC_INST_TABORT 0x7c00071d#define PPC_INST_TSR 0x7c0005dd +#define PPC_INST_DCBF 0x7c0000ac +#define PPC_INST_NAP 0x4c000364#define PPC_INST_SLEEP 0x4c0003a4#define PPC_INST_WINKLE 0x4c0003e4
@@ -532,6 +536,14 @@#define STBCIX (s,a,b) stringify_in_c(.long PPC_INST_STBCIX | \ __PPC_RS(s) | __PPC_RA(a) | __PPC_RB(b)) +#define PPC_DCBFPS (a, b) stringify_in_c(.long PPC_INST_DCBF | \ + ___PPC_RA(a) | ___PPC_RB(b) | (4 << 21)) +#define PPC_DCBSTPS (a, b) stringify_in_c(.long PPC_INST_DCBF | \ + ___PPC_RA(a) | ___PPC_RB(b) | (6 << 21)) + +#define PPC_PHWSYNC stringify_in_c(.long PPC_INST_PHWSYNC) +#define PPC_PLWSYNC stringify_in_c(.long PPC_INST_PLWSYNC) +/* * Define what the VSX XX1 form instructions will look like, then add * the 128 bit load store instructions based on that.
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 3/8 powerpc/pmem: Add flush routines using new pmem store and sync instruction
In reply to Aneesh Kumar K.VStart using dcbstps; phwsync; sequence for flushing persistent memory range. The new instructions are implemented as a variant of dcbf and hwsync and on P8 and P9 they will be executed as those instructions. We avoid using them on older hardware. This helps to avoid difficult to debug bugs.
--- arch/powerpc/include/asm/cacheflush.h | 1 + arch/powerpc/lib/pmem.c | 50 ++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/cacheflush.h +1 -0
@@ -6,6 +6,7 @@#include <linux/mm.h> #include <asm/cputable.h> +#include <asm/cpu_has_feature.h> #ifdef CONFIG_PPC_BOOK3S_64 /*
arch/powerpc/lib/pmem.c +46 -4
80 lines not on this page · raw message
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 4/8 libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
In reply to Aneesh Kumar K.VArchitectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by wmb()
Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
--- drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/asm-generic/cacheflush.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)
drivers/md/dm-writecache.c +1 -1
@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +arch_pmem_flush_barrier ();else ssd_commit_flushed (wc, wait_for_ios); }
drivers/nvdimm/region_devs.c +4 -4
@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +arch_pmem_flush_barrier ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));
include/asm-generic/cacheflush.h +4 -0
@@ -110,4 +110,8 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end) memcpy(dst, src, len)#endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif +#endif /* _ASM_GENERIC_CACHEFLUSH_H */
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
kernel test robot
build botRe: [PATCH v6 4/8] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
I love your patch! Yet something to improve:
Hi "Aneesh,
I love your patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on linux-nvdimm/libnvdimm-for-next v5.8-rc3 next-20200629] [cannot apply to scottwood/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Aneesh-Kumar-K-V/Support-new-pmem-flush-and-sync-instructions-for-POWER/20200629-223649 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: arc-allyesconfig (attached as .config) compiler: arc-elf-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arc
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>):
drivers/nvdimm/region_devs.c: In function 'generic_nvdimm_flush':
>> drivers/nvdimm/region_devs.c:1215:2: error: implicit declaration of function 'arch_pmem_flush_barrier' [-Werror=implicit-function-declaration]
1215 | arch_pmem_flush_barrier();
| ^~~~~~~~~~~~~~~~~~~~~~~cc1: some warnings being treated as errors
vim +/arch_pmem_flush_barrier +1215 drivers/nvdimm/region_devs.c
1178
1179 int nvdimm_flush(struct nd_region *nd_region, struct bio *bio)
1180 {
1181 int rc = 0;
1182
1183 if (!nd_region->flush)
1184 rc = generic_nvdimm_flush(nd_region);
1185 else {
1186 if (nd_region->flush(nd_region, bio))
1187 rc = -EIO;
1188 }
1189
1190 return rc;
1191 }
1192 /**
1193 * nvdimm_flush - flush any posted write queues between the cpu and pmem media
1194 * @nd_region: blk or interleaved pmem region
1195 */
1196 int generic_nvdimm_flush(struct nd_region *nd_region)
1197 {
1198 struct nd_region_data *ndrd = dev_get_drvdata(&nd_region->dev);
1199 int i, idx;
1200
1201 /*
1202 * Try to encourage some diversity in flush hint addresses
1203 * across cpus assuming a limited number of flush hints.
1204 */
1205 idx = this_cpu_read(flush_idx);
1206 idx = this_cpu_add_return(flush_idx, hash_32(current->pid + idx, 8));
1207
1208 /*
1209 * The first arch_pmem_flush_barrier() is needed to 'sfence' all
1210 * previous writes such that they are architecturally visible for
1211 * the platform buffer flush. Note that we've already arranged for pmem
1212 * writes to avoid the cache via memcpy_flushcache(). The final
1213 * wmb() ensures ordering for the NVDIMM flush write.
1214 */
> 1215 arch_pmem_flush_barrier();
1216 for (i = 0; i < nd_region->ndr_mappings; i++)
1217 if (ndrd_get_flush_wpq(ndrd, i, 0))
1218 writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));
1219 wmb();
1220
1221 return 0;
1222 }
1223 EXPORT_SYMBOL_GPL(nvdimm_flush);
1224
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Re: [PATCH v6 4/8] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 24 lines · kernel test robot
Hi "Aneesh,
I love your patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on linux-nvdimm/libnvdimm-for-next v5.8-rc3 next-20200629] [cannot apply to scottwood/next]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]url: https://github.com/0day-ci/linux/commits/Aneesh-Kumar-K-V/Support-new-pmem-flush-and-sync-instructions-for-POWER/20200629-223649 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: arc-allyesconfig (attached as .config) compiler: arc-elf-gcc (GCC) 9.3.0reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arcIf you fix the issue, kindly add following tag as appropriate
Reported-by kernel test robot <[email protected]>
Quoted 7 lines
All errors (new ones prefixed by >>):
drivers/nvdimm/region_devs.c: In function 'generic_nvdimm_flush':Quoted 1 line
Quoted 1 line
drivers/nvdimm/region_devs.c:1215:2: error: implicit declaration of function 'arch_pmem_flush_barrier' [-Werror=implicit-function-declaration]1215 | arch_pmem_flush_barrier(); | ^~~~~~~~~~~~~~~~~~~~~~~cc1: some warnings being treated as errors
Ok let's move the back to include/linux/libnvdimm.h. Not all arch include asm-generic/cacheflush.h
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
kernel test robot
build botRe: [PATCH v6 4/8] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
In reply to Aneesh Kumar K.VI love your patch! Yet something to improve:
Hi "Aneesh,
I love your patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on linux-nvdimm/libnvdimm-for-next v5.8-rc3 next-20200629] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Aneesh-Kumar-K-V/Support-new-pmem-flush-and-sync-instructions-for-POWER/20200629-223649 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: mips-allyesconfig (attached as .config) compiler: mips-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>):
drivers/md/dm-writecache.c: In function 'writecache_commit_flushed':
>> drivers/md/dm-writecache.c:539:3: error: implicit declaration of function 'arch_pmem_flush_barrier' [-Werror=implicit-function-declaration]
539 | arch_pmem_flush_barrier();
| ^~~~~~~~~~~~~~~~~~~~~~~cc1: some warnings being treated as errors
vim +/arch_pmem_flush_barrier +539 drivers/md/dm-writecache.c
535
536 static void writecache_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
537 {
538 if (WC_MODE_PMEM(wc))
> 539 arch_pmem_flush_barrier();
540 else
541 ssd_commit_flushed(wc, wait_for_ios);
542 }
543
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
PATCH 1/1 libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
In reply to Aneesh Kumar K.VArchitectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by wmb()
Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
--- drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/linux/libnvdimm.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)
drivers/md/dm-writecache.c +1 -1
@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +arch_pmem_flush_barrier ();else ssd_commit_flushed (wc, wait_for_ios); }
drivers/nvdimm/region_devs.c +4 -4
@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +arch_pmem_flush_barrier ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));
include/linux/libnvdimm.h +4 -0
@@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size) }#endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif +#endif /* __LIBNVDIMM_H__ */
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 59 lines · Aneesh Kumar K.V
Architectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by
wmb()Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/linux/libnvdimm.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)drivers/md/dm-writecache.c +1
-1@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +arch_pmem_flush_barrier ();else ssd_commit_flushed (wc, wait_for_ios); }drivers/nvdimm/region_devs.c +4
-4@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +arch_pmem_flush_barrier ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));include/linux/libnvdimm.h +0
-0
include/linux/libnvdimm.h static inline void arch_invalidate_pmem(void *addr, size_t size) · line 291
Quoted 6 lines
include/linux/libnvdimm.h +3
-0@@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size) }#endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif
I think it is out of place to define this in libnvdimm.h and it is odd to give it such a long name. The other pmem api helpers like arch_wb_cache_pmem() and arch_invalidate_pmem() are function calls for libnvdimm driver operations, this barrier is just an instruction and is closer to wmb() than the pmem api routine.
Since it is a store fence for pmem, so let's just call it pmem_wmb() and define the generic version in include/linux/compiler.h. It should probably also be documented alongside dma_wmb() in Documentation/memory-barriers.txt about why code would use it over wmb(), and why a symmetric pmem_rmb() is not needed.
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 74 lines · Dan Williams
Quoted 59 lines · Aneesh Kumar K.V
Architectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by
wmb()Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/linux/libnvdimm.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)drivers/md/dm-writecache.c +1
-1@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +arch_pmem_flush_barrier ();else ssd_commit_flushed (wc, wait_for_ios); }drivers/nvdimm/region_devs.c +4
-4@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +arch_pmem_flush_barrier ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));include/linux/libnvdimm.h +0
-0include/linux/libnvdimm.h static inline void arch_invalidate_pmem(void *addr, size_t size) · line 291
Quoted 6 lines
include/linux/libnvdimm.h +3
-0@@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size) }#endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif I think it is out of place to define this in
libnvdimm.hand it is odd to give it such a long name. The other pmem api helpers likearch_wb_cache_pmem()andarch_invalidate_pmem()are function calls for libnvdimm driver operations, this barrier is just an instruction and is closer towmb()than the pmem api routine.
Quoted 5 lines
Since it is a store fence for pmem, so let's just call it
pmem_wmb()and define the generic version ininclude/linux/compiler.h. It should probably also be documented alongsidedma_wmb()inDocumentation/memory-barriers.txtabout why code would use it overwmb(), and why a symmetricpmem_rmb()is not needed.
How about the below? I used pmem_barrier() instead of pmem_wmb(). I guess we wanted this to order() any data access not jus the following stores to persistent storage? W.r.t why a symmetric pmem_rmb() is not needed I was not sure how to explain that. Are you suggesting to explain why a read/load from persistent storage don't want to wait for pmem_barrier() ?
modified Documentation/memory-barriers.txt
@@ -1935,6 +1935,16 @@ There are some more advanced barrier functions:
relaxed I/O accessors and the Documentation/DMA-API.txt file for more information on consistent memory.
+ (*) pmem_barrier();
+
+ These are for use with persistent memory to esure the ordering of stores
+ to persistent memory region.
+
+ For example, after a non temporal write to persistent storage we use pmem_barrier() + to ensures that stores have updated the persistent storage before + any data access or data transfer caused by subsequent instructions is initiated.
+
===============================
IMPLICIT KERNEL MEMORY BARRIERS
modified arch/powerpc/include/asm/barrier.h
@@ -97,6 +97,19 @@ do { \
#define barrier_nospec()
#endif /* CONFIG_PPC_BARRIER_NOSPEC */
+/*
+ * pmem_barrier() ensures that all stores for which the modification
+ * are written to persistent storage by preceding dcbfps/dcbstps
+ * instructions have updated persistent storage before any data
+ * access or data transfer caused by subsequent instructions is
+ * initiated.
+ */
+#define pmem_barrier pmem_barrier
+static inline void pmem_barrier(void)
+{
+ asm volatile(PPC_PHWSYNC ::: "memory");
+}
+
#include <asm-generic/barrier.h>
#endif /* _ASM_POWERPC_BARRIER_H */
modified include/asm-generic/barrier.h
@@ -257,5 +257,16 @@ do { \
})
#endif
+/*
+ * pmem_barrier() ensures that all stores for which the modification
+ * are written to persistent storage by preceding instructions have
+ * updated persistent storage before any data access or data transfer
+ * caused by subsequent instructions is
+ * initiated.
+ */
+#ifndef pmem_barrier
+#define pmem_barrier wmb()
+#endif
+
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_GENERIC_BARRIER_H */
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 77 lines · Aneesh Kumar K.V
Quoted 74 lines · Dan Williams
Quoted 59 lines · Aneesh Kumar K.V
Architectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by
wmb()Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/linux/libnvdimm.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)drivers/md/dm-writecache.c +1
-1@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +arch_pmem_flush_barrier ();else ssd_commit_flushed (wc, wait_for_ios); }drivers/nvdimm/region_devs.c +4
-4@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +arch_pmem_flush_barrier ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));include/linux/libnvdimm.h +0
-0include/linux/libnvdimm.h static inline void arch_invalidate_pmem(void *addr, size_t size) · line 291
Quoted 6 lines
include/linux/libnvdimm.h +3
-0@@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size) }#endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif I think it is out of place to define this in
libnvdimm.hand it is odd to give it such a long name. The other pmem api helpers likearch_wb_cache_pmem()andarch_invalidate_pmem()are function calls for libnvdimm driver operations, this barrier is just an instruction and is closer towmb()than the pmem api routine.
Quoted 7 lines
Quoted 5 lines
Since it is a store fence for pmem, so let's just call it
pmem_wmb()and define the generic version ininclude/linux/compiler.h. It should probably also be documented alongsidedma_wmb()inDocumentation/memory-barriers.txtabout why code would use it overwmb(), and why a symmetricpmem_rmb()is not needed.How about the below? I used
pmem_barrier()instead ofpmem_wmb().
Why? A barrier() is a bi-directional ordering mechanic for reads and writes, and the proposed semantics mechanism only orders writes + persistence. Otherwise the default fallback to wmb() on archs that don't override it does not make sense.
Quoted 3 lines
I
guess we wanted this toorder()any data access not jus the following stores to persistent storage?
Why?
Quoted 4 lines
W.r.t why a symmetric
pmem_rmb()is not
needed I was not sure how to explain that. Are you suggesting to explain why a read/load from persistent storage don't want to wait forpmem_barrier()?
I would expect that the explanation is that a typical rmb() is sufficient and that there is nothing pmem specific semantic for read ordering for pmem vs normal read-barrier semantics.
Review There are some more advanced barrier functions: · line 1941
Quoted 10 lines
modified
Documentation/memory-barriers.txt(quoted diff) +4
-0@@ -1935,6 +1935,16 @@ There are some more advanced barrier functions: relaxed I/O accessors and the Documentation/DMA-API.txt file for more information on consistent memory. + (*) pmem_barrier(); + + These are for use with persistent memory to esure the ordering of stores + to persistent memory region.
If it was just ordering I would expect a typical wmb() to be sufficient, why is the pmem-specific instruction needed? I thought it was handshaking with hardware to ensure acceptance into a persistence domain *in addition* to ordering the stores.
Review There are some more advanced barrier functions: · line 1944
Quoted 3 lines
(quoted diff) +3
-0+ For example, after a non temporal write to persistent storage we use pmem_barrier() + to ensures that stores have updated the persistent storage before + any data access or data transfer caused by subsequent instructions is initiated.
Isn't the ordering aspect is irrelevant relative to traditional wmb()? For example if you used the wrong sync instruction the store ordering will still be correct it would just not persist at the same time as barrier completes. Or am I misunderstanding how these new instructions are distinct?
Quoted 34 lines
(quoted diff) +1
-0+ =============================== IMPLICIT KERNEL MEMORY BARRIERSmodified
arch/powerpc/include/asm/barrier.h(quoted diff) +13
-0@@ -97,6 +97,19 @@ do { \ #define barrier_nospec() #endif /* CONFIG_PPC_BARRIER_NOSPEC */ +/* + * pmem_barrier() ensures that all stores for which the modification + * are written to persistent storage by preceding dcbfps/dcbstps + * instructions have updated persistent storage before any data + * access or data transfer caused by subsequent instructions is + * initiated. + */ +#define pmem_barrier pmem_barrier +static inline void pmem_barrier(void) +{ + asm volatile(PPC_PHWSYNC ::: "memory"); +} + #include <asm-generic/barrier.h> #endif /* _ASM_POWERPC_BARRIER_H */modified
include/asm-generic/barrier.h(quoted diff) +3
-0@@ -257,5 +257,16 @@ do { \ }) #endif +/* + * pmem_barrier() ensures that all stores for which the modification + * are written to persistent storage by preceding instructions have
Review do { \ · line 272
Quoted 10 lines
(quoted diff) +8
-0+ * updated persistent storage before any data access or data transfer + * caused by subsequent instructions is + * initiated. + */ +#ifndef pmem_barrier +#define pmem_barrier wmb() +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_GENERIC_BARRIER_H */
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 127 lines · Dan Williams
Quoted 77 lines · Aneesh Kumar K.V
Quoted 74 lines · Dan Williams
Quoted 59 lines · Aneesh Kumar K.V
Architectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by
wmb()Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
Signed-off-by Aneesh Kumar K.V <[email protected]>--- drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/linux/libnvdimm.h | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-)drivers/md/dm-writecache.c +1
-1@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +arch_pmem_flush_barrier ();else ssd_commit_flushed (wc, wait_for_ios); }drivers/nvdimm/region_devs.c +4
-4@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +arch_pmem_flush_barrier ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));include/linux/libnvdimm.h +0
-0include/linux/libnvdimm.h static inline void arch_invalidate_pmem(void *addr, size_t size) · line 291
Quoted 6 lines
include/linux/libnvdimm.h +3
-0@@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size) }#endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif I think it is out of place to define this in
libnvdimm.hand it is odd to give it such a long name. The other pmem api helpers likearch_wb_cache_pmem()andarch_invalidate_pmem()are function calls for libnvdimm driver operations, this barrier is just an instruction and is closer towmb()than the pmem api routine.Quoted 7 lines
Quoted 5 lines
Since it is a store fence for pmem, so let's just call it
pmem_wmb()and define the generic version ininclude/linux/compiler.h. It should probably also be documented alongsidedma_wmb()inDocumentation/memory-barriers.txtabout why code would use it overwmb(), and why a symmetricpmem_rmb()is not needed.How about the below? I used
pmem_barrier()instead ofpmem_wmb().Why? A
barrier()is a bi-directional ordering mechanic for reads and writes, and the proposed semantics mechanism only orders writes + persistence. Otherwise the default fallback towmb()on archs that don't override it does not make sense.Quoted 3 lines
I
guess we wanted this toorder()any data access not jus the following stores to persistent storage?Why?
Quoted 4 lines
W.r.t why a symmetric
pmem_rmb()is not
needed I was not sure how to explain that. Are you suggesting to explain why a read/load from persistent storage don't want to wait forpmem_barrier()?I would expect that the explanation is that a typical
rmb()is sufficient and that there is nothing pmem specific semantic for read ordering for pmem vs normal read-barrier semantics.Review There are some more advanced barrier functions: · line 1941
Quoted 10 lines
modified
Documentation/memory-barriers.txt(quoted diff) +4
-0@@ -1935,6 +1935,16 @@ There are some more advanced barrier functions: relaxed I/O accessors and the Documentation/DMA-API.txt file for more information on consistent memory. + (*) pmem_barrier(); + + These are for use with persistent memory to esure the ordering of stores + to persistent memory region.If it was just ordering I would expect a typical
wmb()to be sufficient, why is the pmem-specific instruction needed? I thought it was handshaking with hardware to ensure acceptance into a persistence domain *in addition* to ordering the stores.Review There are some more advanced barrier functions: · line 1944
Quoted 3 lines
(quoted diff) +3
-0+ For example, after a non temporal write to persistent storage we use pmem_barrier() + to ensures that stores have updated the persistent storage before + any data access or data transfer caused by subsequent instructions is initiated.
Quoted 6 lines
Isn't the ordering aspect is irrelevant relative to traditional
wmb()? For example if you used the wrong sync instruction the store ordering will still be correct it would just not persist at the same time as barrier completes. Or am I misunderstanding how these new instructions are distinct?
That is correct.
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 111 lines · Aneesh Kumar K.V
Quoted 110 lines · Dan Williams
Quoted 84 lines · Aneesh Kumar K.V
Quoted 81 lines · Dan Williams
Quoted 65 lines · Aneesh Kumar K.V
Architectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by
wmb()Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
Signed-off-by Aneesh Kumar K.V <[email protected]>---
drivers/md/dm-writecache.c | 2 +-
drivers/nvdimm/region_devs.c| 8 ++++----
include/linux/libnvdimm.h | 4 ++++3 files changed, 9 insertions(+), 5 deletions(-)drivers/md/dm-writecache.c +1
-1@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc) static void writecache_commit_flushed(struct dm_writecache *wc, bool wait_for_ios) { if (WC_MODE_PMEM(wc)) - wmb(); + arch_pmem_flush_barrier();else
ssd_commit_flushed(wc, wait_for_ios); }drivers/nvdimm/region_devs.c +0
-0@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region)idx = this_cpu_add_return(flush_idx, hash_32(current->pid
+ idx, 8));/*
- * The firstwmb()is needed to 'sfence' all previous writes - * such that they are architecturally visible for the platform - * buffer flush. Note that we've already arranged for pmem + * The firstarch_pmem_flush_barrier()is needed to 'sfence' all
+ * previous writes such that they are architecturally visible for
+ * the platform buffer flush. Note that we've already arranged for pmem
* writes to avoid the cache via memcpy_flushcache(). The final
*wmb()ensures ordering for the NVDIMM flush write. */
-wmb();
+arch_pmem_flush_barrier();
for (i = 0; i <nd_region->ndr_mappings; i++)
if (ndrd_get_flush_wpq(ndrd, i, 0))writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));include/linux/libnvdimm.h +0
-0include/linux/libnvdimm.h static inline void arch_invalidate_pmem(void · line 292
Quoted 7 lines
include/linux/libnvdimm.h +3
-0@@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size) } #endif +#ifndef arch_pmem_flush_barrier +#define arch_pmem_flush_barrier () wmb() +#endif I think it is out of place to define this in
libnvdimm.hand it is odd to give it such a long name. The other pmem api helpers likearch_wb_cache_pmem()andarch_invalidate_pmem()are function calls for libnvdimm driver operations, this barrier is just an instruction and is closer towmb()than the pmem api routine.Quoted 7 lines
Quoted 5 lines
Since it is a store fence for pmem, so let's just call it
pmem_wmb()and define the generic version ininclude/linux/compiler.h. It should probably also be documented alongsidedma_wmb()inDocumentation/memory-barriers.txtabout why code would use it overwmb(), and why a symmetricpmem_rmb()is not needed.How about the below? I used
pmem_barrier()instead ofpmem_wmb().Why? A
barrier()is a bi-directional ordering mechanic for reads and writes, and the proposed semantics mechanism only orders writes + persistence. Otherwise the default fallback towmb()on archs that don't override it does not make sense.Quoted 3 lines
I
guess we wanted this toorder()any data access not jus the following stores to persistent storage?Why?
Quoted 4 lines
W.r.t why a symmetric
pmem_rmb()is not
needed I was not sure how to explain that. Are you suggesting to explain why a read/load from persistent storage don't want to wait forpmem_barrier()?
Quoted 4 lines
Quoted 4 lines
I would expect that the explanation is that a typical
rmb()is sufficient and that there is nothing pmem specific semantic for read ordering for pmem vs normal read-barrier semantics.
Should that be rmb()? A smp_rmb() would suffice right?
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
In reply to Aneesh Kumar K.VUpdate patch.
From 1e6aa6c4182e14ec5d6bf878ae44c3f69ebff745 Mon Sep 17 00:00:00 2001
From: "Aneesh Kumar K.V" <[email protected]>
Date: Tue, 12 May 2020 20:58:33 +0530
Subject: [PATCH] libnvdimm/nvdimm/flush: Allow architecture to override the
flush barrier
Architectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by wmb()
Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
--- Documentation/memory-barriers.txt | 14 ++++++++++++++ drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/asm-generic/barrier.h | 10 ++++++++++ 4 files changed, 29 insertions(+), 5 deletions(-)
Documentation/memory-barriers.txt +14 -0
@@ -1935,6 +1935,20 @@ There are some more advanced barrier functions: relaxed I/O accessors and the Documentation/DMA-API.txt file for more information on consistent memory. + (*) pmem_wmb(); + + This is for use with persistent memory to ensure that stores for which + modifications are written to persistent storage have updated the persistent + storage. + + For example, after a non-temporal write to pmem region, we use pmem_wmb() + to ensures that stores have updated the persistent storage. This ensures + that stores have updated persistent storage before any data access or + data transfer caused by subsequent instructions is initiated. This is + in addition to the ordering done by wmb(). + + For load from persistent memory, existing read memory barriers are sufficient + to ensure read ordering. =============================== IMPLICIT KERNEL MEMORY BARRIERS
drivers/md/dm-writecache.c +1 -1
@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +pmem_wmb ();else ssd_commit_flushed (wc, wait_for_ios); }
drivers/nvdimm/region_devs.c +4 -4
@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all +* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +pmem_wmb ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));
include/asm-generic/barrier.h +10 -0
@@ -257,5 +257,15 @@ do { \ })#endif +/* +* pmem_barrier() ensures that all stores for which the modification +* are written to persistent storage by preceding instructions have +* updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +#ifndef pmem_wmb +#define pmem_wmb () wmb() +#endif +#endif /* !__ASSEMBLY__ */ #endif /* __ASM_GENERIC_BARRIER_H */
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Dan Williams
Reviewed-byRe: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
Quoted 17 lines · Aneesh Kumar K.V
Update patch.
From
1e6aa6c4182e14ec5d6bf878ae44c3f69ebff745Mon Sep 17 00:00:00 2001
From: "Aneesh Kumar K.V" <[email protected]>
Date: Tue, 12 May 2020 20:58:33 +0530
Subject: [PATCH] libnvdimm/nvdimm/flush: Allow architecture to override the
flush barrierArchitectures like ppc64 provide persistent memory specific barriers that will ensure that all stores for which the modifications are written to persistent storage by preceding dcbfps and dcbstps instructions have updated persistent storage before any data access or data transfer caused by subsequent instructions is initiated. This is in addition to the ordering done by
wmb()
Quoted 3 lines
Update nvdimm core such that architecture can use barriers other than wmb to ensure all previous writes are architecturally visible for the platform buffer flush.
Looks good, after a few minor fixups below you can add:
I'm expecting that these will be merged through the powerpc tree since they mostly impact powerpc with only minor touches to libnvdimm.
Quoted 13 lines
Signed-off-by Aneesh Kumar K.V <[email protected]>--- Documentation/memory-barriers.txt | 14 ++++++++++++++ drivers/md/dm-writecache.c | 2 +- drivers/nvdimm/region_devs.c | 8 ++++---- include/asm-generic/barrier.h | 10 ++++++++++ 4 files changed, 29 insertions(+), 5 deletions(-)Documentation/memory-barriers.txt +0
-0
Documentation/memory-barriers.txt There are some more advanced barrier functions: · line 1942
Quoted 8 lines
Documentation/memory-barriers.txt +5
-0@@ -1935,6 +1935,20 @@ There are some more advanced barrier functions: relaxed I/O accessors and the Documentation/DMA-API.txt file for more information on consistent memory. + (*) pmem_wmb(); + + This is for use with persistent memory to ensure that stores for which + modifications are written to persistent storage have updated the persistent + storage.
I think this should be:
s/updated the persistent storage/reached a platform durability domain/
Documentation/memory-barriers.txt There are some more advanced barrier functions: · line 1945
Quoted 3 lines
Documentation/memory-barriers.txt +3
-0+ + For example, after a non-temporal write to pmem region, we use pmem_wmb() + to ensures that stores have updated the persistent storage. This ensures
s/ensures/ensure/
...and the same comment about "persistent storage" because pmem_wmb() as implemented on x86 does not guarantee that the writes have reached storage it ensures that writes have reached buffers / queues that are within the ADR (platform persistence / durability) domain.
Quoted 27 lines
Documentation/memory-barriers.txt +6
-0+ that stores have updated persistent storage before any data access or + data transfer caused by subsequent instructions is initiated. This is + in addition to the ordering done by wmb(). + + For load from persistent memory, existing read memory barriers are sufficient + to ensure read ordering. =============================== IMPLICIT KERNEL MEMORY BARRIERSdrivers/md/dm-writecache.c +1
-1@@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)static void writecache_commit_flushed (struct dm_writecache *wc,bool wait_for_ios) {if (WC_MODE_PMEM (wc)) -wmb (); +pmem_wmb ();else ssd_commit_flushed (wc, wait_for_ios); }drivers/nvdimm/region_devs.c +0
-0
drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1209
Quoted 7 lines
drivers/nvdimm/region_devs.c +1
-3@@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* -* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem +* The first arch_pmem_flush_barrier() is needed to 'sfence' all
One missed arch_pmem_flush_barrier() rename.
Quoted 15 lines
drivers/nvdimm/region_devs.c +3
-1+* previous writes such that they are architecturally visible for +* the platform buffer flush. Note that we've already arranged for pmem * writes to avoid the cache via memcpy_flushcache(). The final * wmb() ensures ordering for the NVDIMM flush write. */ -wmb (); +pmem_wmb ();for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx));include/asm-generic/barrier.h +0
-0
include/asm-generic/barrier.h do { \ · line 261
Quoted 5 lines
include/asm-generic/barrier.h +2
-0@@ -257,5 +257,15 @@ do { \ })#endif +/* +* pmem_barrier() ensures that all stores for which the modification
One missed pmem_barrier() conversion.
Quoted 11 lines
include/asm-generic/barrier.h +8
-1+* are written to persistent storage by preceding instructions have +* updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +#ifndef pmem_wmb +#define pmem_wmb () wmb() +#endif +#endif /* !__ASSEMBLY__ */ #endif /* __ASM_GENERIC_BARRIER_H */ --
Quoted 2 lines
2.26.2
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 5/8 powerpc/pmem/of_pmem: Update of_pmem to use the new barrier instruction.
In reply to Aneesh Kumar K.Vof_pmem on POWER10 can now use phwsync instead of hwsync to ensure all previous writes are architecturally visible for the platform buffer flush.
--- arch/powerpc/include/asm/cacheflush.h | 7 +++++++ 1 file changed, 7 insertions(+)
arch/powerpc/include/asm/cacheflush.h +7 -0
@@ -98,6 +98,13 @@ static inline void invalidate_dcache_range(unsigned long start,mb ();/* sync */ } +#define arch_pmem_flush_barrier arch_pmem_flush_barrier +static inline void arch_pmem_flush_barrier (void ) +{ +if (cpu_has_feature (CPU_FTR_ARCH_207S )) + asm volatile(PPC_PHWSYNC ::: "memory"); +} +#include <asm-generic/cacheflush.h> #endif /* _ASM_POWERPC_CACHEFLUSH_H */
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 5/8] powerpc/pmem/of_pmem: Update of_pmem to use the new barrier instruction.
Quoted 15 lines · Aneesh Kumar K.V
of_pmemon POWER10 can now use phwsync instead of hwsync to ensure all previous writes are architecturally visible for the platform buffer flush.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/include/asm/cacheflush.h | 7 +++++++ 1 file changed, 7 insertions(+)arch/powerpc/include/asm/cacheflush.h +0
-0
arch/powerpc/include/asm/cacheflush.h static inline void invalidate_dcache_range(unsigned long start, · line 105
Quoted 8 lines
arch/powerpc/include/asm/cacheflush.h +5
-0@@ -98,6 +98,13 @@ static inline void invalidate_dcache_range(unsigned long start,mb ();/* sync */ } +#define arch_pmem_flush_barrier arch_pmem_flush_barrier +static inline void arch_pmem_flush_barrier (void ) +{ +if (cpu_has_feature (CPU_FTR_ARCH_207S )) + asm volatile(PPC_PHWSYNC ::: "memory");
Shouldn't this fallback to a compatible store-fence in an else statement?
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Re: [PATCH v6 5/8] powerpc/pmem/of_pmem: Update of_pmem to use the new barrier instruction.
Quoted 20 lines · Dan Williams
Quoted 18 lines · Aneesh Kumar K.V
of_pmemon POWER10 can now use phwsync instead of hwsync to ensure all previous writes are architecturally visible for the platform buffer flush.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/include/asm/cacheflush.h | 7 +++++++ 1 file changed, 7 insertions(+)arch/powerpc/include/asm/cacheflush.h +0
-0@@ -98,6 +98,13 @@ static inline void invalidate_dcache_range(unsigned long start,mb ();/* sync */ }
Quoted 7 lines
arch/powerpc/include/asm/cacheflush.h static inline void invalidate_dcache_range(unsigned long start, · line 105
Quoted 5 lines
arch/powerpc/include/asm/cacheflush.h +5
-0+#define arch_pmem_flush_barrier arch_pmem_flush_barrier +static inline void arch_pmem_flush_barrier (void ) +{ +if (cpu_has_feature (CPU_FTR_ARCH_207S )) + asm volatile(PPC_PHWSYNC ::: "memory");Shouldn't this fallback to a compatible store-fence in an else statement?
The idea was to avoid calling this on anything else. We ensure that by making sure that pmem devices are not initialized on systems without that cpu feature. Patch 1 does that. Also, the last patch adds a WARN_ON() to catch the usage of this outside pmem devices and on systems without that cpu feature.
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 5/8] powerpc/pmem/of_pmem: Update of_pmem to use the new barrier instruction.
Quoted 31 lines · Aneesh Kumar K.V
Quoted 20 lines · Dan Williams
Quoted 18 lines · Aneesh Kumar K.V
of_pmemon POWER10 can now use phwsync instead of hwsync to ensure all previous writes are architecturally visible for the platform buffer flush.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/include/asm/cacheflush.h | 7 +++++++ 1 file changed, 7 insertions(+)arch/powerpc/include/asm/cacheflush.h +0
-0@@ -98,6 +98,13 @@ static inline void invalidate_dcache_range(unsigned long start,mb ();/* sync */ }Quoted 7 lines
arch/powerpc/include/asm/cacheflush.h static inline void invalidate_dcache_range(unsigned long start, · line 105
Quoted 5 lines
arch/powerpc/include/asm/cacheflush.h +5
-0+#define arch_pmem_flush_barrier arch_pmem_flush_barrier +static inline void arch_pmem_flush_barrier (void ) +{ +if (cpu_has_feature (CPU_FTR_ARCH_207S )) + asm volatile(PPC_PHWSYNC ::: "memory");Shouldn't this fallback to a compatible store-fence in an else statement?
Quoted 5 lines
The idea was to avoid calling this on anything else. We ensure that by making sure that pmem devices are not initialized on systems without that cpu feature. Patch 1 does that. Also, the last patch adds a
WARN_ON()to catch the usage of this outside pmem devices and on systems without that cpu feature.
If patch1 handles this why re-check the cpu-feature in this helper? If the intent is for these routines to be generic why not have them fall back to the P8 barrier instructions for example like x86 clwb(). Any kernel code can call it, and it falls back to a compatible clflush() call on older cpus. I otherwise don't get the point of patch7.
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]
PATCH v6 6/8 powerpc/pmem: Avoid the barrier in flush routines
In reply to Aneesh Kumar K.Vnvdimm expect the flush routines to just mark the cache clean. The barrier that mark the store globally visible is done in nvdimm_flush().
Update the papr_scm driver to a simplified nvdim_flush callback that do only the required barrier.
--- arch/powerpc/lib/pmem.c | 6 ------ arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-)
arch/powerpc/lib/pmem.c +0 -6
@@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
@@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void clean_pmem_range(unsigned long start, unsigned long stop)
arch/powerpc/platforms/pseries/papr_scm.c +13 -0
@@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,return 0 ; } +/* +* We have made sure the pmem writes are done such that before calling this +* all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here +* we just need to add the necessary barrier to make sure the above flushes +* are have updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +static int papr_scm_flush_sync (struct nd_region *nd_region,struct bio *bio) +{ +arch_pmem_flush_barrier (); +return 0 ; +}static ssize_t flags_show (struct device *dev,struct device_attribute *attr,char *buf)
@@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.mapping = &mapping; ndr_desc.num_mappings =1 ; ndr_desc.nd_set = &p->nd_set; + ndr_desc.flush = papr_scm_flush_sync;if (p->is_volatile) p->region =nvdimm_volatile_region_create (p->bus, &ndr_desc);
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Hello,
Quoted 60 lines · Aneesh Kumar K.V
nvdimm expect the flush routines to just mark the cache clean. The barrier that mark the store globally visible is done in
nvdimm_flush().Update the
papr_scmdriver to a simplifiednvdim_flushcallback that do only the required barrier.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/lib/pmem.c | 6 ------ arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-)arch/powerpc/lib/pmem.c +0
-6@@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void __flush_pmem_range(unsigned long start, unsigned long stop)@@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void clean_pmem_range(unsigned long start, unsigned long stop)arch/powerpc/platforms/pseries/papr_scm.c +12
-0@@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,return 0 ; } +/* +* We have made sure the pmem writes are done such that before calling this +* all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here +* we just need to add the necessary barrier to make sure the above flushes +* are have updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +static int papr_scm_flush_sync (struct nd_region *nd_region,struct bio *bio) +{ +arch_pmem_flush_barrier (); +return 0 ; +}static ssize_t flags_show (struct device *dev,struct device_attribute *attr,char *buf)
arch/powerpc/platforms/pseries/papr_scm.c static int papr_scm_nvdimm_init(struct papr_scm_priv *p) · line 758
Quoted 4 lines
arch/powerpc/platforms/pseries/papr_scm.c +1
-0@@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.mapping = &mapping; ndr_desc.num_mappings =1 ; ndr_desc.nd_set = &p->nd_set; + ndr_desc.flush = papr_scm_flush_sync;
AFAICT currently the only device that implements flush is virtio_pmem. How does the nfit driver get away without implementing flush? Also the flush takes arguments that are completely unused but a user of the pmem region must assume they are used, and call flush() on the region rather than arch_pmem_flush_barrier() directly. This may not work well with md as discussed with earlier iteration of the patchest.
Thanks
Michal
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Quoted 60 lines · Michal Suchánek
Hello,
Quoted 57 lines · Aneesh Kumar K.V
nvdimm expect the flush routines to just mark the cache clean. The barrier that mark the store globally visible is done in
nvdimm_flush().Update the
papr_scmdriver to a simplifiednvdim_flushcallback that do only the required barrier.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/lib/pmem.c | 6 ------ arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-)arch/powerpc/lib/pmem.c +0
-6@@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void __flush_pmem_range(unsigned long start, unsigned long stop)@@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void clean_pmem_range(unsigned long start, unsigned long stop)arch/powerpc/platforms/pseries/papr_scm.c +12
-0@@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,return 0 ; } +/* +* We have made sure the pmem writes are done such that before calling this +* all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here +* we just need to add the necessary barrier to make sure the above flushes +* are have updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +static int papr_scm_flush_sync (struct nd_region *nd_region,struct bio *bio) +{ +arch_pmem_flush_barrier (); +return 0 ; +}
Quoted 10 lines
arch/powerpc/platforms/pseries/papr_scm.c static int papr_scm_nvdimm_init(struct papr_scm_priv *p) · line 758
Quoted 7 lines
arch/powerpc/platforms/pseries/papr_scm.c +1
-0static ssize_t flags_show (struct device *dev,struct device_attribute *attr,char *buf)@@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.mapping = &mapping; ndr_desc.num_mappings =1 ; ndr_desc.nd_set = &p->nd_set; + ndr_desc.flush = papr_scm_flush_sync;AFAICT currently the only device that implements flush is
virtio_pmem. How does the nfit driver get away without implementing flush?
generic_nvdimm_flush does the required barrier for nfit. The reason for adding ndr_desc.flush call back for papr_scm was to avoid the usage of iomem based deep flushing (ndr_region_data.flush_wpq) which is not supported by papr_scm.
BTW we do return NULL for ndrd_get_flush_wpq() on power. So the upstream code also does the same thing, but in a different way.
Quoted 3 lines
Also the flush takes arguments that are completely unused but a user of the pmem region must assume they are used, and call
flush()on the region rather thanarch_pmem_flush_barrier()directly.
The bio argument can help a pmem driver to do range based flushing in case of pmem_make_request. If bio is null then we must assume a full device flush.
Quoted 3 lines
This may not
work well with md as discussed with earlier iteration of the patchest.
dm-writecache needs some major changes to work with asynchronous pmem devices.
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Quoted 83 lines · Aneesh Kumar K.V
Quoted 60 lines · Michal Suchánek
Hello,
Quoted 57 lines · Aneesh Kumar K.V
nvdimm expect the flush routines to just mark the cache clean. The barrier that mark the store globally visible is done in
nvdimm_flush().Update the
papr_scmdriver to a simplifiednvdim_flushcallback that do only the required barrier.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/lib/pmem.c | 6 ------ arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-)arch/powerpc/lib/pmem.c +0
-6@@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void __flush_pmem_range(unsigned long start, unsigned long stop)@@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void clean_pmem_range(unsigned long start, unsigned long stop)arch/powerpc/platforms/pseries/papr_scm.c +12
-0@@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,return 0 ; } +/* +* We have made sure the pmem writes are done such that before calling this +* all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here +* we just need to add the necessary barrier to make sure the above flushes +* are have updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +static int papr_scm_flush_sync (struct nd_region *nd_region,struct bio *bio) +{ +arch_pmem_flush_barrier (); +return 0 ; +}Quoted 10 lines
arch/powerpc/platforms/pseries/papr_scm.c static int papr_scm_nvdimm_init(struct papr_scm_priv *p) · line 758
Quoted 7 lines
arch/powerpc/platforms/pseries/papr_scm.c +1
-0static ssize_t flags_show (struct device *dev,struct device_attribute *attr,char *buf)@@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.mapping = &mapping; ndr_desc.num_mappings =1 ; ndr_desc.nd_set = &p->nd_set; + ndr_desc.flush = papr_scm_flush_sync;AFAICT currently the only device that implements flush is
virtio_pmem. How does the nfit driver get away without implementing flush?
generic_nvdimm_flushdoes the required barrier for nfit. The reason for adding ndr_desc.flush call back forpapr_scmwas to avoid the usage of iomem based deep flushing (ndr_region_data.flush_wpq) which is not supported bypapr_scm.BTW we do return NULL for
ndrd_get_flush_wpq()on power. So the upstream code also does the same thing, but in a different way.
Quoted 7 lines
Quoted 3 lines
Also the flush takes arguments that are completely unused but a user of the pmem region must assume they are used, and call
flush()on the region rather thanarch_pmem_flush_barrier()directly.The bio argument can help a pmem driver to do range based flushing in case of
pmem_make_request. If bio is null then we must assume a full device flush.
The bio argument isn't for range based flushing, it is for flush operations that need to complete asynchronously.
There's no mechanism for the block layer to communicate range based cache flushing, block-device flushing is assumed to be the device's entire cache. For pmem that would be the entirety of the cpu cache. Instead of modeling the cpu cache as a storage device cache it is modeled as page-cache. Once the fs-layer writes back page-cache / cpu-cache the storage device is only responsible for flushing those cache-writes into the persistence domain.
Additionally there is a concept of deep-flush that relegates some power-fail scenarios to a smaller failure domain. For example consider the difference between a write arriving at the head of a device-queue and successfully traversing a device-queue to media. The expectation of pmem applications is that data is persisted once they reach the equivalent of the x86 ADR domain, deep-flush is past ADR.
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Quoted 89 lines · Dan Williams
Quoted 87 lines · Aneesh Kumar K.V
Quoted 60 lines · Michal Suchánek
Hello,
Quoted 57 lines · Aneesh Kumar K.V
nvdimm expect the flush routines to just mark the cache clean. The barrier that mark the store globally visible is done in
nvdimm_flush().Update the
papr_scmdriver to a simplifiednvdim_flushcallback that do only the required barrier.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/lib/pmem.c | 6 ------ arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-)arch/powerpc/lib/pmem.c +0
-6@@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void __flush_pmem_range(unsigned long start, unsigned long stop)@@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void clean_pmem_range(unsigned long start, unsigned long stop)arch/powerpc/platforms/pseries/papr_scm.c +12
-0@@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,return 0 ; } +/* +* We have made sure the pmem writes are done such that before calling this +* all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here +* we just need to add the necessary barrier to make sure the above flushes +* are have updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +static int papr_scm_flush_sync (struct nd_region *nd_region,struct bio *bio) +{ +arch_pmem_flush_barrier (); +return 0 ; +}Quoted 10 lines
arch/powerpc/platforms/pseries/papr_scm.c static int papr_scm_nvdimm_init(struct papr_scm_priv *p) · line 758
Quoted 7 lines
arch/powerpc/platforms/pseries/papr_scm.c +1
-0static ssize_t flags_show (struct device *dev,struct device_attribute *attr,char *buf)@@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.mapping = &mapping; ndr_desc.num_mappings =1 ; ndr_desc.nd_set = &p->nd_set; + ndr_desc.flush = papr_scm_flush_sync;AFAICT currently the only device that implements flush is
virtio_pmem. How does the nfit driver get away without implementing flush?
generic_nvdimm_flushdoes the required barrier for nfit. The reason for adding ndr_desc.flush call back forpapr_scmwas to avoid the usage of iomem based deep flushing (ndr_region_data.flush_wpq) which is not supported bypapr_scm.BTW we do return NULL for
ndrd_get_flush_wpq()on power. So the upstream code also does the same thing, but in a different way.Quoted 3 lines
Also the flush takes arguments that are completely unused but a user of the pmem region must assume they are used, and call
flush()on the region rather thanarch_pmem_flush_barrier()directly.
Quoted 6 lines
Quoted 3 lines
The bio argument can help a pmem driver to do range based flushing in case of
pmem_make_request. If bio is null then we must assume a full device flush.The bio argument isn't for range based flushing, it is for flush operations that need to complete asynchronously.
How does the block layer determine that the pmem device needs asynchronous fushing?
The flush() was designed for the purpose with the bio argument and only virtio_pmem which is fulshed asynchronously used it. Now that papr_scm resuses it fir different purpose how do you tell?
Thanks
Michal
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Quoted 90 lines · Michal Suchánek
Quoted 89 lines · Dan Williams
Quoted 87 lines · Aneesh Kumar K.V
Quoted 60 lines · Michal Suchánek
Hello,
Quoted 57 lines · Aneesh Kumar K.V
nvdimm expect the flush routines to just mark the cache clean. The barrier that mark the store globally visible is done in
nvdimm_flush().Update the
papr_scmdriver to a simplifiednvdim_flushcallback that do only the required barrier.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/lib/pmem.c | 6 ------ arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-)arch/powerpc/lib/pmem.c +0
-6@@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void __flush_pmem_range(unsigned long start, unsigned long stop)@@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)for (i =0 ; i < size >> shift; i++, addr += bytes) asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); - - - asm volatile(PPC_PHWSYNC ::: "memory"); } static inline void clean_pmem_range(unsigned long start, unsigned long stop)arch/powerpc/platforms/pseries/papr_scm.c +12
-0@@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,return 0 ; } +/* +* We have made sure the pmem writes are done such that before calling this +* all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here +* we just need to add the necessary barrier to make sure the above flushes +* are have updated persistent storage before any data access or data transfer +* caused by subsequent instructions is initiated. +*/ +static int papr_scm_flush_sync (struct nd_region *nd_region,struct bio *bio) +{ +arch_pmem_flush_barrier (); +return 0 ; +}Quoted 10 lines
arch/powerpc/platforms/pseries/papr_scm.c static int papr_scm_nvdimm_init(struct papr_scm_priv *p) · line 758
Quoted 7 lines
arch/powerpc/platforms/pseries/papr_scm.c +1
-0static ssize_t flags_show (struct device *dev,struct device_attribute *attr,char *buf)@@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) ndr_desc.mapping = &mapping; ndr_desc.num_mappings =1 ; ndr_desc.nd_set = &p->nd_set; + ndr_desc.flush = papr_scm_flush_sync;AFAICT currently the only device that implements flush is
virtio_pmem. How does the nfit driver get away without implementing flush?
generic_nvdimm_flushdoes the required barrier for nfit. The reason for adding ndr_desc.flush call back forpapr_scmwas to avoid the usage of iomem based deep flushing (ndr_region_data.flush_wpq) which is not supported bypapr_scm.BTW we do return NULL for
ndrd_get_flush_wpq()on power. So the upstream code also does the same thing, but in a different way.Quoted 3 lines
Also the flush takes arguments that are completely unused but a user of the pmem region must assume they are used, and call
flush()on the region rather thanarch_pmem_flush_barrier()directly.
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
The bio argument can help a pmem driver to do range based flushing in case of
pmem_make_request. If bio is null then we must assume a full device flush.The bio argument isn't for range based flushing, it is for flush operations that need to complete asynchronously.
How does the block layer determine that the pmem device needs asynchronous fushing?
set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
and dax_synchronous(dev)
Quoted 4 lines
The
flush()was designed for the purpose with the bio argument and onlyvirtio_pmemwhich is fulshed asynchronously used it. Now thatpapr_scmresuses it fir different purpose how do you tell?
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
On Tue, Jun 30, 2020 at 2:21 AM Aneesh Kumar K.V
<[email protected]> wrote:
[..]
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
The bio argument isn't for range based flushing, it is for flush operations that need to complete asynchronously.
How does the block layer determine that the pmem device needs asynchronous fushing?
set_bit(ND_REGION_ASYNC, &ndr_desc.flags);and
dax_synchronous(dev)
Yes, but I think it is overkill to have an indirect function call just for a single instruction.
How about something like this instead, to share a common pmem_wmb() across x86 and powerpc.
drivers/nvdimm/region_devs.c +0 -0
@@ -1180,6 +1180,13 @@ int nvdimm_flush(struct nd_region *nd_region,
struct bio *bio)
{
int rc = 0;+ /*
+ * pmem_wmb() is needed to 'sfence' all previous writes such
+ * that they are architecturally visible for the platform buffer
+ * flush.
+ */
+ pmem_wmb();
+
if (!nd_region->flush)
rc = generic_nvdimm_flush(nd_region);
else {
@@ -1206,17 +1213,14 @@ int generic_nvdimm_flush(struct nd_region *nd_region)
idx = this_cpu_add_return(flush_idx, hash_32(current->pid + idx, 8));
/*
- * The first wmb() is needed to 'sfence' all previous writes
- * such that they are architecturally visible for the platform
- * buffer flush. Note that we've already arranged for pmem
- * writes to avoid the cache via memcpy_flushcache(). The final
- * wmb() ensures ordering for the NVDIMM flush write.
+ * Note that we've already arranged for pmem writes to avoid the
+ * cache via memcpy_flushcache(). The final wmb() ensures
+ * ordering for the NVDIMM flush write.
*/
- wmb();
for (i = 0; i < nd_region->ndr_mappings; i++)
if (ndrd_get_flush_wpq(ndrd, i, 0))
writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));- wmb();
+ pmem_wmb();
return 0;
}
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Quoted 42 lines · Dan Williams
On Tue, Jun 30, 2020 at 2:21 AM Aneesh Kumar K.V
<[email protected]> wrote:
[..]Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
The bio argument isn't for range based flushing, it is for flush operations that need to complete asynchronously.
How does the block layer determine that the pmem device needs asynchronous fushing?
set_bit(ND_REGION_ASYNC, &ndr_desc.flags);and
dax_synchronous(dev)Yes, but I think it is overkill to have an indirect function call just for a single instruction.
How about something like this instead, to share a common
pmem_wmb()across x86 and powerpc.drivers/nvdimm/region_devs.c +7
-0@@ -1180,6 +1180,13 @@ int nvdimm_flush(struct nd_region *nd_region, struct bio *bio) {int rc =0 ; +/* +* pmem_wmb() is needed to 'sfence' all previous writes such +* that they are architecturally visible for the platform buffer +* flush. +*/ +pmem_wmb (); +if (!nd_region->flush) rc =generic_nvdimm_flush (nd_region);else {drivers/nvdimm/region_devs.c +0
-0@@ -1206,17 +1213,14 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/*
drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1215
Quoted 10 lines
drivers/nvdimm/region_devs.c +3
-6-* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem -* writes to avoid the cache via memcpy_flushcache(). The final -* wmb() ensures ordering for the NVDIMM flush write. +* Note that we've already arranged for pmem writes to avoid the +* cache via memcpy_flushcache(). The final wmb() ensures +* ordering for the NVDIMM flush write. */ -wmb ();
The series already convert this to pmem_wmb().
drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1223
Quoted 5 lines
drivers/nvdimm/region_devs.c +1
-1for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx)); -wmb (); +pmem_wmb ();
Should this be pmem_wmb()? This is ordering the above writeq() right?
drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1226
Quoted 4 lines
drivers/nvdimm/region_devs.c +0
-0return 0 ; }
This still results in two pmem_wmb() on platforms that doesn't have flush_wpq. I was trying to avoid that by adding a nd_region->flush call back.
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
Quoted 58 lines · Aneesh Kumar K.V
Quoted 42 lines · Dan Williams
On Tue, Jun 30, 2020 at 2:21 AM Aneesh Kumar K.V
<[email protected]> wrote:
[..]Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
The bio argument isn't for range based flushing, it is for flush operations that need to complete asynchronously.
How does the block layer determine that the pmem device needs asynchronous fushing?
set_bit(ND_REGION_ASYNC, &ndr_desc.flags);and
dax_synchronous(dev)Yes, but I think it is overkill to have an indirect function call just for a single instruction.
How about something like this instead, to share a common
pmem_wmb()across x86 and powerpc.drivers/nvdimm/region_devs.c +7
-0@@ -1180,6 +1180,13 @@ int nvdimm_flush(struct nd_region *nd_region, struct bio *bio) {int rc =0 ; +/* +* pmem_wmb() is needed to 'sfence' all previous writes such +* that they are architecturally visible for the platform buffer +* flush. +*/ +pmem_wmb (); +if (!nd_region->flush) rc =generic_nvdimm_flush (nd_region);else {drivers/nvdimm/region_devs.c +0
-0@@ -1206,17 +1213,14 @@ int generic_nvdimm_flush(struct nd_region *nd_region) idx =this_cpu_add_return (flush_idx,hash_32 (current->pid + idx,8 ));/* drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1215
Quoted 10 lines
drivers/nvdimm/region_devs.c +3
-6-* The first wmb() is needed to 'sfence' all previous writes -* such that they are architecturally visible for the platform -* buffer flush. Note that we've already arranged for pmem -* writes to avoid the cache via memcpy_flushcache(). The final -* wmb() ensures ordering for the NVDIMM flush write. +* Note that we've already arranged for pmem writes to avoid the +* cache via memcpy_flushcache(). The final wmb() ensures +* ordering for the NVDIMM flush write. */ -wmb ();The series already convert this to
pmem_wmb().
Quoted 8 lines
drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1223
Quoted 5 lines
drivers/nvdimm/region_devs.c +1
-1for (i =0 ; i < nd_region->ndr_mappings; i++)if (ndrd_get_flush_wpq (ndrd, i,0 ))writeq (1 ,ndrd_get_flush_wpq (ndrd, i, idx)); -wmb (); +pmem_wmb ();Should this be
pmem_wmb()? This is ordering the abovewriteq()right?
Correct, this can just be wmb().
Quoted 9 lines
drivers/nvdimm/region_devs.c int generic_nvdimm_flush(struct nd_region *nd_region) · line 1226
Quoted 5 lines
drivers/nvdimm/region_devs.c +0
-0return 0 ; }This still results in two
pmem_wmb()on platforms that doesn't haveflush_wpq. I was trying to avoid that by adding and_region->flushcall back.
How about skip or exit early out of generic_nvdimm_flush if ndrd->flush_wpq is NULL? That still saves an indirect branch at the cost of another conditional, but that should still be worth it.
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 7/8 powerpc/pmem: Add WARN_ONCE to catch the wrong usage of pmem flush functions.
In reply to Aneesh Kumar K.VWe only support persistent memory on P8 and above. This is enforced by the firmware and further checked on virtualzied platform during platform init. Add WARN_ONCE in pmem flush routines to catch the wrong usage of these.
--- arch/powerpc/include/asm/cacheflush.h | 2 ++ arch/powerpc/lib/pmem.c | 2 ++ 2 files changed, 4 insertions(+)
arch/powerpc/include/asm/cacheflush.h +2 -0
@@ -103,6 +103,8 @@ static inline void arch_pmem_flush_barrier(void) {if (cpu_has_feature (CPU_FTR_ARCH_207S )) asm volatile(PPC_PHWSYNC ::: "memory"); +else +WARN_ONCE (1 ,"Using pmem flush on older hardware." ); }#include <asm-generic/cacheflush.h>
arch/powerpc/lib/pmem.c +2 -0
@@ -37,12 +37,14 @@ static inline void clean_pmem_range(unsigned long start, unsigned long stop) {if (cpu_has_feature (CPU_FTR_ARCH_207S ))return __clean_pmem_range (start, stop); +WARN_ONCE (1 ,"Using pmem flush on older hardware." ); }static inline void flush_pmem_range (unsigned long start,unsigned long stop) {if (cpu_has_feature (CPU_FTR_ARCH_207S ))return __flush_pmem_range (start, stop); +WARN_ONCE (1 ,"Using pmem flush on older hardware." ); }/*
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
Re: [PATCH v6 7/8] powerpc/pmem: Add WARN_ONCE to catch the wrong usage of pmem flush functions.
Quoted 16 lines · Aneesh Kumar K.V
We only support persistent memory on P8 and above. This is enforced by the firmware and further checked on virtualzied platform during platform init. Add
WARN_ONCEin pmem flush routines to catch the wrong usage of these.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/include/asm/cacheflush.h | 2 ++ arch/powerpc/lib/pmem.c | 2 ++ 2 files changed, 4 insertions(+)arch/powerpc/include/asm/cacheflush.h +0
-0
arch/powerpc/include/asm/cacheflush.h static inline void arch_pmem_flush_barrier(void) · line 107
Quoted 5 lines
arch/powerpc/include/asm/cacheflush.h +2
-0@@ -103,6 +103,8 @@ static inline void arch_pmem_flush_barrier(void) {if (cpu_has_feature (CPU_FTR_ARCH_207S )) asm volatile(PPC_PHWSYNC ::: "memory"); +else +WARN_ONCE (1 ,"Using pmem flush on older hardware." );
This seems too late to be making this determination. I'd expect the driver to fail to successfully bind default if this constraint is not met.
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]
Re: [PATCH v6 7/8] powerpc/pmem: Add WARN_ONCE to catch the wrong usage of pmem flush functions.
Quoted 13 lines · Dan Williams
Quoted 11 lines · Aneesh Kumar K.V
We only support persistent memory on P8 and above. This is enforced by the firmware and further checked on virtualzied platform during platform init. Add
WARN_ONCEin pmem flush routines to catch the wrong usage of these.Signed-off-by Aneesh Kumar K.V <[email protected]>--- arch/powerpc/include/asm/cacheflush.h | 2 ++ arch/powerpc/lib/pmem.c | 2 ++ 2 files changed, 4 insertions(+)
Quoted 14 lines
arch/powerpc/include/asm/cacheflush.h static inline void arch_pmem_flush_barrier(void) · line 107
Quoted 10 lines
arch/powerpc/include/asm/cacheflush.h +2
-0@@ -103,6 +103,8 @@ static inline void arch_pmem_flush_barrier(void) {if (cpu_has_feature (CPU_FTR_ARCH_207S )) asm volatile(PPC_PHWSYNC ::: "memory"); +else +WARN_ONCE (1 ,"Using pmem flush on older hardware." );This seems too late to be making this determination. I'd expect the driver to fail to successfully bind default if this constraint is not met.
We do that in Patch 1.
-aneesh
_______________________________________________
Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]
PATCH v6 8/8 powerpc/pmem: Initialize pmem device on newer hardware
In reply to Aneesh Kumar K.VWith kernel now supporting new pmem flush/sync instructions, we can now enable the kernel to initialize the device. On P10 these devices would appear with a new compatible string. For PAPR device we have
compatible "ibm,pmemory-v2"
and for OF pmem device we have
compatible "pmem-region-v2"
--- arch/powerpc/platforms/pseries/papr_scm.c | 1 + drivers/nvdimm/of_pmem.c | 1 + 2 files changed, 2 insertions(+)
arch/powerpc/platforms/pseries/papr_scm.c +1 -0
@@ -889,6 +889,7 @@ static int papr_scm_remove(struct platform_device *pdev)static const struct of_device_id papr_scm_match[] = { { .compatible ="ibm,pmemory" }, + { .compatible ="ibm,pmemory-v2" }, { }, };
drivers/nvdimm/of_pmem.c +1 -0
@@ -90,6 +90,7 @@ static int of_pmem_region_remove(struct platform_device *pdev)static const struct of_device_id of_pmem_region_match[] = { { .compatible ="pmem-region" }, + { .compatible ="pmem-region-v2" }, { }, };
Signature · 4 lines
2.26.2 _______________________________________________ Linux-nvdimm mailing list -- [email protected] To unsubscribe send an email to [email protected]