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

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

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ 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(facility)          (ALT_CTX_EARLY << ALT_CTX_SHIFT         | \
 43                                          ALT_TYPE_FACILITY << ALT_TYPE_SHIFT    | \
 44                                          (facility) << ALT_DATA_SHIFT)
 45 
 46 #define ALT_SPEC(facility)              (ALT_CTX_LATE << ALT_CTX_SHIFT          | \
 47                                          ALT_TYPE_SPEC << ALT_TYPE_SHIFT        | \
 48                                          (facility) << ALT_DATA_SHIFT)
 49 
 50 #define ALT_LOWCORE                     (ALT_CTX_EARLY << ALT_CTX_SHIFT         | \
 51                                          ALT_TYPE_LOWCORE << ALT_TYPE_SHIFT)
 52 
 53 #ifndef __ASSEMBLY__
 54 
 55 #include <linux/types.h>
 56 #include <linux/stddef.h>
 57 #include <linux/stringify.h>
 58 
 59 struct alt_instr {
 60         s32 instr_offset;       /* original instruction */
 61         s32 repl_offset;        /* offset to replacement instruction */
 62         union {
 63                 u32 feature;    /* feature required for replacement */
 64                 struct {
 65                         u32 ctx  : 4;  /* context */
 66                         u32 type : 8;  /* type of alternative */
 67                         u32 data : 20; /* patching information */
 68                 };
 69         };
 70         u8  instrlen;           /* length of original instruction */
 71 } __packed;
 72 
 73 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
 74 
 75 void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx);
 76 
 77 static inline void apply_alternative_instructions(void)
 78 {
 79         __apply_alternatives(__alt_instructions, __alt_instructions_end, ALT_CTX_LATE);
 80 }
 81 
 82 static inline void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
 83 {
 84         __apply_alternatives(start, end, ALT_CTX_ALL);
 85 }
 86 
 87 /*
 88  * +---------------------------------+
 89  * |661:                             |662:
 90  * | oldinstr                        |
 91  * +---------------------------------+
 92  *
 93  * .altinstr_replacement section
 94  * +---------------------------------+
 95  * |6641:                            |6651:
 96  * | alternative instr 1             |
 97  * +---------------------------------+
 98  * |6642:                            |6652:
 99  * | alternative instr 2             |
100  * +---------------------------------+
101  *
102  * .altinstructions section
103  * +---------------------------------+
104  * | alt_instr entries for each      |
105  * | alternative instr               |
106  * +---------------------------------+
107  */
108 
109 #define b_altinstr(num)         "664"#num
110 #define e_altinstr(num)         "665"#num
111 #define oldinstr_len            "662b-661b"
112 #define altinstr_len(num)       e_altinstr(num)"b-"b_altinstr(num)"b"
113 
114 #define OLDINSTR(oldinstr) \
115         "661:\n\t" oldinstr "\n662:\n"
116 
117 #define ALTINSTR_ENTRY(feature, num)                                    \
118         "\t.long 661b - .\n"                    /* old instruction */   \
119         "\t.long " b_altinstr(num)"b - .\n"     /* alt instruction */   \
120         "\t.long " __stringify(feature) "\n"    /* feature         */   \
121         "\t.byte " oldinstr_len "\n"            /* instruction len */   \
122         "\t.org . - (" oldinstr_len ") & 1\n"                           \
123         "\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n"     \
124         "\t.org . - (" altinstr_len(num) ") + (" oldinstr_len ")\n"
125 
126 #define ALTINSTR_REPLACEMENT(altinstr, num)     /* replacement */       \
127         b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n"
128 
129 /* alternative assembly primitive: */
130 #define ALTERNATIVE(oldinstr, altinstr, feature) \
131         ".pushsection .altinstr_replacement, \"ax\"\n"                  \
132         ALTINSTR_REPLACEMENT(altinstr, 1)                               \
133         ".popsection\n"                                                 \
134         OLDINSTR(oldinstr)                                              \
135         ".pushsection .altinstructions,\"a\"\n"                         \
136         ALTINSTR_ENTRY(feature, 1)                                      \
137         ".popsection\n"
138 
139 #define ALTERNATIVE_2(oldinstr, altinstr1, feature1, altinstr2, feature2)\
140         ".pushsection .altinstr_replacement, \"ax\"\n"                  \
141         ALTINSTR_REPLACEMENT(altinstr1, 1)                              \
142         ALTINSTR_REPLACEMENT(altinstr2, 2)                              \
143         ".popsection\n"                                                 \
144         OLDINSTR(oldinstr)                                              \
145         ".pushsection .altinstructions,\"a\"\n"                         \
146         ALTINSTR_ENTRY(feature1, 1)                                     \
147         ALTINSTR_ENTRY(feature2, 2)                                     \
148         ".popsection\n"
149 
150 /*
151  * Alternative instructions for different CPU types or capabilities.
152  *
153  * This allows to use optimized instructions even on generic binary
154  * kernels.
155  *
156  * oldinstr is padded with jump and nops at compile time if altinstr is
157  * longer. altinstr is padded with jump and nops at run-time during patching.
158  *
159  * For non barrier like inlines please define new variants
160  * without volatile and memory clobber.
161  */
162 #define alternative(oldinstr, altinstr, feature)                        \
163         asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature) : : : "memory")
164 
165 #define alternative_2(oldinstr, altinstr1, feature1, altinstr2, feature2) \
166         asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, feature1,   \
167                                    altinstr2, feature2) ::: "memory")
168 
169 /* Alternative inline assembly with input. */
170 #define alternative_input(oldinstr, newinstr, feature, input...)        \
171         asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature)   \
172                 : : input)
173 
174 /* Like alternative_input, but with a single output argument */
175 #define alternative_io(oldinstr, altinstr, feature, output, input...)   \
176         asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature)    \
177                 : output : input)
178 
179 /* Use this macro if more than one output parameter is needed. */
180 #define ASM_OUTPUT2(a...) a
181 
182 /* Use this macro if clobbers are needed without inputs. */
183 #define ASM_NO_INPUT_CLOBBER(clobber...) : clobber
184 
185 #else  /* __ASSEMBLY__ */
186 
187 /*
188  * Issue one struct alt_instr descriptor entry (need to put it into
189  * the section .altinstructions, see below). This entry contains
190  * enough information for the alternatives patching code to patch an
191  * instruction. See apply_alternatives().
192  */
193 .macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
194         .long   \orig_start - .
195         .long   \alt_start - .
196         .long   \feature
197         .byte   \orig_end - \orig_start
198         .org    . - ( \orig_end - \orig_start ) & 1
199         .org    . - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start )
200         .org    . - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start )
201 .endm
202 
203 /*
204  * Define an alternative between two instructions. If @feature is
205  * present, early code in apply_alternatives() replaces @oldinstr with
206  * @newinstr.
207  */
208 .macro ALTERNATIVE oldinstr, newinstr, feature
209         .pushsection .altinstr_replacement,"ax"
210 770:    \newinstr
211 771:    .popsection
212 772:    \oldinstr
213 773:    .pushsection .altinstructions,"a"
214         alt_entry 772b, 773b, 770b, 771b, \feature
215         .popsection
216 .endm
217 
218 /*
219  * Define an alternative between two instructions. If @feature is
220  * present, early code in apply_alternatives() replaces @oldinstr with
221  * @newinstr.
222  */
223 .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
224         .pushsection .altinstr_replacement,"ax"
225 770:    \newinstr1
226 771:    \newinstr2
227 772:    .popsection
228 773:    \oldinstr
229 774:    .pushsection .altinstructions,"a"
230         alt_entry 773b, 774b, 770b, 771b,\feature1
231         alt_entry 773b, 774b, 771b, 772b,\feature2
232         .popsection
233 .endm
234 
235 #endif /* __ASSEMBLY__ */
236 
237 #endif /* _ASM_S390_ALTERNATIVE_H */
238 

~ [ 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