Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

New implementation for IO memcpy and IO memset

The IO memcpy and IO memset functions in asm-generic/io.h simply call
memcpy and memset. This can lead to alignment problems or faults on
architectures that do not define their own version and fall back to
these defaults.
This patch introduces new implementations for IO memcpy and IO memset,
that use read{l,q} accessor functions, align accesses to machine word
size, and resort to byte accesses when the target memory is not aligned.
For new architectures and existing ones that were using the old
fallbacks these functions are save to use, because IO memory constraints
are taken into account. Moreover, architectures with similar
implementations can now use these new versions, not needing to implement
their own.

Reviewed-by: Yann Sionneau <ysionneau@kalrayinc.com>
Signed-off-by: Julian Vetter <jvetter@kalrayinc.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

authored by

Julian Vetter and committed by
Arnd Bergmann
b660d0a2 d4d3125a

+140 -20
+3 -19
include/asm-generic/io.h
··· 1211 1211 #endif 1212 1212 1213 1213 #ifndef memset_io 1214 - #define memset_io memset_io 1215 1214 /** 1216 1215 * memset_io Set a range of I/O memory to a constant value 1217 1216 * @addr: The beginning of the I/O-memory range to set ··· 1219 1220 * 1220 1221 * Set a range of I/O memory to a given value. 1221 1222 */ 1222 - static inline void memset_io(volatile void __iomem *addr, int value, 1223 - size_t size) 1224 - { 1225 - memset(__io_virt(addr), value, size); 1226 - } 1223 + void memset_io(volatile void __iomem *addr, int val, size_t count); 1227 1224 #endif 1228 1225 1229 1226 #ifndef memcpy_fromio 1230 - #define memcpy_fromio memcpy_fromio 1231 1227 /** 1232 1228 * memcpy_fromio Copy a block of data from I/O memory 1233 1229 * @dst: The (RAM) destination for the copy ··· 1231 1237 * 1232 1238 * Copy a block of data from I/O memory. 1233 1239 */ 1234 - static inline void memcpy_fromio(void *buffer, 1235 - const volatile void __iomem *addr, 1236 - size_t size) 1237 - { 1238 - memcpy(buffer, __io_virt(addr), size); 1239 - } 1240 + void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count); 1240 1241 #endif 1241 1242 1242 1243 #ifndef memcpy_toio 1243 - #define memcpy_toio memcpy_toio 1244 1244 /** 1245 1245 * memcpy_toio Copy a block of data into I/O memory 1246 1246 * @dst: The (I/O memory) destination for the copy ··· 1243 1255 * 1244 1256 * Copy a block of data to I/O memory. 1245 1257 */ 1246 - static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer, 1247 - size_t size) 1248 - { 1249 - memcpy(__io_virt(addr), buffer, size); 1250 - } 1258 + void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count); 1251 1259 #endif 1252 1260 1253 1261 extern int devmem_is_allowed(unsigned long pfn);
+1 -1
lib/Makefile
··· 35 35 is_single_threaded.o plist.o decompress.o kobject_uevent.o \ 36 36 earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ 37 37 nmi_backtrace.o win_minmax.o memcat_p.o \ 38 - buildid.o objpool.o union_find.o 38 + buildid.o objpool.o union_find.o iomem_copy.o 39 39 40 40 lib-$(CONFIG_PRINTK) += dump_stack.o 41 41 lib-$(CONFIG_SMP) += cpumask.o
+136
lib/iomem_copy.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2024 Kalray, Inc. All Rights Reserved. 4 + */ 5 + 6 + #include <linux/align.h> 7 + #include <linux/export.h> 8 + #include <linux/io.h> 9 + #include <linux/types.h> 10 + #include <linux/unaligned.h> 11 + 12 + #ifndef memset_io 13 + /** 14 + * memset_io Set a range of I/O memory to a constant value 15 + * @addr: The beginning of the I/O-memory range to set 16 + * @val: The value to set the memory to 17 + * @count: The number of bytes to set 18 + * 19 + * Set a range of I/O memory to a given value. 20 + */ 21 + void memset_io(volatile void __iomem *addr, int val, size_t count) 22 + { 23 + long qc = (u8)val; 24 + 25 + qc *= ~0UL / 0xff; 26 + 27 + while (count && !IS_ALIGNED((long)addr, sizeof(long))) { 28 + __raw_writeb(val, addr); 29 + addr++; 30 + count--; 31 + } 32 + 33 + while (count >= sizeof(long)) { 34 + #ifdef CONFIG_64BIT 35 + __raw_writeq(qc, addr); 36 + #else 37 + __raw_writel(qc, addr); 38 + #endif 39 + 40 + addr += sizeof(long); 41 + count -= sizeof(long); 42 + } 43 + 44 + while (count) { 45 + __raw_writeb(val, addr); 46 + addr++; 47 + count--; 48 + } 49 + } 50 + EXPORT_SYMBOL(memset_io); 51 + #endif 52 + 53 + #ifndef memcpy_fromio 54 + /** 55 + * memcpy_fromio Copy a block of data from I/O memory 56 + * @dst: The (RAM) destination for the copy 57 + * @src: The (I/O memory) source for the data 58 + * @count: The number of bytes to copy 59 + * 60 + * Copy a block of data from I/O memory. 61 + */ 62 + void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count) 63 + { 64 + while (count && !IS_ALIGNED((long)src, sizeof(long))) { 65 + *(u8 *)dst = __raw_readb(src); 66 + src++; 67 + dst++; 68 + count--; 69 + } 70 + 71 + while (count >= sizeof(long)) { 72 + #ifdef CONFIG_64BIT 73 + long val = __raw_readq(src); 74 + #else 75 + long val = __raw_readl(src); 76 + #endif 77 + put_unaligned(val, (long *)dst); 78 + 79 + 80 + src += sizeof(long); 81 + dst += sizeof(long); 82 + count -= sizeof(long); 83 + } 84 + 85 + while (count) { 86 + *(u8 *)dst = __raw_readb(src); 87 + src++; 88 + dst++; 89 + count--; 90 + } 91 + } 92 + EXPORT_SYMBOL(memcpy_fromio); 93 + #endif 94 + 95 + #ifndef memcpy_toio 96 + /** 97 + * memcpy_toio Copy a block of data into I/O memory 98 + * @dst: The (I/O memory) destination for the copy 99 + * @src: The (RAM) source for the data 100 + * @count: The number of bytes to copy 101 + * 102 + * Copy a block of data to I/O memory. 103 + */ 104 + void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count) 105 + { 106 + while (count && !IS_ALIGNED((long)dst, sizeof(long))) { 107 + __raw_writeb(*(u8 *)src, dst); 108 + src++; 109 + dst++; 110 + count--; 111 + } 112 + 113 + while (count >= sizeof(long)) { 114 + long val = get_unaligned((long *)src); 115 + #ifdef CONFIG_64BIT 116 + __raw_writeq(val, dst); 117 + #else 118 + __raw_writel(val, dst); 119 + #endif 120 + 121 + src += sizeof(long); 122 + dst += sizeof(long); 123 + count -= sizeof(long); 124 + } 125 + 126 + while (count) { 127 + __raw_writeb(*(u8 *)src, dst); 128 + src++; 129 + dst++; 130 + count--; 131 + } 132 + } 133 + EXPORT_SYMBOL(memcpy_toio); 134 + #endif 135 + 136 +