[PATCH v2 5/7] string: introduce memcpy_streaming() helpers

From: Li Zhe

Date: Thu May 21 2026 - 00:05:37 EST


Introduce a generic memcpy_streaming() interface for write-once copy
sites that can fall back to memcpy() when no architecture-specific
optimization is available.

Add memcpy_streaming_drain() alongside it so callers can separate the
copy primitive from any required ordering point. On x86, wire the helper
to memcpy_flushcache() and sfence so common code can request a streaming
copy without embedding x86-specific movnti details.

Callers are responsible for invoking memcpy_streaming_drain() before
later normal stores that must be ordered after the streaming copy.

Signed-off-by: Li Zhe <lizhe.67@xxxxxxxxxxxxx>
---
arch/x86/include/asm/string_64.h | 13 +++++++++++++
include/linux/string.h | 18 ++++++++++++++++++
2 files changed, 31 insertions(+)

diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index 4635616863f5..15504b844f1e 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -100,6 +100,19 @@ static __always_inline void memcpy_flushcache(void *dst, const void *src, size_t
}
__memcpy_flushcache(dst, src, cnt);
}
+
+#define __HAVE_ARCH_MEMCPY_STREAMING 1
+static __always_inline void memcpy_streaming(void *dst, const void *src,
+ size_t cnt)
+{
+ memcpy_flushcache(dst, src, cnt);
+}
+
+static __always_inline void memcpy_streaming_drain(void)
+{
+ asm volatile("sfence" : : : "memory");
+}
+
#endif

#endif /* __KERNEL__ */
diff --git a/include/linux/string.h b/include/linux/string.h
index b850bd91b3d8..ba029be9c187 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -281,6 +281,24 @@ static inline void memcpy_flushcache(void *dst, const void *src, size_t cnt)
}
#endif

+#ifndef __HAVE_ARCH_MEMCPY_STREAMING
+/*
+ * memcpy_streaming() is for write-once copy sites that may use
+ * non-temporal stores on some architectures. Callers must follow it
+ * with memcpy_streaming_drain() before later normal stores that need to
+ * be ordered after the streaming copy. Implementations that use regular
+ * cached stores can make the drain a no-op.
+ */
+static inline void memcpy_streaming(void *dst, const void *src, size_t cnt)
+{
+ memcpy(dst, src, cnt);
+}
+
+static inline void memcpy_streaming_drain(void)
+{
+}
+#endif
+
void *memchr_inv(const void *s, int c, size_t n);
char *strreplace(char *str, char old, char new);

--
2.20.1