Skip to content

Commit 8ae031a

Browse files
committed
linuxkm/linuxkm_wc_port.h: improve my_memcpy(), my_memset(), and my_memmove() (CONFIG_FORTIFY_SOURCE workarounds) with copy-by-words codepaths.
1 parent 82d94da commit 8ae031a

1 file changed

Lines changed: 58 additions & 20 deletions

File tree

linuxkm/linuxkm_wc_port.h

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
const char *s_start = s;
147147
while (*s)
148148
++s;
149-
return (size_t)s - (size_t)s_start;
149+
return (size_t)((uintptr_t)s - (uintptr_t)s_start);
150150
}
151151

152152
#include <linux/string.h>
@@ -157,37 +157,75 @@
157157
(sizeof(s) - 1) : strlen(s))
158158

159159
static inline void *my_memcpy(void *dest, const void *src, size_t n) {
160-
u8 *src_bytes = (u8 *)src,
161-
*dest_bytes = (u8 *)dest,
162-
*endp = src_bytes + n;
163-
while (src_bytes < endp)
164-
*dest_bytes++ = *src_bytes++;
160+
if (! (((uintptr_t)dest | (uintptr_t)src | (uintptr_t)n) & (uintptr_t)(sizeof(uintptr_t) - 1))) {
161+
uintptr_t *src_longs = (uintptr_t *)src,
162+
*dest_longs = (uintptr_t *)dest,
163+
*endp = (uintptr_t *)((u8 *)src + n);
164+
while (src_longs < endp)
165+
*dest_longs++ = *src_longs++;
166+
} else {
167+
u8 *src_bytes = (u8 *)src,
168+
*dest_bytes = (u8 *)dest,
169+
*endp = src_bytes + n;
170+
while (src_bytes < endp)
171+
*dest_bytes++ = *src_bytes++;
172+
}
165173
return dest;
166174
}
167175
#undef memcpy
168176
#define memcpy my_memcpy
169177

170178
static inline void *my_memset(void *dest, int c, size_t n) {
171-
u8 *dest_bytes = (u8 *)dest, *endp = dest_bytes + n;
172-
while (dest_bytes < endp)
173-
*dest_bytes++ = (u8)c;
179+
if (! (((uintptr_t)dest | (uintptr_t)n) & (uintptr_t)(sizeof(uintptr_t) - 1))) {
180+
uintptr_t c_long = __builtin_choose_expr(
181+
sizeof(uintptr_t) == 8,
182+
(uintptr_t)(u8)c * 0x0101010101010101UL,
183+
(uintptr_t)(u8)c * 0x01010101U
184+
);
185+
uintptr_t *dest_longs = (uintptr_t *)dest, *endp = (uintptr_t *)((u8 *)dest_longs + n);
186+
while (dest_longs < endp)
187+
*dest_longs++ = c_long;
188+
} else {
189+
u8 *dest_bytes = (u8 *)dest, *endp = dest_bytes + n;
190+
while (dest_bytes < endp)
191+
*dest_bytes++ = (u8)c;
192+
}
174193
return dest;
175194
}
176195
#undef memset
177196
#define memset my_memset
178197

179198
static inline void *my_memmove(void *dest, const void *src, size_t n) {
180-
u8 *src_bytes = (u8 *)src, *dest_bytes = (u8 *)dest;
181-
if (src_bytes < dest_bytes) {
182-
u8 *startp = src_bytes;
183-
src_bytes += n - 1;
184-
dest_bytes += n - 1;
185-
while (src_bytes >= startp)
186-
*dest_bytes-- = *src_bytes--;
187-
} else if (src_bytes > dest_bytes) {
188-
u8 *endp = src_bytes + n;
189-
while (src_bytes < endp)
190-
*dest_bytes++ = *src_bytes++;
199+
if (! (((uintptr_t)dest | (uintptr_t)src | (uintptr_t)n) & (uintptr_t)(sizeof(uintptr_t) - 1))) {
200+
uintptr_t *src_longs = (uintptr_t *)src, *dest_longs = (uintptr_t *)dest;
201+
n >>= __builtin_choose_expr(
202+
sizeof(uintptr_t) == 8,
203+
3U,
204+
2U);
205+
if (src_longs < dest_longs) {
206+
uintptr_t *startp = src_longs;
207+
src_longs += n - 1;
208+
dest_longs += n - 1;
209+
while (src_longs >= startp)
210+
*dest_longs-- = *src_longs--;
211+
} else if (src_longs > dest_longs) {
212+
uintptr_t *endp = src_longs + n;
213+
while (src_longs < endp)
214+
*dest_longs++ = *src_longs++;
215+
}
216+
} else {
217+
u8 *src_bytes = (u8 *)src, *dest_bytes = (u8 *)dest;
218+
if (src_bytes < dest_bytes) {
219+
u8 *startp = src_bytes;
220+
src_bytes += n - 1;
221+
dest_bytes += n - 1;
222+
while (src_bytes >= startp)
223+
*dest_bytes-- = *src_bytes--;
224+
} else if (src_bytes > dest_bytes) {
225+
u8 *endp = src_bytes + n;
226+
while (src_bytes < endp)
227+
*dest_bytes++ = *src_bytes++;
228+
}
191229
}
192230
return dest;
193231
}

0 commit comments

Comments
 (0)