~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/include/asm/alternative.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef _ASM_S390_ALTERNATIVE_H
  3 #define _ASM_S390_ALTERNATIVE_H
  4 
  5 /*
  6  * Each alternative comes with a 32 bit feature field:
  7  *      union {
  8  *              u32 feature;
  9  *              struct {
 10  *                      u32 ctx  : 4;
 11  *                      u32 type : 8;
 12  *                      u32 data : 20;
 13  *              };
 14  *      }
 15  *
 16  * @ctx is a bitfield, where only one bit must be set. Each bit defines
 17  * in which context an alternative is supposed to be applied to the
 18  * kernel image:
 19  *
 20  * - from the decompressor before the kernel itself is executed
 21  * - from early kernel code from within the kernel
 22  *
 23  * @type is a number which defines the type and with that the type
 24  * specific alternative patching.
 25  *
 26  * @data is additional type specific information which defines if an
 27  * alternative should be applied.
 28  */
 29 
 30 #define ALT_CTX_EARLY           1
 31 #define ALT_CTX_LATE            2
 32 #define ALT_CTX_ALL             (ALT_CTX_EARLY | ALT_CTX_LATE)
 33 
 34 #define ALT_TYPE_FACILITY       0
 35 #define ALT_TYPE_SPEC           1
 36 #define ALT_TYPE_LOWCORE        2
 37 
 38 #define ALT_DATA_SHIFT          0
 39 #define ALT_TYPE_SHIFT          20
 40 #define ALT_CTX_SHIFT           28
 41 
 42 #define ALT_FACILITY_EARLY(facility)    (ALT_CTX_EARLY << ALT_CTX_SHIFT         | \
 43                                          ALT_TYPE_FACILITY << ALT_TYPE_SHIFT    | \
 44                                          (facility) << ALT_DATA_SHIFT)
 45 
 46 #define ALT_FACILITY(facility)          (ALT_CTX_LATE << ALT_CTX_SHIFT          | \
 47                                          ALT_TYPE_FACILITY << ALT_TYPE_SHIFT    | \
 48                                          (facility) << ALT_DATA_SHIFT)
 49 
 50 #define ALT_SPEC(facility)              (ALT_CTX_LATE << ALT_CTX_SHIFT          | \
 51                                          ALT_TYPE_SPEC << ALT_TYPE_SHIFT        | \
 52                                          (facility) << ALT_DATA_SHIFT)
 53 
 54 #define ALT_LOWCORE                     (ALT_CTX_EARLY << ALT_CTX_SHIFT         | \
 55                                          ALT_TYPE_LOWCORE << ALT_TYPE_SHIFT)
 56 
 57 #ifndef __ASSEMBLY__
 58 
 59 #include <linux/types.h>
 60 #include <linux/stddef.h>
 61 #include <linux/stringify.h>
 62 
 63 struct alt_instr {
 64         s32 instr_offset;       /* original instruction */
 65         s32 repl_offset;        /* offset to replacement instruction */
 66         union {
 67                 u32 feature;    /* feature required for replacement */
 68                 struct {
 69                         u32 ctx  : 4;  /* context */
 70                         u32 type : 8;  /* type of alternative */
 71                         u32 data : 20; /* patching information */
 72                 };
 73         };
 74         u8  instrlen;           /* length of original instruction */
 75 } __packed;
 76 
 77 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 78 
 79 void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx);
 80 
 81 static inline void apply_alternative_instructions(void)
 82 {
 83         __apply_alternatives(__alt_instructions, __alt_instructions_end, ALT_CTX_LATE);
 84 }
 85 
 86 static inline void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
 87 {
 88         __apply_alternatives(start, end, ALT_CTX_ALL);
 89 }
 90 
 91 /*
 92  * +---------------------------------+
 93  * |661:                             |662:
 94  * | oldinstr                        |
 95  * +---------------------------------+
 96  *
 97  * .altinstr_replacement section
 98  * +---------------------------------+
 99  * |6641:                            |6651:
100  * | alternative instr 1             |
101  * +---------------------------------+
102  * |6642:                            |6652:
103  * | alternative instr 2             |
104  * +---------------------------------+
105  *
106  * .altinstructions section
107  * +---------------------------------+
108  * | alt_instr entries for each      |
109  * | alternative instr               |
110  * +---------------------------------+
111  */
112 
113 #define b_altinstr(num)         "664"#num
114 #define e_altinstr(num)         "665"#num
115 #define oldinstr_len            "662b-661b"
116 #define altinstr_len(num)       e_altinstr(num)"b-"b_altinstr(num)"b"
117 
118 #define OLDINSTR(oldinstr) \
119         "661:\n\t" oldinstr "\n662:\n"
120 
121 #define ALTINSTR_ENTRY(feature, num)                                    \
122         "\t.long 661b - .\n"                    /* old instruction */   \
123         "\t.long " b_altinstr(num)"b - .\n"     /* alt instruction */   \
124         "\t.long " __stringify(feature) "\n"    /* feature         */   \
125         "\t.byte " oldinstr_len "\n"            /* instruction len */   \
126         "\t.org . - (" oldinstr_len ") & 1\n"                           \
127         "\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n"     \
128         "\t.org . - (" altinstr_len(num) ") + (" oldinstr_len ")\n"
129 
130 #define ALTINSTR_REPLACEMENT(altinstr, num)     /* replacement */       \
131         b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n"
132 
133 /* alternative assembly primitive: */
134 #define ALTERNATIVE(oldinstr, altinstr, feature) \
135         ".pushsection .altinstr_replacement, \"ax\"\n"                  \
136         ALTINSTR_REPLACEMENT(altinstr, 1)                               \
137         ".popsection\n"                                                 \
138         OLDINSTR(oldinstr)                                              \
139         ".pushsection .altinstructions,\"a\"\n"                         \
140         ALTINSTR_ENTRY(feature, 1)                                      \
141         ".popsection\n"
142 
143 #define ALTERNATIVE_2(oldinstr, altinstr1, feature1, altinstr2, feature2)\
144         ".pushsection .altinstr_replacement, \"ax\"\n"                  \
145         ALTINSTR_REPLACEMENT(altinstr1, 1)                              \
146         ALTINSTR_REPLACEMENT(altinstr2, 2)                              \
147         ".popsection\n"                                                 \
148         OLDINSTR(oldinstr)                                              \
149         ".pushsection .altinstructions,\"a\"\n"                         \
150         ALTINSTR_ENTRY(feature1, 1)                                     \
151         ALTINSTR_ENTRY(feature2, 2)                                     \
152         ".popsection\n"
153 
154 /*
155  * Alternative instructions for different CPU types or capabilities.
156  *
157  * This allows to use optimized instructions even on generic binary
158  * kernels.
159  *
160  * oldinstr is padded with jump and nops at compile time if altinstr is
161  * longer. altinstr is padded with jump and nops at run-time during patching.
162  *
163  * For non barrier like inlines please define new variants
164  * without volatile and memory clobber.
165  */
166 #define alternative(oldinstr, altinstr, feature)                        \
167         asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature) : : : "memory")
168 
169 #define alternative_2(oldinstr, altinstr1, feature1, altinstr2, feature2) \
170         asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, feature1,   \
171                                    altinstr2, feature2) ::: "memory")
172 
173 /* Alternative inline assembly with input. */
174 #define alternative_input(oldinstr, newinstr, feature, input...)        \
175         asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature)   \
176                 : : input)
177 
178 /* Like alternative_input, but with a single output argument */
179 #define alternative_io(oldinstr, altinstr, feature, output, input...)   \
180         asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature)    \
181                 : output : input)
182 
183 /* Use this macro if more than one output parameter is needed. */
184 #define ASM_OUTPUT2(a...) a
185 
186 /* Use this macro if clobbers are needed without inputs. */
187 #define ASM_NO_INPUT_CLOBBER(clobber...) : clobber
188 
189 #else  /* __ASSEMBLY__ */
190 
191 /*
192  * Issue one struct alt_instr descriptor entry (need to put it into
193  * the section .altinstructions, see below). This entry contains
194  * enough information for the alternatives patching code to patch an
195  * instruction. See apply_alternatives().
196  */
197 .macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
198         .long   \orig_start - .
199         .long   \alt_start - .
200         .long   \feature
201         .byte   \orig_end - \orig_start
202         .org    . - ( \orig_end - \orig_start ) & 1
203         .org    . - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start )
204         .org    . - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start )
205 .endm
206 
207 /*
208  * Define an alternative between two instructions. If @feature is
209  * present, early code in apply_alternatives() replaces @oldinstr with
210  * @newinstr.
211  */
212 .macro ALTERNATIVE oldinstr, newinstr, feature
213         .pushsection .altinstr_replacement,"ax"
214 770:    \newinstr
215 771:    .popsection
216 772:    \oldinstr
217 773:    .pushsection .altinstructions,"a"
218         alt_entry 772b, 773b, 770b, 771b, \feature
219         .popsection
220 .endm
221 
222 /*
223  * Define an alternative between two instructions. If @feature is
224  * present, early code in apply_alternatives() replaces @oldinstr with
225  * @newinstr.
226  */
227 .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
228         .pushsection .altinstr_replacement,"ax"
229 770:    \newinstr1
230 771:    \newinstr2
231 772:    .popsection
232 773:    \oldinstr
233 774:    .pushsection .altinstructions,"a"
234         alt_entry 773b, 774b, 770b, 771b,\feature1
235         alt_entry 773b, 774b, 771b, 772b,\feature2
236         .popsection
237 .endm
238 
239 #endif /* __ASSEMBLY__ */
240 
241 #endif /* _ASM_S390_ALTERNATIVE_H */
242 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php