Skip to content

Commit b7969b5

Browse files
author
Yonghong Song
committed
[BPF] Add support for asm gotol_or_nop and nop_or_gotol insns
Two new insns are added to BPF instruction set: gotol_or_nop encoding: gotol encoding with src_reg = 1 nop_or_gotol encoding: gotol encoding with src_reg = 3 Basically src_reg 'bit_0 == 1' means it is gotol_or_nop/nop_or_gotol insn. The src_reg 'bit_1' indicates the insn itself will be a 'goto' 'bit_1 == 0' or a 'nop' 'bit_1 == 1'. Two insns intend to support kernel static key like transformation where the insn can be a nop or a ja. The following is an example, where two labels, static_key_loc_1 and static_key_loc_2, can be used to identify the location of a particular gotol_or_nop/nop_or_gotol location. It is possible that user space could do static_key_enable("static_key_loc_1") libbpf can validate that the label "static_key_loc_1" indeed corresponds to a gotol_or_nop/nop_or_gotol insn and it can translated the 'static_key_enable("static_key_loc_1")' to something like bpf syscall command 'static_key_enable prog, insn offset 1' and kernel will do proper adjustment. the same for static_key_disable, static_key_enabled, etc. ``` $ cat t.c int bar(void); int foo1(int arg1) { int a = arg1, b; asm volatile goto ("r0 = 0; \ static_key_loc_1: \ gotol_or_nop %l[label]; \ r2 = 2; \ r3 = 3; \ ":: : "r0", "r2", "r3" :label); a = bar(); label: b = 20 * a; return b; } int foo2(int arg1) { int a = arg1, b; asm volatile goto ("r0 = 0; \ static_key_loc_2: \ nop_or_gotol %l[label]; \ r2 = 2; \ r3 = 3; \ ":: : "r0", "r2", "r3" :label); a = bar(); label: b = 20 * a; return b; } $ clang --target=bpf -O2 -g -c t.c $ llvm-objdump -S t.o t.o: file format elf64-bpf Disassembly of section .text: 0000000000000000 <foo1>: ; asm volatile goto ("r0 = 0; \ 0: b7 00 00 00 00 00 00 00 r0 = 0x0 0000000000000008 <static_key_loc_1>: 1: 06 10 00 00 04 00 00 00 gotol_or_nop +0x4 <LBB0_2> 2: b7 02 00 00 02 00 00 00 r2 = 0x2 3: b7 03 00 00 03 00 00 00 r3 = 0x3 ; a = bar(); 4: 85 10 00 00 ff ff ff ff call -0x1 5: bf 01 00 00 00 00 00 00 r1 = r0 0000000000000030 <LBB0_2>: ; b = 20 * a; 6: 27 01 00 00 14 00 00 00 r1 *= 0x14 ; return b; 7: bf 10 00 00 00 00 00 00 r0 = r1 8: 95 00 00 00 00 00 00 00 exit 0000000000000048 <foo2>: ; asm volatile goto ("r0 = 0; \ 9: b7 00 00 00 00 00 00 00 r0 = 0x0 0000000000000050 <static_key_loc_2>: 10: 06 30 00 00 04 00 00 00 nop_or_gotol +0x4 <LBB1_2> 11: b7 02 00 00 02 00 00 00 r2 = 0x2 12: b7 03 00 00 03 00 00 00 r3 = 0x3 ; a = bar(); 13: 85 10 00 00 ff ff ff ff call -0x1 14: bf 01 00 00 00 00 00 00 r1 = r0 0000000000000078 <LBB1_2>: ; b = 20 * a; 15: 27 01 00 00 14 00 00 00 r1 *= 0x14 ; return b; 16: bf 10 00 00 00 00 00 00 r0 = r1 17: 95 00 00 00 00 00 00 00 exit ```
1 parent 6e761f3 commit b7969b5

File tree

4 files changed

+36
-2
lines changed

4 files changed

+36
-2
lines changed

llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ struct BPFOperand : public MCParsedAsmOperand {
231231
.Case("call", true)
232232
.Case("goto", true)
233233
.Case("gotol", true)
234+
.Case("gotol_or_nop", true)
235+
.Case("nop_or_gotol", true)
234236
.Case("*", true)
235237
.Case("exit", true)
236238
.Case("lock", true)
@@ -259,6 +261,8 @@ struct BPFOperand : public MCParsedAsmOperand {
259261
.Case("bswap64", true)
260262
.Case("goto", true)
261263
.Case("gotol", true)
264+
.Case("gotol_or_nop", true)
265+
.Case("nop_or_gotol", true)
262266
.Case("ll", true)
263267
.Case("skb", true)
264268
.Case("s", true)

llvm/lib/Target/BPF/BPFInstrInfo.td

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,32 @@ class BRANCH_LONG<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
604604
let BPFClass = BPF_JMP32;
605605
}
606606

607+
class BRANCH_OR_NOP<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
608+
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
609+
(outs),
610+
(ins brtarget:$BrDst),
611+
!strconcat(OpcodeStr, " $BrDst"),
612+
Pattern> {
613+
bits<32> BrDst;
614+
615+
let Inst{55-52} = 1;
616+
let Inst{31-0} = BrDst;
617+
let BPFClass = BPF_JMP32;
618+
}
619+
620+
class NOP_OR_BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
621+
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
622+
(outs),
623+
(ins brtarget:$BrDst),
624+
!strconcat(OpcodeStr, " $BrDst"),
625+
Pattern> {
626+
bits<32> BrDst;
627+
628+
let Inst{55-52} = 3;
629+
let Inst{31-0} = BrDst;
630+
let BPFClass = BPF_JMP32;
631+
}
632+
607633
class CALL<string OpcodeStr>
608634
: TYPE_ALU_JMP<BPF_CALL.Value, BPF_K.Value,
609635
(outs),
@@ -632,6 +658,8 @@ class CALLX<string OpcodeStr>
632658
let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in {
633659
def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>;
634660
def JMPL : BRANCH_LONG<BPF_JA, "gotol", []>;
661+
def JMPL_OR_NOP : BRANCH_OR_NOP<BPF_JA, "gotol_or_nop", []>;
662+
def NOP_OR_JMPL : NOP_OR_BRANCH<BPF_JA, "nop_or_gotol", []>;
635663
}
636664

637665
// Jump and link

llvm/lib/Target/BPF/MCTargetDesc/BPFInstPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ void BPFInstPrinter::printBrTargetOperand(const MCInst *MI, unsigned OpNo,
103103
raw_ostream &O) {
104104
const MCOperand &Op = MI->getOperand(OpNo);
105105
if (Op.isImm()) {
106-
if (MI->getOpcode() == BPF::JMPL) {
106+
if (MI->getOpcode() == BPF::JMPL || MI->getOpcode() == BPF::JMPL_OR_NOP ||
107+
MI->getOpcode() == BPF::NOP_OR_JMPL) {
107108
int32_t Imm = Op.getImm();
108109
O << ((Imm >= 0) ? "+" : "") << formatImm(Imm);
109110
} else {

llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI,
9696
Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_4));
9797
else if (MI.getOpcode() == BPF::LD_imm64)
9898
Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_8));
99-
else if (MI.getOpcode() == BPF::JMPL)
99+
else if (MI.getOpcode() == BPF::JMPL || MI.getOpcode() == BPF::JMPL_OR_NOP ||
100+
MI.getOpcode() == BPF::NOP_OR_JMPL)
100101
Fixups.push_back(MCFixup::create(0, Expr, (MCFixupKind)BPF::FK_BPF_PCRel_4));
101102
else
102103
// bb label

0 commit comments

Comments
 (0)