^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * String handling functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/nospec-insn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) GEN_BR_THUNK %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * void *memmove(void *dest, const void *src, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) WEAK(memmove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) ENTRY(__memmove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ltgr %r4,%r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) lgr %r1,%r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) jz .Lmemmove_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) aghi %r4,-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) clgr %r2,%r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) jnh .Lmemmove_forward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) la %r5,1(%r4,%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) clgr %r2,%r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) jl .Lmemmove_reverse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .Lmemmove_forward:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) srlg %r0,%r4,8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ltgr %r0,%r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) jz .Lmemmove_forward_remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .Lmemmove_forward_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mvc 0(256,%r1),0(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) la %r1,256(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) la %r3,256(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) brctg %r0,.Lmemmove_forward_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .Lmemmove_forward_remainder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) larl %r5,.Lmemmove_mvc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ex %r4,0(%r5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .Lmemmove_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .Lmemmove_reverse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ic %r0,0(%r4,%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) stc %r0,0(%r4,%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) brctg %r4,.Lmemmove_reverse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ic %r0,0(%r4,%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) stc %r0,0(%r4,%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .Lmemmove_mvc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) mvc 0(1,%r1),0(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ENDPROC(__memmove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) EXPORT_SYMBOL(memmove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * memset implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * This code corresponds to the C construct below. We do distinguish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * between clearing (c == 0) and setting a memory array (c != 0) simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * because nearly all memset invocations in the kernel clear memory and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * the xc instruction is preferred in such cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * void *memset(void *s, int c, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * if (likely(c == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * return __builtin_memset(s, 0, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * return __builtin_memset(s, c, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) WEAK(memset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ENTRY(__memset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ltgr %r4,%r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) jz .Lmemset_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ltgr %r3,%r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) jnz .Lmemset_fill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) aghi %r4,-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) srlg %r3,%r4,8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ltgr %r3,%r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) lgr %r1,%r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) jz .Lmemset_clear_remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .Lmemset_clear_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) xc 0(256,%r1),0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) la %r1,256(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) brctg %r3,.Lmemset_clear_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .Lmemset_clear_remainder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) larl %r3,.Lmemset_xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ex %r4,0(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .Lmemset_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .Lmemset_fill:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) cghi %r4,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) lgr %r1,%r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) je .Lmemset_fill_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) aghi %r4,-2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) srlg %r5,%r4,8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ltgr %r5,%r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) jz .Lmemset_fill_remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .Lmemset_fill_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) stc %r3,0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) mvc 1(255,%r1),0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) la %r1,256(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) brctg %r5,.Lmemset_fill_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .Lmemset_fill_remainder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) stc %r3,0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) larl %r5,.Lmemset_mvc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ex %r4,0(%r5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .Lmemset_fill_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) stc %r3,0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .Lmemset_xc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) xc 0(1,%r1),0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .Lmemset_mvc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mvc 1(1,%r1),0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ENDPROC(__memset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) EXPORT_SYMBOL(memset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * memcpy implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * void *memcpy(void *dest, const void *src, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) WEAK(memcpy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ENTRY(__memcpy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ltgr %r4,%r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) jz .Lmemcpy_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) aghi %r4,-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) srlg %r5,%r4,8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ltgr %r5,%r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) lgr %r1,%r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) jnz .Lmemcpy_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .Lmemcpy_remainder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) larl %r5,.Lmemcpy_mvc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ex %r4,0(%r5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .Lmemcpy_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .Lmemcpy_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mvc 0(256,%r1),0(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) la %r1,256(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) la %r3,256(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) brctg %r5,.Lmemcpy_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) j .Lmemcpy_remainder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .Lmemcpy_mvc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) mvc 0(1,%r1),0(%r3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ENDPROC(__memcpy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) EXPORT_SYMBOL(memcpy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * __memset16/32/64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * void *__memset16(uint16_t *s, uint16_t v, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * void *__memset32(uint32_t *s, uint32_t v, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * void *__memset64(uint64_t *s, uint64_t v, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .macro __MEMSET bits,bytes,insn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ENTRY(__memset\bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ltgr %r4,%r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) jz .L__memset_exit\bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) cghi %r4,\bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) je .L__memset_store\bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) aghi %r4,-(\bytes+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) srlg %r5,%r4,8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ltgr %r5,%r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) lgr %r1,%r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) jz .L__memset_remainder\bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .L__memset_loop\bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) \insn %r3,0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mvc \bytes(256-\bytes,%r1),0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) la %r1,256(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) brctg %r5,.L__memset_loop\bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .L__memset_remainder\bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) \insn %r3,0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) larl %r5,.L__memset_mvc\bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ex %r4,0(%r5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .L__memset_store\bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) \insn %r3,0(%r2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .L__memset_exit\bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) BR_EX %r14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .L__memset_mvc\bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mvc \bytes(1,%r1),0(%r1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ENDPROC(__memset\bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) __MEMSET 16,2,sth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) EXPORT_SYMBOL(__memset16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) __MEMSET 32,4,st
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) EXPORT_SYMBOL(__memset32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) __MEMSET 64,8,stg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) EXPORT_SYMBOL(__memset64)