xref: /openbmc/linux/arch/s390/include/asm/string.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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