1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2c6557e7fSMartin Schwidefsky /*
3c6557e7fSMartin Schwidefsky * S390 version
4a53c8fabSHeiko Carstens * Copyright IBM Corp. 1999
5c6557e7fSMartin Schwidefsky * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
6c6557e7fSMartin Schwidefsky */
7c6557e7fSMartin Schwidefsky
8c6557e7fSMartin Schwidefsky #ifndef _S390_STRING_H_
9c6557e7fSMartin Schwidefsky #define _S390_STRING_H_
10c6557e7fSMartin Schwidefsky
11c6557e7fSMartin Schwidefsky #ifndef _LINUX_TYPES_H
12c6557e7fSMartin Schwidefsky #include <linux/types.h>
13c6557e7fSMartin Schwidefsky #endif
14c6557e7fSMartin Schwidefsky
15c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_MEMCPY /* gcc builtin & arch function */
16b4623d4eSHeiko Carstens #define __HAVE_ARCH_MEMMOVE /* gcc builtin & arch function */
17c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_MEMSET /* gcc builtin & arch function */
180b77d670SHeiko Carstens #define __HAVE_ARCH_MEMSET16 /* arch function */
190b77d670SHeiko Carstens #define __HAVE_ARCH_MEMSET32 /* arch function */
200b77d670SHeiko Carstens #define __HAVE_ARCH_MEMSET64 /* arch function */
217e0d92f0SVasily Gorbik
227e0d92f0SVasily Gorbik void *memcpy(void *dest, const void *src, size_t n);
237e0d92f0SVasily Gorbik void *memset(void *s, int c, size_t n);
247e0d92f0SVasily Gorbik void *memmove(void *dest, const void *src, size_t n);
257e0d92f0SVasily Gorbik
267e0d92f0SVasily Gorbik #ifndef CONFIG_KASAN
277e0d92f0SVasily Gorbik #define __HAVE_ARCH_MEMCHR /* inline & arch function */
287e0d92f0SVasily Gorbik #define __HAVE_ARCH_MEMCMP /* arch function */
297e0d92f0SVasily Gorbik #define __HAVE_ARCH_MEMSCAN /* inline & arch function */
30c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRCAT /* inline & arch function */
31c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRCMP /* arch function */
32c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRCPY /* inline & arch function */
33c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRLCAT /* arch function */
34c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRLEN /* inline & arch function */
35c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRNCAT /* arch function */
36c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRNCPY /* arch function */
37c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRNLEN /* inline & arch function */
38c6557e7fSMartin Schwidefsky #define __HAVE_ARCH_STRSTR /* arch function */
39c6557e7fSMartin Schwidefsky
40c6557e7fSMartin Schwidefsky /* Prototypes for non-inlined arch strings functions. */
4149913f1fSHeiko Carstens int memcmp(const void *s1, const void *s2, size_t n);
4249913f1fSHeiko Carstens int strcmp(const char *s1, const char *s2);
4349913f1fSHeiko Carstens size_t strlcat(char *dest, const char *src, size_t n);
4449913f1fSHeiko Carstens char *strncat(char *dest, const char *src, size_t n);
4549913f1fSHeiko Carstens char *strncpy(char *dest, const char *src, size_t n);
4649913f1fSHeiko Carstens char *strstr(const char *s1, const char *s2);
477e0d92f0SVasily Gorbik #endif /* !CONFIG_KASAN */
48c6557e7fSMartin Schwidefsky
49c6557e7fSMartin Schwidefsky #undef __HAVE_ARCH_STRCHR
50c6557e7fSMartin Schwidefsky #undef __HAVE_ARCH_STRNCHR
51c6557e7fSMartin Schwidefsky #undef __HAVE_ARCH_STRNCMP
52c6557e7fSMartin Schwidefsky #undef __HAVE_ARCH_STRPBRK
53c6557e7fSMartin Schwidefsky #undef __HAVE_ARCH_STRSEP
54c6557e7fSMartin Schwidefsky #undef __HAVE_ARCH_STRSPN
55c6557e7fSMartin Schwidefsky
56fb594ec1SVasily Gorbik #if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
57fb594ec1SVasily Gorbik
58f45f7b5bSVasily Gorbik #define strlen(s) __strlen(s)
59f45f7b5bSVasily Gorbik
60f45f7b5bSVasily Gorbik #define __no_sanitize_prefix_strfunc(x) __##x
61fb594ec1SVasily Gorbik
62fb594ec1SVasily Gorbik #ifndef __NO_FORTIFY
63fb594ec1SVasily Gorbik #define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
64fb594ec1SVasily Gorbik #endif
65fb594ec1SVasily Gorbik
66f45f7b5bSVasily Gorbik #else
67f45f7b5bSVasily Gorbik #define __no_sanitize_prefix_strfunc(x) x
68fb594ec1SVasily Gorbik #endif /* defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__) */
69fb594ec1SVasily Gorbik
70*e48b6853SHeiko Carstens void *__memcpy(void *dest, const void *src, size_t n);
71*e48b6853SHeiko Carstens void *__memset(void *s, int c, size_t n);
72*e48b6853SHeiko Carstens void *__memmove(void *dest, const void *src, size_t n);
730b77d670SHeiko Carstens void *__memset16(uint16_t *s, uint16_t v, size_t count);
740b77d670SHeiko Carstens void *__memset32(uint32_t *s, uint32_t v, size_t count);
750b77d670SHeiko Carstens void *__memset64(uint64_t *s, uint64_t v, size_t count);
760b77d670SHeiko Carstens
memset16(uint16_t * s,uint16_t v,size_t count)770b77d670SHeiko Carstens static inline void *memset16(uint16_t *s, uint16_t v, size_t count)
780b77d670SHeiko Carstens {
790b77d670SHeiko Carstens return __memset16(s, v, count * sizeof(v));
800b77d670SHeiko Carstens }
810b77d670SHeiko Carstens
memset32(uint32_t * s,uint32_t v,size_t count)820b77d670SHeiko Carstens static inline void *memset32(uint32_t *s, uint32_t v, size_t count)
830b77d670SHeiko Carstens {
840b77d670SHeiko Carstens return __memset32(s, v, count * sizeof(v));
850b77d670SHeiko Carstens }
860b77d670SHeiko Carstens
memset64(uint64_t * s,uint64_t v,size_t count)870b77d670SHeiko Carstens static inline void *memset64(uint64_t *s, uint64_t v, size_t count)
880b77d670SHeiko Carstens {
890b77d670SHeiko Carstens return __memset64(s, v, count * sizeof(v));
900b77d670SHeiko Carstens }
910b77d670SHeiko Carstens
9279962038SHeiko Carstens #if !defined(IN_ARCH_STRING_C) && (!defined(CONFIG_FORTIFY_SOURCE) || defined(__NO_FORTIFY))
93c6557e7fSMartin Schwidefsky
947e0d92f0SVasily Gorbik #ifdef __HAVE_ARCH_MEMCHR
memchr(const void * s,int c,size_t n)95c6557e7fSMartin Schwidefsky static inline void *memchr(const void * s, int c, size_t n)
96c6557e7fSMartin Schwidefsky {
97c6557e7fSMartin Schwidefsky const void *ret = s + n;
98c6557e7fSMartin Schwidefsky
99c6557e7fSMartin Schwidefsky asm volatile(
1008f45db55SHeiko Carstens " lgr 0,%[c]\n"
1018f45db55SHeiko Carstens "0: srst %[ret],%[s]\n"
102c6557e7fSMartin Schwidefsky " jo 0b\n"
103c6557e7fSMartin Schwidefsky " jl 1f\n"
1048f45db55SHeiko Carstens " la %[ret],0\n"
105c6557e7fSMartin Schwidefsky "1:"
1068f45db55SHeiko Carstens : [ret] "+&a" (ret), [s] "+&a" (s)
1078f45db55SHeiko Carstens : [c] "d" (c)
1088f45db55SHeiko Carstens : "cc", "memory", "0");
109c6557e7fSMartin Schwidefsky return (void *) ret;
110c6557e7fSMartin Schwidefsky }
1117e0d92f0SVasily Gorbik #endif
112c6557e7fSMartin Schwidefsky
1137e0d92f0SVasily Gorbik #ifdef __HAVE_ARCH_MEMSCAN
memscan(void * s,int c,size_t n)114c6557e7fSMartin Schwidefsky static inline void *memscan(void *s, int c, size_t n)
115c6557e7fSMartin Schwidefsky {
116c6557e7fSMartin Schwidefsky const void *ret = s + n;
117c6557e7fSMartin Schwidefsky
118c6557e7fSMartin Schwidefsky asm volatile(
1198f45db55SHeiko Carstens " lgr 0,%[c]\n"
1208f45db55SHeiko Carstens "0: srst %[ret],%[s]\n"
121c6557e7fSMartin Schwidefsky " jo 0b\n"
1228f45db55SHeiko Carstens : [ret] "+&a" (ret), [s] "+&a" (s)
1238f45db55SHeiko Carstens : [c] "d" (c)
1248f45db55SHeiko Carstens : "cc", "memory", "0");
125c6557e7fSMartin Schwidefsky return (void *) ret;
126c6557e7fSMartin Schwidefsky }
1277e0d92f0SVasily Gorbik #endif
128c6557e7fSMartin Schwidefsky
1297e0d92f0SVasily Gorbik #ifdef __HAVE_ARCH_STRCAT
strcat(char * dst,const char * src)130c6557e7fSMartin Schwidefsky static inline char *strcat(char *dst, const char *src)
131c6557e7fSMartin Schwidefsky {
1328f45db55SHeiko Carstens unsigned long dummy = 0;
133c6557e7fSMartin Schwidefsky char *ret = dst;
134c6557e7fSMartin Schwidefsky
135c6557e7fSMartin Schwidefsky asm volatile(
1368f45db55SHeiko Carstens " lghi 0,0\n"
1378f45db55SHeiko Carstens "0: srst %[dummy],%[dst]\n"
138c6557e7fSMartin Schwidefsky " jo 0b\n"
1398f45db55SHeiko Carstens "1: mvst %[dummy],%[src]\n"
140c6557e7fSMartin Schwidefsky " jo 1b"
1418f45db55SHeiko Carstens : [dummy] "+&a" (dummy), [dst] "+&a" (dst), [src] "+&a" (src)
1428f45db55SHeiko Carstens :
1438f45db55SHeiko Carstens : "cc", "memory", "0");
144c6557e7fSMartin Schwidefsky return ret;
145c6557e7fSMartin Schwidefsky }
1467e0d92f0SVasily Gorbik #endif
147c6557e7fSMartin Schwidefsky
1487e0d92f0SVasily Gorbik #ifdef __HAVE_ARCH_STRCPY
strcpy(char * dst,const char * src)149c6557e7fSMartin Schwidefsky static inline char *strcpy(char *dst, const char *src)
150c6557e7fSMartin Schwidefsky {
151c6557e7fSMartin Schwidefsky char *ret = dst;
152c6557e7fSMartin Schwidefsky
153c6557e7fSMartin Schwidefsky asm volatile(
1548f45db55SHeiko Carstens " lghi 0,0\n"
1558f45db55SHeiko Carstens "0: mvst %[dst],%[src]\n"
156c6557e7fSMartin Schwidefsky " jo 0b"
1578f45db55SHeiko Carstens : [dst] "+&a" (dst), [src] "+&a" (src)
1588f45db55SHeiko Carstens :
1598f45db55SHeiko Carstens : "cc", "memory", "0");
160c6557e7fSMartin Schwidefsky return ret;
161c6557e7fSMartin Schwidefsky }
1627e0d92f0SVasily Gorbik #endif
163c6557e7fSMartin Schwidefsky
164f45f7b5bSVasily Gorbik #if defined(__HAVE_ARCH_STRLEN) || (defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__))
__no_sanitize_prefix_strfunc(strlen)165f45f7b5bSVasily Gorbik static inline size_t __no_sanitize_prefix_strfunc(strlen)(const char *s)
166c6557e7fSMartin Schwidefsky {
1678f45db55SHeiko Carstens unsigned long end = 0;
168c6557e7fSMartin Schwidefsky const char *tmp = s;
169c6557e7fSMartin Schwidefsky
170c6557e7fSMartin Schwidefsky asm volatile(
1718f45db55SHeiko Carstens " lghi 0,0\n"
1728f45db55SHeiko Carstens "0: srst %[end],%[tmp]\n"
173c6557e7fSMartin Schwidefsky " jo 0b"
1748f45db55SHeiko Carstens : [end] "+&a" (end), [tmp] "+&a" (tmp)
1758f45db55SHeiko Carstens :
1768f45db55SHeiko Carstens : "cc", "memory", "0");
1778f45db55SHeiko Carstens return end - (unsigned long)s;
178c6557e7fSMartin Schwidefsky }
1797e0d92f0SVasily Gorbik #endif
180c6557e7fSMartin Schwidefsky
1817e0d92f0SVasily Gorbik #ifdef __HAVE_ARCH_STRNLEN
strnlen(const char * s,size_t n)182c6557e7fSMartin Schwidefsky static inline size_t strnlen(const char * s, size_t n)
183c6557e7fSMartin Schwidefsky {
184c6557e7fSMartin Schwidefsky const char *tmp = s;
185c6557e7fSMartin Schwidefsky const char *end = s + n;
186c6557e7fSMartin Schwidefsky
187c6557e7fSMartin Schwidefsky asm volatile(
1888f45db55SHeiko Carstens " lghi 0,0\n"
1898f45db55SHeiko Carstens "0: srst %[end],%[tmp]\n"
190c6557e7fSMartin Schwidefsky " jo 0b"
1918f45db55SHeiko Carstens : [end] "+&a" (end), [tmp] "+&a" (tmp)
1928f45db55SHeiko Carstens :
1938f45db55SHeiko Carstens : "cc", "memory", "0");
194c6557e7fSMartin Schwidefsky return end - s;
195c6557e7fSMartin Schwidefsky }
1967e0d92f0SVasily Gorbik #endif
1976faf2507SRusty Russell #else /* IN_ARCH_STRING_C */
1986faf2507SRusty Russell void *memchr(const void * s, int c, size_t n);
1996faf2507SRusty Russell void *memscan(void *s, int c, size_t n);
2006faf2507SRusty Russell char *strcat(char *dst, const char *src);
2016faf2507SRusty Russell char *strcpy(char *dst, const char *src);
2026faf2507SRusty Russell size_t strlen(const char *s);
2036faf2507SRusty Russell size_t strnlen(const char * s, size_t n);
204c6557e7fSMartin Schwidefsky #endif /* !IN_ARCH_STRING_C */
205c6557e7fSMartin Schwidefsky
206c6557e7fSMartin Schwidefsky #endif /* __S390_STRING_H_ */
207