]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
81b785f3 KC |
2 | /* |
3 | * This provides an optimized implementation of memcpy, and a simplified | |
4 | * implementation of memset and memmove. These are used here because the | |
5 | * standard kernel runtime versions are not yet available and we don't | |
6 | * trust the gcc built-in implementations as they may do unexpected things | |
7 | * (e.g. FPU ops) in the minimal decompression stub execution environment. | |
8 | */ | |
dc425a6e KC |
9 | #include "error.h" |
10 | ||
8fee13a4 | 11 | #include "../string.c" |
820e8fec | 12 | |
820e8fec | 13 | #ifdef CONFIG_X86_32 |
00ec2c37 | 14 | static void *__memcpy(void *dest, const void *src, size_t n) |
820e8fec VG |
15 | { |
16 | int d0, d1, d2; | |
17 | asm volatile( | |
18 | "rep ; movsl\n\t" | |
19 | "movl %4,%%ecx\n\t" | |
20 | "rep ; movsb\n\t" | |
21 | : "=&c" (d0), "=&D" (d1), "=&S" (d2) | |
22 | : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src) | |
23 | : "memory"); | |
24 | ||
25 | return dest; | |
26 | } | |
27 | #else | |
00ec2c37 | 28 | static void *__memcpy(void *dest, const void *src, size_t n) |
820e8fec VG |
29 | { |
30 | long d0, d1, d2; | |
31 | asm volatile( | |
32 | "rep ; movsq\n\t" | |
33 | "movq %4,%%rcx\n\t" | |
34 | "rep ; movsb\n\t" | |
35 | : "=&c" (d0), "=&D" (d1), "=&S" (d2) | |
36 | : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src) | |
37 | : "memory"); | |
38 | ||
39 | return dest; | |
40 | } | |
41 | #endif | |
04999550 VG |
42 | |
43 | void *memset(void *s, int c, size_t n) | |
44 | { | |
45 | int i; | |
46 | char *ss = s; | |
47 | ||
48 | for (i = 0; i < n; i++) | |
49 | ss[i] = c; | |
50 | return s; | |
51 | } | |
bf0118db | 52 | |
81b785f3 | 53 | void *memmove(void *dest, const void *src, size_t n) |
bf0118db KC |
54 | { |
55 | unsigned char *d = dest; | |
56 | const unsigned char *s = src; | |
57 | ||
58 | if (d <= s || d - s >= n) | |
00ec2c37 | 59 | return __memcpy(dest, src, n); |
bf0118db KC |
60 | |
61 | while (n-- > 0) | |
62 | d[n] = s[n]; | |
63 | ||
64 | return dest; | |
65 | } | |
00ec2c37 KC |
66 | |
67 | /* Detect and warn about potential overlaps, but handle them with memmove. */ | |
68 | void *memcpy(void *dest, const void *src, size_t n) | |
69 | { | |
70 | if (dest > src && dest - src < n) { | |
71 | warn("Avoiding potentially unsafe overlapping memcpy()!"); | |
72 | return memmove(dest, src, n); | |
73 | } | |
74 | return __memcpy(dest, src, n); | |
75 | } |