Skip to content

Commit 632d566

Browse files
Martin SchwidefskyZhengShunQian
Martin Schwidefsky
authored andcommitted
s390: add assembler macros for CPU alternatives
[ Upstream commit fba9eb7 ] Add a header with macros usable in assembler files to emit alternative code sequences. It works analog to the alternatives for inline assmeblies in C files, with the same restrictions and capabilities. The syntax is ALTERNATIVE "<default instructions sequence>", \ "<alternative instructions sequence>", \ "<features-bit>" and ALTERNATIVE_2 "<default instructions sequence>", \ "<alternative instructions sqeuence #1>", \ "<feature-bit #1>", "<alternative instructions sqeuence #2>", \ "<feature-bit #2>" Reviewed-by: Vasily Gorbik <gor@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8bb2f58 commit 632d566

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed
+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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 */

0 commit comments

Comments
 (0)