at v4.5 5.7 kB view raw
1/* 2 * Copyright(c) 2015 Intel Corporation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 */ 13#ifndef __PMEM_H__ 14#define __PMEM_H__ 15 16#include <linux/io.h> 17#include <linux/uio.h> 18 19#ifdef CONFIG_ARCH_HAS_PMEM_API 20#define ARCH_MEMREMAP_PMEM MEMREMAP_WB 21#include <asm/pmem.h> 22#else 23#define ARCH_MEMREMAP_PMEM MEMREMAP_WT 24/* 25 * These are simply here to enable compilation, all call sites gate 26 * calling these symbols with arch_has_pmem_api() and redirect to the 27 * implementation in asm/pmem.h. 28 */ 29static inline bool __arch_has_wmb_pmem(void) 30{ 31 return false; 32} 33 34static inline void arch_wmb_pmem(void) 35{ 36 BUG(); 37} 38 39static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src, 40 size_t n) 41{ 42 BUG(); 43} 44 45static inline size_t arch_copy_from_iter_pmem(void __pmem *addr, size_t bytes, 46 struct iov_iter *i) 47{ 48 BUG(); 49 return 0; 50} 51 52static inline void arch_clear_pmem(void __pmem *addr, size_t size) 53{ 54 BUG(); 55} 56 57static inline void arch_wb_cache_pmem(void __pmem *addr, size_t size) 58{ 59 BUG(); 60} 61#endif 62 63/* 64 * Architectures that define ARCH_HAS_PMEM_API must provide 65 * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), 66 * arch_copy_from_iter_pmem(), arch_clear_pmem(), arch_wb_cache_pmem() 67 * and arch_has_wmb_pmem(). 68 */ 69static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size) 70{ 71 memcpy(dst, (void __force const *) src, size); 72} 73 74static inline bool arch_has_pmem_api(void) 75{ 76 return IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API); 77} 78 79/** 80 * arch_has_wmb_pmem - true if wmb_pmem() ensures durability 81 * 82 * For a given cpu implementation within an architecture it is possible 83 * that wmb_pmem() resolves to a nop. In the case this returns 84 * false, pmem api users are unable to ensure durability and may want to 85 * fall back to a different data consistency model, or otherwise notify 86 * the user. 87 */ 88static inline bool arch_has_wmb_pmem(void) 89{ 90 return arch_has_pmem_api() && __arch_has_wmb_pmem(); 91} 92 93/* 94 * These defaults seek to offer decent performance and minimize the 95 * window between i/o completion and writes being durable on media. 96 * However, it is undefined / architecture specific whether 97 * ARCH_MEMREMAP_PMEM + default_memcpy_to_pmem is sufficient for 98 * making data durable relative to i/o completion. 99 */ 100static inline void default_memcpy_to_pmem(void __pmem *dst, const void *src, 101 size_t size) 102{ 103 memcpy((void __force *) dst, src, size); 104} 105 106static inline size_t default_copy_from_iter_pmem(void __pmem *addr, 107 size_t bytes, struct iov_iter *i) 108{ 109 return copy_from_iter_nocache((void __force *)addr, bytes, i); 110} 111 112static inline void default_clear_pmem(void __pmem *addr, size_t size) 113{ 114 if (size == PAGE_SIZE && ((unsigned long)addr & ~PAGE_MASK) == 0) 115 clear_page((void __force *)addr); 116 else 117 memset((void __force *)addr, 0, size); 118} 119 120/** 121 * memcpy_to_pmem - copy data to persistent memory 122 * @dst: destination buffer for the copy 123 * @src: source buffer for the copy 124 * @n: length of the copy in bytes 125 * 126 * Perform a memory copy that results in the destination of the copy 127 * being effectively evicted from, or never written to, the processor 128 * cache hierarchy after the copy completes. After memcpy_to_pmem() 129 * data may still reside in cpu or platform buffers, so this operation 130 * must be followed by a wmb_pmem(). 131 */ 132static inline void memcpy_to_pmem(void __pmem *dst, const void *src, size_t n) 133{ 134 if (arch_has_pmem_api()) 135 arch_memcpy_to_pmem(dst, src, n); 136 else 137 default_memcpy_to_pmem(dst, src, n); 138} 139 140/** 141 * wmb_pmem - synchronize writes to persistent memory 142 * 143 * After a series of memcpy_to_pmem() operations this drains data from 144 * cpu write buffers and any platform (memory controller) buffers to 145 * ensure that written data is durable on persistent memory media. 146 */ 147static inline void wmb_pmem(void) 148{ 149 if (arch_has_wmb_pmem()) 150 arch_wmb_pmem(); 151 else 152 wmb(); 153} 154 155/** 156 * copy_from_iter_pmem - copy data from an iterator to PMEM 157 * @addr: PMEM destination address 158 * @bytes: number of bytes to copy 159 * @i: iterator with source data 160 * 161 * Copy data from the iterator 'i' to the PMEM buffer starting at 'addr'. 162 * This function requires explicit ordering with a wmb_pmem() call. 163 */ 164static inline size_t copy_from_iter_pmem(void __pmem *addr, size_t bytes, 165 struct iov_iter *i) 166{ 167 if (arch_has_pmem_api()) 168 return arch_copy_from_iter_pmem(addr, bytes, i); 169 return default_copy_from_iter_pmem(addr, bytes, i); 170} 171 172/** 173 * clear_pmem - zero a PMEM memory range 174 * @addr: virtual start address 175 * @size: number of bytes to zero 176 * 177 * Write zeros into the memory range starting at 'addr' for 'size' bytes. 178 * This function requires explicit ordering with a wmb_pmem() call. 179 */ 180static inline void clear_pmem(void __pmem *addr, size_t size) 181{ 182 if (arch_has_pmem_api()) 183 arch_clear_pmem(addr, size); 184 else 185 default_clear_pmem(addr, size); 186} 187 188/** 189 * wb_cache_pmem - write back processor cache for PMEM memory range 190 * @addr: virtual start address 191 * @size: number of bytes to write back 192 * 193 * Write back the processor cache range starting at 'addr' for 'size' bytes. 194 * This function requires explicit ordering with a wmb_pmem() call. 195 */ 196static inline void wb_cache_pmem(void __pmem *addr, size_t size) 197{ 198 if (arch_has_pmem_api()) 199 arch_wb_cache_pmem(addr, size); 200} 201#endif /* __PMEM_H__ */