0001
0002 #ifndef _ASM_S390_ALTERNATIVE_H
0003 #define _ASM_S390_ALTERNATIVE_H
0004
0005 #ifndef __ASSEMBLY__
0006
0007 #include <linux/types.h>
0008 #include <linux/stddef.h>
0009 #include <linux/stringify.h>
0010
0011 struct alt_instr {
0012 s32 instr_offset;
0013 s32 repl_offset;
0014 u16 facility;
0015 u8 instrlen;
0016 } __packed;
0017
0018 void apply_alternative_instructions(void);
0019 void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #define b_altinstr(num) "664"#num
0044 #define e_altinstr(num) "665"#num
0045 #define oldinstr_len "662b-661b"
0046 #define altinstr_len(num) e_altinstr(num)"b-"b_altinstr(num)"b"
0047
0048 #define OLDINSTR(oldinstr) \
0049 "661:\n\t" oldinstr "\n662:\n"
0050
0051 #define ALTINSTR_ENTRY(facility, num) \
0052 "\t.long 661b - .\n" \
0053 "\t.long " b_altinstr(num)"b - .\n" \
0054 "\t.word " __stringify(facility) "\n" \
0055 "\t.byte " oldinstr_len "\n" \
0056 "\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n" \
0057 "\t.org . - (" altinstr_len(num) ") + (" oldinstr_len ")\n"
0058
0059 #define ALTINSTR_REPLACEMENT(altinstr, num) \
0060 b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n"
0061
0062
0063 #define ALTERNATIVE(oldinstr, altinstr, facility) \
0064 ".pushsection .altinstr_replacement, \"ax\"\n" \
0065 ALTINSTR_REPLACEMENT(altinstr, 1) \
0066 ".popsection\n" \
0067 OLDINSTR(oldinstr) \
0068 ".pushsection .altinstructions,\"a\"\n" \
0069 ALTINSTR_ENTRY(facility, 1) \
0070 ".popsection\n"
0071
0072 #define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2)\
0073 ".pushsection .altinstr_replacement, \"ax\"\n" \
0074 ALTINSTR_REPLACEMENT(altinstr1, 1) \
0075 ALTINSTR_REPLACEMENT(altinstr2, 2) \
0076 ".popsection\n" \
0077 OLDINSTR(oldinstr) \
0078 ".pushsection .altinstructions,\"a\"\n" \
0079 ALTINSTR_ENTRY(facility1, 1) \
0080 ALTINSTR_ENTRY(facility2, 2) \
0081 ".popsection\n"
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 #define alternative(oldinstr, altinstr, facility) \
0096 asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) : : : "memory")
0097
0098 #define alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
0099 asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, facility1, \
0100 altinstr2, facility2) ::: "memory")
0101
0102
0103 #define alternative_input(oldinstr, newinstr, feature, input...) \
0104 asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
0105 : : input)
0106
0107
0108 #define alternative_io(oldinstr, altinstr, facility, output, input...) \
0109 asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) \
0110 : output : input)
0111
0112
0113 #define ASM_OUTPUT2(a...) a
0114
0115
0116 #define ASM_NO_INPUT_CLOBBER(clobber...) : clobber
0117
0118 #endif
0119
0120 #endif