Skip to content

Commit

Permalink
Merge pull request #20 from jpsamaroo/jps/bpfcall
Browse files Browse the repository at this point in the history
Add bpfcall and runtime buffers
  • Loading branch information
jpsamaroo authored Apr 13, 2021
2 parents 8ddd527 + a76a1a8 commit e4d5d1c
Show file tree
Hide file tree
Showing 14 changed files with 374 additions and 51 deletions.
18 changes: 11 additions & 7 deletions Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ version = "0.4.1"

[[Clang_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "libLLVM_jll"]
git-tree-sha1 = "b0db0edbfd3388b23f9578ec2ee7ff814f646649"
git-tree-sha1 = "a5923c06de3178dd755f4b9411ea8922a7ae6fb8"
uuid = "0ee61d77-7f21-5576-8119-9fcc46b10100"
version = "11.0.0+7"
version = "11.0.1+3"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "919c7f3151e79ff196add81d7f4e45d91bbf420b"
git-tree-sha1 = "ac4132ad78082518ec2037ae5770b6e796f7f956"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.25.0"
version = "3.27.0"

[[DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
Expand Down Expand Up @@ -83,9 +83,9 @@ version = "1.2.0"

[[LLVM]]
deps = ["CEnum", "Libdl", "Printf", "Unicode"]
git-tree-sha1 = "000a737732aa4eb996414c4685368f6a74b41d14"
git-tree-sha1 = "b616937c31337576360cb9fb872ec7633af7b194"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "3.4.0"
version = "3.6.0"

[[LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
Expand Down Expand Up @@ -142,7 +142,7 @@ uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.0"

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs"]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[Preferences]]
Expand Down Expand Up @@ -250,3 +250,7 @@ deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c417cbbce3efb49a309b2d478fea9df7cfe024c0"
uuid = "c88a4935-d25e-5644-aacc-5db6f1b8ef79"
version = "1.1.0+0"

[[p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "BPFnative"
uuid = "b6338580-32ea-11e9-1791-33a79977d8c4"
authors = ["Julian P Samaroo <[email protected]>"]
version = "0.1.1"
version = "0.1.2"

[deps]
CBinding = "d43a6710-96b8-4a2d-833c-c424785e5374"
Expand All @@ -15,7 +15,7 @@ Preferences = "21216c6a-2e73-6563-6e65-726566657250"
[compat]
CBinding = "1"
GPUCompiler = "0.9.1"
LLVM = "= 3.4"
LLVM = "3.6"
Libbpf_jll = "0.3"
Preferences = "1"
julia = "1.6"
Expand Down
10 changes: 6 additions & 4 deletions src/BPFnative.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,17 @@ end
# Runtime API
module RT
import ..API
include("runtime_maps.jl")
include("misc.jl")
include("runtime/bpfcall.jl")
include("runtime/maps.jl")
include("runtime/buffers.jl")
include("runtime/helpers.jl")
end

# Host API
module Host
import ..API
include("syscall.jl")
include("host_maps.jl")
include("host/syscall.jl")
include("host/maps.jl")
end

# Compiler
Expand Down
95 changes: 94 additions & 1 deletion src/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const bpffunction_cache = Dict{UInt,Any}()

# actual compilation
function bpffunction_compile(source::FunctionSpec; format=:obj, license="",
prog_section="prog", btf=true, kwargs...)
prog_section="prog", btf=false, kwargs...)
# compile to BPF
target = BPFCompilerTarget(; license, prog_section)
params = BPFCompilerParams()
Expand All @@ -49,3 +49,96 @@ function bpffunction_compile(source::FunctionSpec; format=:obj, license="",
return collect(codeunits(args[1]))
end
bpffunction_link(@nospecialize(source::FunctionSpec), exe; kwargs...) = exe

function GPUCompiler.finish_module!(job::BPFCompilerJob, mod::LLVM.Module)
#= TODO: Fix upstream and re-enable if needed
invoke(GPUCompiler.finish_module!,
Tuple{CompilerJob{BPFCompilerTarget}, LLVM.Module},
job, mod)
=#

for func in LLVM.functions(mod)
if LLVM.name(func) == "gpu_signal_exception"
throw(GPUCompiler.KernelError(job, "eBPF does not support exceptions"))
end
# Set entry section for loaders like libbpf
LLVM.section!(func, job.target.prog_section)
end

# Set license
license = job.target.license
if license != ""
ctx = LLVM.context(mod)
i8 = LLVM.Int8Type(ctx)
glob = GlobalVariable(mod, LLVM.ArrayType(i8, length(license)+1), "_license")
linkage!(glob, LLVM.API.LLVMExternalLinkage)
constant!(glob, true)
section!(glob, "license")
str = ConstantArray(Vector{UInt8}(license*'\0'), ctx)
@assert context(glob) == context(str) == ctx
initializer!(glob, str)
end

# Set all map definitions as external linkage
for gv in filter(x->(section(x)=="maps")||(section(x)==".maps"), collect(LLVM.globals(mod)))
linkage!(gv, LLVM.API.LLVMExternalLinkage)
end

ModulePassManager() do pm
if Base.JLOptions().debug_level > 1
# Validate contexts, for my sanity
add!(pm, ModulePass("BPFValidateContexts", validate_contexts!))
end
# Promote `@malloc` intrinsics
add!(pm, FunctionPass("BPFHeapToStack", heap_to_stack!))
run!(pm, mod)
end
end

"Validates LLVM contexts of all the things."
function validate_contexts!(mod::LLVM.Module)
ctx = LLVM.context(mod)
for fn in LLVM.functions(mod)
@assert context(fn) == ctx "Failed validation: $fn"
for bb in LLVM.blocks(fn)
for insn in LLVM.instructions(bb)
@assert context(insn) == ctx "Failed validation: $insn"
for op in LLVM.operands(insn)
@assert context(op) == ctx "Failed validation: $op"
end
end
end
end
for gv in LLVM.globals(mod)
@assert context(gv) == ctx "Failed validation: $gv"
end
false
end

"Promotes `@malloc` intrinsics to allocas."
function heap_to_stack!(fn::LLVM.Function)
changed = false
ctx = LLVM.context(fn)
for bb in LLVM.blocks(fn)
for insn in LLVM.instructions(bb)
if insn isa LLVM.CallInst && LLVM.name(LLVM.called_value(insn)) == "malloc"
sz = convert(Int64, LLVM.operands(insn)[1])
T_i8 = LLVM.Int8Type(ctx)
T_pi8 = LLVM.PointerType(T_i8)
T_buf = LLVM.ArrayType(T_i8, sz)
Builder(ctx) do builder
# Place alloca at beginning of entry
position!(builder, first(LLVM.instructions(first(LLVM.blocks(fn)))))
buf = alloca!(builder, T_buf)
# Replace malloc with bitcast'd alloca
position!(builder, insn)
new_insn = bitcast!(builder, buf, T_pi8)
replace_uses!(insn, new_insn)
unsafe_delete!(LLVM.parent(insn), insn)
end
changed = true
end
end
end
changed
end
2 changes: 1 addition & 1 deletion src/host_maps.jl → src/host/maps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ function Base.delete!(map::AbstractHashMap{K,V}, idx) where {K,V}
map
end

function Base.haskey(map::AbstractHashMap{K,V}, idx) where {K,V}
function Base.haskey(map::HostMap{K,V}, idx) where {K,V}
key = Ref{K}(idx)
value = Ref{V}()
key_ptr = Base.unsafe_convert(Ptr{K}, key)
Expand Down
File renamed without changes.
22 changes: 0 additions & 22 deletions src/misc.jl

This file was deleted.

16 changes: 8 additions & 8 deletions src/probes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ struct KProbe <: AbstractProbe
kfunc::String
retprobe::Bool
end
function KProbe(f::Function, kfunc; retprobe=false)
obj = API.Object(bpffunction(f, Tuple{API.pointertype(API.pt_regs)}; btf=false))
function KProbe(f::Function, kfunc; retprobe=false, kwargs...)
obj = API.Object(bpffunction(f, Tuple{API.pointertype(API.pt_regs)}; btf=false, kwargs...))
foreach(prog->API.set_kprobe!(prog), API.programs(obj))
KProbe(obj, kfunc, retprobe)
end
Expand All @@ -20,8 +20,8 @@ struct UProbe{F<:Function,T} <: AbstractProbe
sig::T
retprobe::Bool
end
function UProbe(f::Function, method, sig; retprobe=false)
obj = API.Object(bpffunction(f, Tuple{API.pointertype(API.pt_regs)}; btf=false))
function UProbe(f::Function, method, sig; retprobe=false, kwargs...)
obj = API.Object(bpffunction(f, Tuple{API.pointertype(API.pt_regs)}; btf=false, kwargs...))
#foreach(prog->API.set_uprobe!(prog), API.programs(obj))
foreach(prog->API.set_kprobe!(prog), API.programs(obj))
UProbe(obj, method, sig, retprobe)
Expand All @@ -31,18 +31,18 @@ struct Tracepoint <: AbstractProbe
category::String
name::String
end
function Tracepoint(f::Function, category, name)
obj = API.Object(bpffunction(f, Tuple{API.pointertype(API.pt_regs)}; btf=false))
function Tracepoint(f::Function, category, name; kwargs...)
obj = API.Object(bpffunction(f, Tuple{API.pointertype(API.pt_regs)}; btf=false, kwargs...))
foreach(prog->API.set_tracepoint!(prog), API.programs(obj))
Tracepoint(obj, category, name)
end

Base.show(io::IO, p::KProbe) =
print(io, "KProbe ($(p.kfunc)")
print(io, "KProbe ($(p.kfunc))")
Base.show(io::IO, p::UProbe) =
print(io, "UProbe ($(p.func)($(p.sig)))")
Base.show(io::IO, p::Tracepoint) =
print(io, "Tracepoint ($(p.category)/$(p.name)")
print(io, "Tracepoint ($(p.category)/$(p.name))")

function API.load(p::KProbe)
API.load(p.obj)
Expand Down
2 changes: 1 addition & 1 deletion src/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ for method in (:code_typed, :code_warntype, :code_llvm, :code_native)
function $method(io::IO, @nospecialize(func), @nospecialize(types);
kernel::Bool=false, kwargs...)
source = FunctionSpec(func, Base.to_tuple_type(types), kernel)
target = BPFCompilerTarget(; dev_isa=default_isa(default_device()))
target = BPFCompilerTarget()
params = BPFCompilerParams()
job = CompilerJob(target, source, params)
GPUCompiler.$method($(args...); kwargs...)
Expand Down
26 changes: 26 additions & 0 deletions src/runtime/bpfcall.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export bpfcall

@generated function _bpfcall(::Val{cmd}, ::Type{rettype}, ::Type{argtypes}, args::Vararg{Any}) where {cmd,rettype,argtypes}
JuliaContext() do ctx
T_ret = convert(LLVMType, rettype, ctx)
T_args = map(x->convert(LLVMType, x, ctx), argtypes.parameters)

llvm_f, _ = create_function(T_ret, LLVMType[T_args...])
mod = LLVM.parent(llvm_f)

Builder(ctx) do builder
entry = BasicBlock(llvm_f, "entry", ctx)
position!(builder, entry)
ft = LLVM.FunctionType(T_ret, LLVMType[T_args...])
ftp = LLVM.PointerType(ft)
f = inttoptr!(builder, ConstantInt(cmd, ctx), ftp)
value = call!(builder, f, LLVM.Value[parameters(llvm_f)...])
ret!(builder, value)
end
call_function(llvm_f, rettype, Base.to_tuple_type(args), :((args...,)))
end
end
@inline bpfcall(cmd::API.BPFHelper, RT, AT, args...) =
_bpfcall(Val(Int(cmd)), RT, AT, args...)
@inline bpfcall(cmd::API.BPFHelper, RT) = _bpfcall(Val(Int(cmd)), RT, Tuple{})
@inline bpfcall(cmd::API.BPFHelper) = _bpfcall(Val(Int(cmd)), Cvoid, Tuple{})
Loading

2 comments on commit e4d5d1c

@jpsamaroo
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/34189

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.1.2 -m "<description of version>" e4d5d1c156be1bbf9cc4d2b44f0831071052b59b
git push origin v0.1.2

Please sign in to comment.