cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

string.c (1951B)


      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
     11#include "../string.c"
     12
     13#ifdef CONFIG_X86_32
     14static void *____memcpy(void *dest, const void *src, size_t n)
     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
     28static void *____memcpy(void *dest, const void *src, size_t n)
     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
     42
     43void *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}
     52
     53void *memmove(void *dest, const void *src, size_t n)
     54{
     55	unsigned char *d = dest;
     56	const unsigned char *s = src;
     57
     58	if (d <= s || d - s >= n)
     59		return ____memcpy(dest, src, n);
     60
     61	while (n-- > 0)
     62		d[n] = s[n];
     63
     64	return dest;
     65}
     66
     67/* Detect and warn about potential overlaps, but handle them with memmove. */
     68void *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}
     76
     77#ifdef CONFIG_KASAN
     78extern void *__memset(void *s, int c, size_t n) __alias(memset);
     79extern void *__memmove(void *dest, const void *src, size_t n) __alias(memmove);
     80extern void *__memcpy(void *dest, const void *src, size_t n) __alias(memcpy);
     81#endif