Merge tag 's390-6.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[linux-block.git] / arch / s390 / include / asm / alternative.h
CommitLineData
9fa1db4c 1/* SPDX-License-Identifier: GPL-2.0 */
686140a1
VG
2#ifndef _ASM_S390_ALTERNATIVE_H
3#define _ASM_S390_ALTERNATIVE_H
4
5#ifndef __ASSEMBLY__
6
7#include <linux/types.h>
8#include <linux/stddef.h>
9#include <linux/stringify.h>
10
11struct alt_instr {
12 s32 instr_offset; /* original instruction */
13 s32 repl_offset; /* offset to replacement instruction */
14 u16 facility; /* facility bit set for replacement */
15 u8 instrlen; /* length of original instruction */
686140a1
VG
16} __packed;
17
049a2c2d
HC
18void apply_alternative_instructions(void);
19void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
20
686140a1 21/*
e6ed91fd
HC
22 * +---------------------------------+
23 * |661: |662:
24 * | oldinstr |
25 * +---------------------------------+
686140a1
VG
26 *
27 * .altinstr_replacement section
e6ed91fd 28 * +---------------------------------+
686140a1
VG
29 * |6641: |6651:
30 * | alternative instr 1 |
e6ed91fd
HC
31 * +---------------------------------+
32 * |6642: |6652:
33 * | alternative instr 2 |
34 * +---------------------------------+
686140a1
VG
35 *
36 * .altinstructions section
37 * +---------------------------------+
38 * | alt_instr entries for each |
39 * | alternative instr |
40 * +---------------------------------+
41 */
42
e6ed91fd
HC
43#define b_altinstr(num) "664"#num
44#define e_altinstr(num) "665"#num
686140a1 45#define oldinstr_len "662b-661b"
686140a1 46#define altinstr_len(num) e_altinstr(num)"b-"b_altinstr(num)"b"
686140a1 47
e6ed91fd
HC
48#define OLDINSTR(oldinstr) \
49 "661:\n\t" oldinstr "\n662:\n"
686140a1
VG
50
51#define ALTINSTR_ENTRY(facility, num) \
52 "\t.long 661b - .\n" /* old instruction */ \
53 "\t.long " b_altinstr(num)"b - .\n" /* alt instruction */ \
54 "\t.word " __stringify(facility) "\n" /* facility bit */ \
e6ed91fd 55 "\t.byte " oldinstr_len "\n" /* instruction len */ \
207ddb91 56 "\t.org . - (" oldinstr_len ") & 1\n" \
e6ed91fd
HC
57 "\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n" \
58 "\t.org . - (" altinstr_len(num) ") + (" oldinstr_len ")\n"
686140a1
VG
59
60#define ALTINSTR_REPLACEMENT(altinstr, num) /* replacement */ \
e6ed91fd 61 b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n"
686140a1 62
686140a1
VG
63/* alternative assembly primitive: */
64#define ALTERNATIVE(oldinstr, altinstr, facility) \
65 ".pushsection .altinstr_replacement, \"ax\"\n" \
66 ALTINSTR_REPLACEMENT(altinstr, 1) \
67 ".popsection\n" \
e6ed91fd 68 OLDINSTR(oldinstr) \
686140a1
VG
69 ".pushsection .altinstructions,\"a\"\n" \
70 ALTINSTR_ENTRY(facility, 1) \
71 ".popsection\n"
72
73#define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2)\
74 ".pushsection .altinstr_replacement, \"ax\"\n" \
75 ALTINSTR_REPLACEMENT(altinstr1, 1) \
76 ALTINSTR_REPLACEMENT(altinstr2, 2) \
77 ".popsection\n" \
e6ed91fd 78 OLDINSTR(oldinstr) \
686140a1
VG
79 ".pushsection .altinstructions,\"a\"\n" \
80 ALTINSTR_ENTRY(facility1, 1) \
81 ALTINSTR_ENTRY(facility2, 2) \
82 ".popsection\n"
686140a1
VG
83
84/*
85 * Alternative instructions for different CPU types or capabilities.
86 *
87 * This allows to use optimized instructions even on generic binary
88 * kernels.
89 *
90 * oldinstr is padded with jump and nops at compile time if altinstr is
91 * longer. altinstr is padded with jump and nops at run-time during patching.
92 *
93 * For non barrier like inlines please define new variants
94 * without volatile and memory clobber.
95 */
96#define alternative(oldinstr, altinstr, facility) \
cceb0183 97 asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) : : : "memory")
686140a1
VG
98
99#define alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
cceb0183 100 asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, facility1, \
686140a1
VG
101 altinstr2, facility2) ::: "memory")
102
80841ad8
HC
103/* Alternative inline assembly with input. */
104#define alternative_input(oldinstr, newinstr, feature, input...) \
105 asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
106 : : input)
107
108/* Like alternative_input, but with a single output argument */
109#define alternative_io(oldinstr, altinstr, facility, output, input...) \
110 asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) \
111 : output : input)
112
113/* Use this macro if more than one output parameter is needed. */
114#define ASM_OUTPUT2(a...) a
115
116/* Use this macro if clobbers are needed without inputs. */
117#define ASM_NO_INPUT_CLOBBER(clobber...) : clobber
118
686140a1
VG
119#endif /* __ASSEMBLY__ */
120
121#endif /* _ASM_S390_ALTERNATIVE_H */