root/arch/s390/include/asm/alternative-asm.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


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

/* [<][>][^][v][top][bottom][index][help] */