diff --git a/.cargo/config.toml b/.cargo/config.toml index 0c1258f66..674071ffa 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -9,3 +9,9 @@ linker = "arm-linux-gnueabihf-gcc" [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-musl-gcc" + +[target.powerpc64le-unknown-linux-gnu] +linker = "powerpc64le-linux-gnu-gcc" + +[target.s390x-unknown-linux-gnu] +linker = "s390x-linux-gnu-gcc" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68553fb9f..3e21cff5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,6 +72,8 @@ jobs: - aarch64-unknown-linux-gnu - armv7-unknown-linux-gnueabi - riscv64gc-unknown-linux-gnu + - powerpc64le-unknown-linux-gnu + - s390x-unknown-linux-gnu runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -135,6 +137,8 @@ jobs: - aarch64 - arm - riscv64 + - powerpc64 + - s390x target: - bpfel-unknown-none - bpfeb-unknown-none diff --git a/Cargo.toml b/Cargo.toml index 082ab9bd1..7ee4e6b9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ default-members = [ # ebpf crates are omitted; they must be built with: # --target bpfe{b,l}-unknown-none - # CARGO_CFG_BPF_TARGET_ARCH={x86_64,aarch64,arm,riscv64} + # CARGO_CFG_BPF_TARGET_ARCH={x86_64,aarch64,arm,riscv64,powerpc64,s390x} ] [workspace.package] diff --git a/aya-obj/src/btf/relocation.rs b/aya-obj/src/btf/relocation.rs index c9412c79b..c78431dff 100644 --- a/aya-obj/src/btf/relocation.rs +++ b/aya-obj/src/btf/relocation.rs @@ -1215,7 +1215,7 @@ impl ComputedRelocation { } #[cfg(target_endian = "big")] FieldLShift64 => { - value.value = (8 - byte_size) * 8 + (bit_off - byte_off * 8); + value.value = ((8 - byte_size) * 8 + (bit_off - byte_off * 8)) as u64; } FieldRShift64 => { value.value = 64 - bit_size as u64; diff --git a/aya-obj/src/generated/mod.rs b/aya-obj/src/generated/mod.rs index f90979376..bbb693b35 100644 --- a/aya-obj/src/generated/mod.rs +++ b/aya-obj/src/generated/mod.rs @@ -13,8 +13,12 @@ mod btf_internal_bindings; mod linux_bindings_aarch64; #[cfg(target_arch = "arm")] mod linux_bindings_armv7; +#[cfg(target_arch = "powerpc64")] +mod linux_bindings_powerpc64; #[cfg(target_arch = "riscv64")] mod linux_bindings_riscv64; +#[cfg(target_arch = "s390x")] +mod linux_bindings_s390x; #[cfg(target_arch = "x86_64")] mod linux_bindings_x86_64; @@ -25,7 +29,11 @@ pub use btf_internal_bindings::{bpf_core_relo, bpf_core_relo_kind, btf_ext_heade pub use linux_bindings_aarch64::*; #[cfg(target_arch = "arm")] pub use linux_bindings_armv7::*; +#[cfg(target_arch = "powerpc64")] +pub use linux_bindings_powerpc64::*; #[cfg(target_arch = "riscv64")] pub use linux_bindings_riscv64::*; +#[cfg(target_arch = "s390x")] +pub use linux_bindings_s390x::*; #[cfg(target_arch = "x86_64")] pub use linux_bindings_x86_64::*; diff --git a/ebpf/aya-ebpf-bindings/build.rs b/ebpf/aya-ebpf-bindings/build.rs index fde2d9e54..e491077d8 100644 --- a/ebpf/aya-ebpf-bindings/build.rs +++ b/ebpf/aya-ebpf-bindings/build.rs @@ -9,5 +9,5 @@ fn main() { let arch = arch.split_once('-').map_or(&*arch, |x| x.0); println!("cargo:rustc-cfg=bpf_target_arch=\"{arch}\""); } - println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\"))"); + println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\",\"powerpc64\",\"s390x\"))"); } diff --git a/ebpf/aya-ebpf-bindings/src/lib.rs b/ebpf/aya-ebpf-bindings/src/lib.rs index b9037baca..0add58d9d 100644 --- a/ebpf/aya-ebpf-bindings/src/lib.rs +++ b/ebpf/aya-ebpf-bindings/src/lib.rs @@ -14,13 +14,23 @@ mod aarch64; #[cfg(bpf_target_arch = "riscv64")] mod riscv64; +#[cfg(bpf_target_arch = "powerpc64")] +mod powerpc64; + +#[cfg(bpf_target_arch = "s390x")] +mod s390x; + mod gen { #[cfg(bpf_target_arch = "aarch64")] pub use super::aarch64::*; #[cfg(bpf_target_arch = "arm")] pub use super::armv7::*; + #[cfg(bpf_target_arch = "powerpc64")] + pub use super::powerpc64::*; #[cfg(bpf_target_arch = "riscv64")] pub use super::riscv64::*; + #[cfg(bpf_target_arch = "s390x")] + pub use super::s390x::*; #[cfg(bpf_target_arch = "x86_64")] pub use super::x86_64::*; } diff --git a/ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs b/ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs new file mode 100644 index 000000000..226884eae --- /dev/null +++ b/ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs @@ -0,0 +1,3 @@ +#![allow(clippy::all, dead_code)] +pub mod bindings; +pub mod helpers; diff --git a/ebpf/aya-ebpf-bindings/src/s390x/mod.rs b/ebpf/aya-ebpf-bindings/src/s390x/mod.rs new file mode 100644 index 000000000..226884eae --- /dev/null +++ b/ebpf/aya-ebpf-bindings/src/s390x/mod.rs @@ -0,0 +1,3 @@ +#![allow(clippy::all, dead_code)] +pub mod bindings; +pub mod helpers; diff --git a/ebpf/aya-ebpf-cty/build.rs b/ebpf/aya-ebpf-cty/build.rs index 1488a7f2d..8642bdbec 100644 --- a/ebpf/aya-ebpf-cty/build.rs +++ b/ebpf/aya-ebpf-cty/build.rs @@ -9,6 +9,6 @@ fn main() { let arch = arch.split_once('-').map_or(&*arch, |x| x.0); println!("cargo:rustc-cfg=bpf_target_arch=\"{arch}\""); } - println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\"))"); + println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\",\"powerpc64\",\"s390x\"))"); println!("cargo::rustc-check-cfg=cfg(target_arch, values(\"asmjs\",\"nvptx\",\"xtensa\"))"); } diff --git a/ebpf/aya-ebpf-cty/src/lib.rs b/ebpf/aya-ebpf-cty/src/lib.rs index b2530c12d..d25b85057 100644 --- a/ebpf/aya-ebpf-cty/src/lib.rs +++ b/ebpf/aya-ebpf-cty/src/lib.rs @@ -24,9 +24,15 @@ mod ad { #[cfg(bpf_target_arch = "aarch64")] pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "powerpc64")] + pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "riscv64")] pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "s390x")] + pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "x86_64")] pub type c_char = super::c_schar; } diff --git a/ebpf/aya-ebpf/build.rs b/ebpf/aya-ebpf/build.rs index e087046ac..38887c3bc 100644 --- a/ebpf/aya-ebpf/build.rs +++ b/ebpf/aya-ebpf/build.rs @@ -10,7 +10,7 @@ fn main() { let arch = arch.split_once('-').map_or(&*arch, |x| x.0); println!("cargo:rustc-cfg=bpf_target_arch=\"{arch}\""); } - println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\"))"); + println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\",\"powerpc64\",\"s390x\"))"); println!("cargo::rustc-check-cfg=cfg(unstable)"); } diff --git a/ebpf/aya-ebpf/src/args.rs b/ebpf/aya-ebpf/src/args.rs index 7cee97a83..72023e0d7 100644 --- a/ebpf/aya-ebpf/src/args.rs +++ b/ebpf/aya-ebpf/src/args.rs @@ -1,8 +1,13 @@ -// aarch64 uses user_pt_regs instead of pt_regs -#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] +#[cfg(any( + bpf_target_arch = "x86_64", + bpf_target_arch = "arm", + bpf_target_arch = "powerpc64" +))] use crate::bindings::pt_regs; -#[cfg(bpf_target_arch = "aarch64")] +// aarch64 uses user_pt_regs instead of pt_regs +#[cfg(any(bpf_target_arch = "aarch64", bpf_target_arch = "s390x"))] use crate::bindings::user_pt_regs as pt_regs; +// riscv64 uses user_regs_struct instead of pt_regs #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; use crate::{cty::c_void, helpers::bpf_probe_read}; @@ -168,6 +173,36 @@ impl FromPtRegs for *const T { } } +#[cfg(bpf_target_arch = "powerpc64")] +impl FromPtRegs for *const T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + unsafe { bpf_probe_read(&ctx.gpr[3 + n]).map(|v| v as *const _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gpr[3]).map(|v| v as *const _).ok() } + } +} + +#[cfg(bpf_target_arch = "s390x")] +impl FromPtRegs for *const T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 4 { + unsafe { bpf_probe_read(&ctx.gprs[2 + n]).map(|v| v as *const _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gprs[2]).map(|v| v as *const _).ok() } + } +} + #[cfg(bpf_target_arch = "x86_64")] impl FromPtRegs for *mut T { fn from_argument(ctx: &pt_regs, n: usize) -> Option { @@ -238,6 +273,36 @@ impl FromPtRegs for *mut T { } } +#[cfg(bpf_target_arch = "powerpc64")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + unsafe { bpf_probe_read(&ctx.gpr[3 + n]).map(|v| v as *mut _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gpr[3]).map(|v| v as *mut _).ok() } + } +} + +#[cfg(bpf_target_arch = "s390x")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 4 { + unsafe { bpf_probe_read(&ctx.gprs[2 + n]).map(|v| v as *mut _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gprs[2]).map(|v| v as *mut _).ok() } + } +} + /// Helper macro to implement [`FromPtRegs`] for a primitive type. macro_rules! impl_from_pt_regs { ($type:ident) => { @@ -310,6 +375,36 @@ macro_rules! impl_from_pt_regs { Some(ctx.ra as *const $type as _) } } + + #[cfg(bpf_target_arch = "powerpc64")] + impl FromPtRegs for $type { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + Some(ctx.gpr[3 + n] as *const $type as _) + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + Some(ctx.gpr[3] as *const $type as _) + } + } + + #[cfg(bpf_target_arch = "s390x")] + impl FromPtRegs for $type { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 4 { + Some(ctx.gprs[2 + n] as *const $type as _) + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + Some(ctx.gprs[2] as *const $type as _) + } + } }; } diff --git a/ebpf/aya-ebpf/src/programs/probe.rs b/ebpf/aya-ebpf/src/programs/probe.rs index 3f9b965bd..8507c0be0 100644 --- a/ebpf/aya-ebpf/src/programs/probe.rs +++ b/ebpf/aya-ebpf/src/programs/probe.rs @@ -1,9 +1,15 @@ use core::ffi::c_void; -#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] +#[cfg(any( + bpf_target_arch = "x86_64", + bpf_target_arch = "arm", + bpf_target_arch = "powerpc64" +))] use crate::bindings::pt_regs; -#[cfg(bpf_target_arch = "aarch64")] +// aarch64 uses user_pt_regs instead of pt_regs +#[cfg(any(bpf_target_arch = "aarch64", bpf_target_arch = "s390x"))] use crate::bindings::user_pt_regs as pt_regs; +// riscv64 uses user_regs_struct instead of pt_regs #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; use crate::{args::FromPtRegs, EbpfContext}; diff --git a/ebpf/aya-ebpf/src/programs/retprobe.rs b/ebpf/aya-ebpf/src/programs/retprobe.rs index 2cff9b559..f271473b6 100644 --- a/ebpf/aya-ebpf/src/programs/retprobe.rs +++ b/ebpf/aya-ebpf/src/programs/retprobe.rs @@ -1,9 +1,15 @@ use core::ffi::c_void; -#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] +#[cfg(any( + bpf_target_arch = "x86_64", + bpf_target_arch = "arm", + bpf_target_arch = "powerpc64" +))] use crate::bindings::pt_regs; -#[cfg(bpf_target_arch = "aarch64")] +// aarch64 uses user_pt_regs instead of pt_regs +#[cfg(any(bpf_target_arch = "aarch64", bpf_target_arch = "s390x"))] use crate::bindings::user_pt_regs as pt_regs; +// riscv64 uses user_regs_struct instead of pt_regs #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; use crate::{args::FromPtRegs, EbpfContext};