string.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // SPDX-License-Identifier: GPL-2.0
  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. */
  9. #include "error.h"
  10. #include "../string.c"
  11. #ifdef CONFIG_X86_32
  12. static void *____memcpy(void *dest, const void *src, size_t n)
  13. {
  14. int d0, d1, d2;
  15. asm volatile(
  16. "rep ; movsl\n\t"
  17. "movl %4,%%ecx\n\t"
  18. "rep ; movsb\n\t"
  19. : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  20. : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src)
  21. : "memory");
  22. return dest;
  23. }
  24. #else
  25. static void *____memcpy(void *dest, const void *src, size_t n)
  26. {
  27. long d0, d1, d2;
  28. asm volatile(
  29. "rep ; movsq\n\t"
  30. "movq %4,%%rcx\n\t"
  31. "rep ; movsb\n\t"
  32. : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  33. : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src)
  34. : "memory");
  35. return dest;
  36. }
  37. #endif
  38. void *memset(void *s, int c, size_t n)
  39. {
  40. int i;
  41. char *ss = s;
  42. for (i = 0; i < n; i++)
  43. ss[i] = c;
  44. return s;
  45. }
  46. void *memmove(void *dest, const void *src, size_t n)
  47. {
  48. unsigned char *d = dest;
  49. const unsigned char *s = src;
  50. if (d <= s || d - s >= n)
  51. return ____memcpy(dest, src, n);
  52. while (n-- > 0)
  53. d[n] = s[n];
  54. return dest;
  55. }
  56. /* Detect and warn about potential overlaps, but handle them with memmove. */
  57. void *memcpy(void *dest, const void *src, size_t n)
  58. {
  59. if (dest > src && dest - src < n) {
  60. warn("Avoiding potentially unsafe overlapping memcpy()!");
  61. return memmove(dest, src, n);
  62. }
  63. return ____memcpy(dest, src, n);
  64. }
  65. #ifdef CONFIG_KASAN
  66. extern void *__memset(void *s, int c, size_t n) __alias(memset);
  67. extern void *__memmove(void *dest, const void *src, size_t n) __alias(memmove);
  68. extern void *__memcpy(void *dest, const void *src, size_t n) __alias(memcpy);
  69. #endif