Skip to content

Commit 9a67245

Browse files
committedNov 19, 2017
[bpf] allow direct and indirect calls
kernel verifier is becoming smarter and soon will support direct and indirect function calls. Remove obsolete error from BPF backend. Make call to use PCRel_4 fixup. 'bpf to bpf' calls are distinguished from 'bpf to kernel' calls by insn->src_reg == BPF_PSEUDO_CALL == 1 which is used as relocation indicator similar to ld_imm64->src_reg == BPF_PSEUDO_MAP_FD == 1 The actual 'call' instruction remains the same for both 'bpf to kernel' and 'bpf to bpf' calls. Signed-off-by: Alexei Starovoitov <ast@kernel.org> llvm-svn: 318614
1 parent 9a94dfc commit 9a67245

12 files changed

+32
-18
lines changed
 

‎llvm/lib/Target/BPF/BPFISelLowering.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -330,13 +330,6 @@ SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
330330
// Likewise ExternalSymbol -> TargetExternalSymbol.
331331
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
332332
auto GV = G->getGlobal();
333-
fail(CLI.DL, DAG,
334-
"A call to global function '" + StringRef(GV->getName())
335-
+ "' is not supported. "
336-
+ (GV->isDeclaration() ?
337-
"Only calls to predefined BPF helpers are allowed." :
338-
"Please use __attribute__((always_inline) to make sure"
339-
" this function is inlined."));
340333
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT,
341334
G->getOffset(), 0);
342335
} else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {

‎llvm/lib/Target/BPF/BPFInstrInfo.td

+14
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,18 @@ class CALL<string OpcodeStr>
400400
let BPFClass = BPF_JMP;
401401
}
402402

403+
class CALLX<string OpcodeStr>
404+
: TYPE_ALU_JMP<BPF_CALL.Value, BPF_X.Value,
405+
(outs),
406+
(ins calltarget:$BrDst),
407+
!strconcat(OpcodeStr, " $BrDst"),
408+
[]> {
409+
bits<32> BrDst;
410+
411+
let Inst{31-0} = BrDst;
412+
let BPFClass = BPF_JMP;
413+
}
414+
403415
// Jump always
404416
let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in {
405417
def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>;
@@ -410,6 +422,7 @@ let isCall=1, hasDelaySlot=0, Uses = [R11],
410422
// Potentially clobbered registers
411423
Defs = [R0, R1, R2, R3, R4, R5] in {
412424
def JAL : CALL<"call">;
425+
def JALX : CALLX<"callx">;
413426
}
414427

415428
class NOP_I<string OpcodeStr>
@@ -476,6 +489,7 @@ def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)),
476489
def : Pat<(BPFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>;
477490
def : Pat<(BPFcall texternalsym:$dst), (JAL texternalsym:$dst)>;
478491
def : Pat<(BPFcall imm:$dst), (JAL imm:$dst)>;
492+
def : Pat<(BPFcall GPR:$dst), (JALX GPR:$dst)>;
479493

480494
// Loads
481495
def : Pat<(extloadi8 ADDRri:$src), (i64 (LDB ADDRri:$src))>;

‎llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
7676
unsigned Idx = IsLittleEndian ? i : Size - i - 1;
7777
Data[Fixup.getOffset() + Idx] = uint8_t(Value >> (i * 8));
7878
}
79+
} else if (Fixup.getKind() == FK_PCRel_4) {
80+
Value = (uint32_t)((Value - 8) / 8);
81+
if (IsLittleEndian) {
82+
Data[Fixup.getOffset() + 1] = 0x10;
83+
support::endian::write32le(&Data[Fixup.getOffset() + 4], Value);
84+
} else {
85+
Data[Fixup.getOffset() + 1] = 0x1;
86+
support::endian::write32be(&Data[Fixup.getOffset() + 4], Value);
87+
}
7988
} else {
8089
assert(Fixup.getKind() == FK_PCRel_2);
8190
Value = (uint16_t)((Value - 8) / 8);

‎llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
4444
llvm_unreachable("invalid fixup kind!");
4545
case FK_SecRel_8:
4646
return ELF::R_BPF_64_64;
47+
case FK_PCRel_4:
4748
case FK_SecRel_4:
4849
return ELF::R_BPF_64_32;
4950
case FK_Data_8:

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI,
100100

101101
if (MI.getOpcode() == BPF::JAL)
102102
// func call name
103-
Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_4));
103+
Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_4));
104104
else if (MI.getOpcode() == BPF::LD_imm64)
105105
Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_8));
106106
else

‎llvm/test/CodeGen/BPF/cc_args.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not llc < %s -march=bpfel -show-mc-encoding | FileCheck %s
1+
; RUN: llc < %s -march=bpfel -show-mc-encoding | FileCheck %s
22

33
define void @test() #0 {
44
entry:

‎llvm/test/CodeGen/BPF/cc_args_be.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not llc < %s -march=bpfeb -show-mc-encoding | FileCheck %s
1+
; RUN: llc < %s -march=bpfeb -show-mc-encoding | FileCheck %s
22
; test big endian
33

44
define void @test() #0 {

‎llvm/test/CodeGen/BPF/cc_ret.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not llc < %s -march=bpfel | FileCheck %s
1+
; RUN: llc < %s -march=bpfel | FileCheck %s
22

33
define void @test() #0 {
44
entry:

‎llvm/test/CodeGen/BPF/fi_ri.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not llc < %s -march=bpf | FileCheck %s
1+
; RUN: llc < %s -march=bpf | FileCheck %s
22

33
%struct.key_t = type { i32, [16 x i8] }
44

‎llvm/test/CodeGen/BPF/sanity.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not llc < %s -march=bpfel | FileCheck %s
1+
; RUN: llc < %s -march=bpfel | FileCheck %s
22

33
@foo_printf.fmt = private unnamed_addr constant [9 x i8] c"hello \0A\00", align 1
44

‎llvm/test/CodeGen/BPF/undef.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
; RUN: not llc < %s -march=bpfel | FileCheck -check-prefixes=CHECK,EL %s
2-
; RUN: not llc < %s -march=bpfeb | FileCheck -check-prefixes=CHECK,EB %s
1+
; RUN: llc < %s -march=bpfel | FileCheck -check-prefixes=CHECK,EL %s
2+
; RUN: llc < %s -march=bpfeb | FileCheck -check-prefixes=CHECK,EB %s
33

44
%struct.bpf_map_def = type { i32, i32, i32, i32 }
55
%struct.__sk_buff = type opaque

‎llvm/test/CodeGen/BPF/warn-call.ll

-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
; CHECK: error: warn_call.c
44
; CHECK: built-in function 'memcpy'
5-
; CHECK: error: warn_call.c
6-
; CHECK: global function 'foo'
7-
; CHECK: global function 'bar'
85
define i8* @warn(i8* returned, i8*, i64) local_unnamed_addr #0 !dbg !6 {
96
tail call void @llvm.dbg.value(metadata i8* %0, i64 0, metadata !14, metadata !17), !dbg !18
107
tail call void @llvm.dbg.value(metadata i8* %1, i64 0, metadata !15, metadata !17), !dbg !19

0 commit comments

Comments
 (0)
Please sign in to comment.