Skip to content

Commit 6deaa3b

Browse files
author
Martin Schwidefsky
committed
s390: extend expoline to BC instructions
The BPF JIT uses a 'b <disp>(%r<x>)' instruction in the definition of the sk_load_word and sk_load_half functions. Add support for branch-on-condition instructions contained in the thunk code of an expoline. Signed-off-by: Martin Schwidefsky <[email protected]>
1 parent 9f18fff commit 6deaa3b

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

arch/s390/include/asm/nospec-insn.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ _LC_BR_R1 = __LC_BR_R1
3535
__THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
3636
.endm
3737

38+
.macro __THUNK_PROLOG_BC d0,r1,r2
39+
__THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
40+
.endm
41+
3842
.macro __THUNK_BR r1,r2
3943
jg __s390x_indirect_jump_r\r2\()use_r\r1
4044
.endm
4145

46+
.macro __THUNK_BC d0,r1,r2
47+
jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1
48+
.endm
49+
4250
.macro __THUNK_BRASL r1,r2,r3
4351
brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
4452
.endm
@@ -81,6 +89,23 @@ _LC_BR_R1 = __LC_BR_R1
8189
.endif
8290
.endm
8391

92+
.macro __DECODE_DRR expand,disp,reg,ruse
93+
.set __decode_fail,1
94+
.irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
95+
.ifc \reg,%r\r1
96+
.irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
97+
.ifc \ruse,%r\r2
98+
\expand \disp,\r1,\r2
99+
.set __decode_fail,0
100+
.endif
101+
.endr
102+
.endif
103+
.endr
104+
.if __decode_fail == 1
105+
.error "__DECODE_DRR failed"
106+
.endif
107+
.endm
108+
84109
.macro __THUNK_EX_BR reg,ruse
85110
# Be very careful when adding instructions to this macro!
86111
# The ALTERNATIVE replacement code has a .+10 which targets
@@ -101,17 +126,42 @@ _LC_BR_R1 = __LC_BR_R1
101126
555: br \reg
102127
.endm
103128

129+
.macro __THUNK_EX_BC disp,reg,ruse
130+
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
131+
exrl 0,556f
132+
j .
133+
#else
134+
larl \ruse,556f
135+
ex 0,0(\ruse)
136+
j .
137+
#endif
138+
556: b \disp(\reg)
139+
.endm
140+
104141
.macro GEN_BR_THUNK reg,ruse=%r1
105142
__DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
106143
__THUNK_EX_BR \reg,\ruse
107144
__THUNK_EPILOG
108145
.endm
109146

147+
.macro GEN_B_THUNK disp,reg,ruse=%r1
148+
__DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
149+
__THUNK_EX_BC \disp,\reg,\ruse
150+
__THUNK_EPILOG
151+
.endm
152+
110153
.macro BR_EX reg,ruse=%r1
111154
557: __DECODE_RR __THUNK_BR,\reg,\ruse
112155
.pushsection .s390_indirect_branches,"a",@progbits
113156
.long 557b-.
114157
.popsection
158+
.endm
159+
160+
.macro B_EX disp,reg,ruse=%r1
161+
558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
162+
.pushsection .s390_indirect_branches,"a",@progbits
163+
.long 558b-.
164+
.popsection
115165
.endm
116166

117167
.macro BASR_EX rsave,rtarget,ruse=%r1
@@ -123,10 +173,17 @@ _LC_BR_R1 = __LC_BR_R1
123173

124174
#else
125175
.macro GEN_BR_THUNK reg,ruse=%r1
176+
.endm
177+
178+
.macro GEN_B_THUNK disp,reg,ruse=%r1
126179
.endm
127180

128181
.macro BR_EX reg,ruse=%r1
129182
br \reg
183+
.endm
184+
185+
.macro B_EX disp,reg,ruse=%r1
186+
b \disp(\reg)
130187
.endm
131188

132189
.macro BASR_EX rsave,rtarget,ruse=%r1

arch/s390/kernel/nospec-branch.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
9393
s32 *epo;
9494

9595
/* Second part of the instruction replace is always a nop */
96-
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
9796
for (epo = start; epo < end; epo++) {
9897
instr = (u8 *) epo + *epo;
9998
if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
@@ -114,18 +113,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
114113
br = thunk + (*(int *)(thunk + 2)) * 2;
115114
else
116115
continue;
117-
if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
116+
/* Check for unconditional branch 0x07f? or 0x47f???? */
117+
if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
118118
continue;
119+
120+
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
119121
switch (type) {
120122
case BRCL_EXPOLINE:
121-
/* brcl to thunk, replace with br + nop */
122123
insnbuf[0] = br[0];
123124
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
125+
if (br[0] == 0x47) {
126+
/* brcl to b, replace with bc + nopr */
127+
insnbuf[2] = br[2];
128+
insnbuf[3] = br[3];
129+
} else {
130+
/* brcl to br, replace with bcr + nop */
131+
}
124132
break;
125133
case BRASL_EXPOLINE:
126-
/* brasl to thunk, replace with basr + nop */
127-
insnbuf[0] = 0x0d;
128134
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
135+
if (br[0] == 0x47) {
136+
/* brasl to b, replace with bas + nopr */
137+
insnbuf[0] = 0x4d;
138+
insnbuf[2] = br[2];
139+
insnbuf[3] = br[3];
140+
} else {
141+
/* brasl to br, replace with basr + nop */
142+
insnbuf[0] = 0x0d;
143+
}
129144
break;
130145
}
131146

0 commit comments

Comments
 (0)