Commit 11ebe0e1 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Khalid Elmously

s390: extend expoline to BC instructions

BugLink: https://bugs.launchpad.net/bugs/1775477

[ Upstream commit 6deaa3bb ]

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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
Acked-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent 7b48e8e7
...@@ -29,10 +29,18 @@ ...@@ -29,10 +29,18 @@
__THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1 __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
.endm .endm
.macro __THUNK_PROLOG_BC d0,r1,r2
__THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
.endm
.macro __THUNK_BR r1,r2 .macro __THUNK_BR r1,r2
jg __s390x_indirect_jump_r\r2\()use_r\r1 jg __s390x_indirect_jump_r\r2\()use_r\r1
.endm .endm
.macro __THUNK_BC d0,r1,r2
jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1
.endm
.macro __THUNK_BRASL r1,r2,r3 .macro __THUNK_BRASL r1,r2,r3
brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2 brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
.endm .endm
...@@ -75,6 +83,23 @@ ...@@ -75,6 +83,23 @@
.endif .endif
.endm .endm
.macro __DECODE_DRR expand,disp,reg,ruse
.set __decode_fail,1
.irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
.ifc \reg,%r\r1
.irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
.ifc \ruse,%r\r2
\expand \disp,\r1,\r2
.set __decode_fail,0
.endif
.endr
.endif
.endr
.if __decode_fail == 1
.error "__DECODE_DRR failed"
.endif
.endm
.macro __THUNK_EX_BR reg,ruse .macro __THUNK_EX_BR reg,ruse
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
exrl 0,555f exrl 0,555f
...@@ -87,17 +112,42 @@ ...@@ -87,17 +112,42 @@
555: br \reg 555: br \reg
.endm .endm
.macro __THUNK_EX_BC disp,reg,ruse
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
exrl 0,556f
j .
#else
larl \ruse,556f
ex 0,0(\ruse)
j .
#endif
556: b \disp(\reg)
.endm
.macro GEN_BR_THUNK reg,ruse=%r1 .macro GEN_BR_THUNK reg,ruse=%r1
__DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
__THUNK_EX_BR \reg,\ruse __THUNK_EX_BR \reg,\ruse
__THUNK_EPILOG __THUNK_EPILOG
.endm .endm
.macro GEN_B_THUNK disp,reg,ruse=%r1
__DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
__THUNK_EX_BC \disp,\reg,\ruse
__THUNK_EPILOG
.endm
.macro BR_EX reg,ruse=%r1 .macro BR_EX reg,ruse=%r1
557: __DECODE_RR __THUNK_BR,\reg,\ruse 557: __DECODE_RR __THUNK_BR,\reg,\ruse
.pushsection .s390_indirect_branches,"a",@progbits .pushsection .s390_indirect_branches,"a",@progbits
.long 557b-. .long 557b-.
.popsection .popsection
.endm
.macro B_EX disp,reg,ruse=%r1
558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
.pushsection .s390_indirect_branches,"a",@progbits
.long 558b-.
.popsection
.endm .endm
.macro BASR_EX rsave,rtarget,ruse=%r1 .macro BASR_EX rsave,rtarget,ruse=%r1
...@@ -109,10 +159,17 @@ ...@@ -109,10 +159,17 @@
#else #else
.macro GEN_BR_THUNK reg,ruse=%r1 .macro GEN_BR_THUNK reg,ruse=%r1
.endm
.macro GEN_B_THUNK disp,reg,ruse=%r1
.endm .endm
.macro BR_EX reg,ruse=%r1 .macro BR_EX reg,ruse=%r1
br \reg br \reg
.endm
.macro B_EX disp,reg,ruse=%r1
b \disp(\reg)
.endm .endm
.macro BASR_EX rsave,rtarget,ruse=%r1 .macro BASR_EX rsave,rtarget,ruse=%r1
......
...@@ -94,7 +94,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end) ...@@ -94,7 +94,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
s32 *epo; s32 *epo;
/* Second part of the instruction replace is always a nop */ /* Second part of the instruction replace is always a nop */
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
for (epo = start; epo < end; epo++) { for (epo = start; epo < end; epo++) {
instr = (u8 *) epo + *epo; instr = (u8 *) epo + *epo;
if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04) if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
...@@ -115,18 +114,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end) ...@@ -115,18 +114,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
br = thunk + (*(int *)(thunk + 2)) * 2; br = thunk + (*(int *)(thunk + 2)) * 2;
else else
continue; continue;
if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0) /* Check for unconditional branch 0x07f? or 0x47f???? */
if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
continue; continue;
memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
switch (type) { switch (type) {
case BRCL_EXPOLINE: case BRCL_EXPOLINE:
/* brcl to thunk, replace with br + nop */
insnbuf[0] = br[0]; insnbuf[0] = br[0];
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
if (br[0] == 0x47) {
/* brcl to b, replace with bc + nopr */
insnbuf[2] = br[2];
insnbuf[3] = br[3];
} else {
/* brcl to br, replace with bcr + nop */
}
break; break;
case BRASL_EXPOLINE: case BRASL_EXPOLINE:
/* brasl to thunk, replace with basr + nop */
insnbuf[0] = 0x0d;
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f); insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
if (br[0] == 0x47) {
/* brasl to b, replace with bas + nopr */
insnbuf[0] = 0x4d;
insnbuf[2] = br[2];
insnbuf[3] = br[3];
} else {
/* brasl to br, replace with basr + nop */
insnbuf[0] = 0x0d;
}
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment