^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) #ifndef _ASM_S390_ALTERNATIVE_ASM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _ASM_S390_ALTERNATIVE_ASM_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #ifdef __ASSEMBLY__
^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) * Check the length of an instruction sequence. The length may not be larger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * than 254 bytes and it has to be divisible by 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) .macro alt_len_check start,end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) .if ( \end - \start ) > 254
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) .error "cpu alternatives does not support instructions blocks > 254 bytes\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) .endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) .if ( \end - \start ) % 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) .error "cpu alternatives instructions length is odd\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) .endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Issue one struct alt_instr descriptor entry (need to put it into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * the section .altinstructions, see below). This entry contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * enough information for the alternatives patching code to patch an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * instruction. See apply_alternatives().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .long \orig_start - .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .long \alt_start - .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .word \feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .byte \orig_end - \orig_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .byte \alt_end - \alt_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Fill up @bytes with nops. The macro emits 6-byte nop instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * for the bulk of the area, possibly followed by a 4-byte and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * a 2-byte nop if the size of the area is not divisible by 6.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .macro alt_pad_fill bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .fill ( \bytes ) / 6, 6, 0xc0040000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .fill ( \bytes ) % 6 / 4, 4, 0x47000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .fill ( \bytes ) % 6 % 4 / 2, 2, 0x0700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Fill up @bytes with nops. If the number of bytes is larger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * than 6, emit a jg instruction to branch over all nops, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * fill an area of size (@bytes - 6) with nop instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .macro alt_pad bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .if ( \bytes > 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .if ( \bytes > 6 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) jg . + \bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) alt_pad_fill \bytes - 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) alt_pad_fill \bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Define an alternative between two instructions. If @feature is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * present, early code in apply_alternatives() replaces @oldinstr with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * @newinstr. ".skip" directive takes care of proper instruction padding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * in case @newinstr is longer than @oldinstr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .macro ALTERNATIVE oldinstr, newinstr, feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .pushsection .altinstr_replacement,"ax"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 770: \newinstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 771: .popsection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 772: \oldinstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 773: alt_len_check 770b, 771b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) alt_len_check 772b, 773b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) alt_pad ( ( 771b - 770b ) - ( 773b - 772b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 774: .pushsection .altinstructions,"a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) alt_entry 772b, 774b, 770b, 771b, \feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .popsection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Define an alternative between two instructions. If @feature is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * present, early code in apply_alternatives() replaces @oldinstr with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * @newinstr. ".skip" directive takes care of proper instruction padding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * in case @newinstr is longer than @oldinstr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .pushsection .altinstr_replacement,"ax"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 770: \newinstr1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 771: \newinstr2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 772: .popsection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 773: \oldinstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) 774: alt_len_check 770b, 771b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) alt_len_check 771b, 772b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) alt_len_check 773b, 774b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .if ( 771b - 770b > 772b - 771b )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) alt_pad ( ( 771b - 770b ) - ( 774b - 773b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) alt_pad ( ( 772b - 771b ) - ( 774b - 773b ) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 775: .pushsection .altinstructions,"a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) alt_entry 773b, 775b, 770b, 771b,\feature1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) alt_entry 773b, 775b, 771b, 772b,\feature2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .popsection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #endif /* __ASSEMBLY__ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #endif /* _ASM_S390_ALTERNATIVE_ASM_H */