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 951832bd4..66d725119 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,6 +71,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 @@ -134,6 +136,8 @@ jobs: - aarch64 - arm - riscv64 + - powerpc64 + - s390x target: - bpfel-unknown-none - bpfeb-unknown-none diff --git a/.github/workflows/gen.yml b/.github/workflows/gen.yml index 30763c412..3bb657ad9 100644 --- a/.github/workflows/gen.yml +++ b/.github/workflows/gen.yml @@ -29,7 +29,7 @@ jobs: - name: Install headers run: | sudo apt -y update - sudo apt -y install libc6-dev libc6-dev-{arm64,armel,riscv64}-cross + sudo apt -y install libc6-dev libc6-dev-{arm64,armel,riscv64,ppc64el,s390x}-cross - name: Run codegen run: | diff --git a/Cargo.toml b/Cargo.toml index a370735e6..532445d63 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/generated/linux_bindings_powerpc64.rs b/aya-obj/src/generated/linux_bindings_powerpc64.rs new file mode 100644 index 000000000..e69de29bb diff --git a/aya-obj/src/generated/linux_bindings_s390x.rs b/aya-obj/src/generated/linux_bindings_s390x.rs new file mode 100644 index 000000000..e69de29bb 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/bindings.rs b/ebpf/aya-ebpf-bindings/src/powerpc64/bindings.rs new file mode 100644 index 000000000..e69de29bb diff --git a/ebpf/aya-ebpf-bindings/src/powerpc64/helpers.rs b/ebpf/aya-ebpf-bindings/src/powerpc64/helpers.rs new file mode 100644 index 000000000..e69de29bb 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/bindings.rs b/ebpf/aya-ebpf-bindings/src/s390x/bindings.rs new file mode 100644 index 000000000..e69de29bb diff --git a/ebpf/aya-ebpf-bindings/src/s390x/helpers.rs b/ebpf/aya-ebpf-bindings/src/s390x/helpers.rs new file mode 100644 index 000000000..e69de29bb 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}; diff --git a/xtask/src/codegen/aya.rs b/xtask/src/codegen/aya.rs index be447bd59..935036d37 100644 --- a/xtask/src/codegen/aya.rs +++ b/xtask/src/codegen/aya.rs @@ -57,6 +57,8 @@ fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyh aarch64_sysroot, armv7_sysroot, riscv64_sysroot, + powerpc64_sysroot, + s390x_sysroot, } = opts; let types = [ // BPF @@ -179,6 +181,8 @@ fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyh Architecture::ARMv7 => "armv7-unknown-linux-gnu", Architecture::AArch64 => "aarch64-unknown-linux-gnu", Architecture::RISCV64 => "riscv64-unknown-linux-gnu", + Architecture::PowerPC64 => "powerpc64le-unknown-linux-gnu", + Architecture::S390X => "s390x-unknown-linux-gnu", }; bindgen = bindgen.clang_args(&["-target", target]); @@ -189,6 +193,8 @@ fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyh Architecture::ARMv7 => armv7_sysroot, Architecture::AArch64 => aarch64_sysroot, Architecture::RISCV64 => riscv64_sysroot, + Architecture::PowerPC64 => powerpc64_sysroot, + Architecture::S390X => s390x_sysroot, }; bindgen = bindgen.clang_args(&["-I", &*sysroot.to_string_lossy()]); diff --git a/xtask/src/codegen/aya_ebpf_bindings.rs b/xtask/src/codegen/aya_ebpf_bindings.rs index ced98b151..af400e421 100644 --- a/xtask/src/codegen/aya_ebpf_bindings.rs +++ b/xtask/src/codegen/aya_ebpf_bindings.rs @@ -17,6 +17,8 @@ pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::E aarch64_sysroot, armv7_sysroot, riscv64_sysroot, + powerpc64_sysroot, + s390x_sysroot, } = opts; let dir = PathBuf::from("ebpf/aya-ebpf-bindings"); @@ -80,6 +82,8 @@ pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::E Architecture::ARMv7 => "armv7-unknown-linux-gnu", Architecture::AArch64 => "aarch64-unknown-linux-gnu", Architecture::RISCV64 => "riscv64-unknown-linux-gnu", + Architecture::PowerPC64 => "powerpc64le-unknown-linux-gnu", + Architecture::S390X => "s390x-unknown-linux-gnu", }; bindgen = bindgen.clang_args(&["-target", target]); @@ -90,6 +94,8 @@ pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::E Architecture::ARMv7 => armv7_sysroot, Architecture::AArch64 => aarch64_sysroot, Architecture::RISCV64 => riscv64_sysroot, + Architecture::PowerPC64 => powerpc64_sysroot, + Architecture::S390X => s390x_sysroot, }; bindgen = bindgen.clang_args(&["-I", &*sysroot.to_string_lossy()]); diff --git a/xtask/src/codegen/mod.rs b/xtask/src/codegen/mod.rs index 4c2796844..b1cbd09de 100644 --- a/xtask/src/codegen/mod.rs +++ b/xtask/src/codegen/mod.rs @@ -11,6 +11,8 @@ const SUPPORTED_ARCHS: &[Architecture] = &[ Architecture::ARMv7, Architecture::AArch64, Architecture::RISCV64, + Architecture::PowerPC64, + Architecture::S390X, ]; #[derive(Debug, Copy, Clone)] @@ -19,6 +21,8 @@ pub enum Architecture { ARMv7, AArch64, RISCV64, + PowerPC64, + S390X, } impl Architecture { @@ -36,6 +40,8 @@ impl std::str::FromStr for Architecture { "armv7" => Architecture::ARMv7, "aarch64" => Architecture::AArch64, "riscv64" => Architecture::RISCV64, + "powerpc64" => Architecture::PowerPC64, + "s390x" => Architecture::S390X, _ => return Err("invalid architecture"), }) } @@ -48,6 +54,8 @@ impl std::fmt::Display for Architecture { Architecture::ARMv7 => "armv7", Architecture::AArch64 => "aarch64", Architecture::RISCV64 => "riscv64", + Architecture::PowerPC64 => "powerpc64", + Architecture::S390X => "s390x", }) } } @@ -67,6 +75,16 @@ pub struct SysrootOptions { #[arg(long, default_value = "/usr/riscv64-linux-gnu/include", action)] riscv64_sysroot: PathBuf, + + #[arg( + long, + default_value = "/usr/powerpc64le-unknown-linux-gnu/include", + action + )] + powerpc64_sysroot: PathBuf, + + #[arg(long, default_value = "/usr/s390x-unknown-linux-gnu/include", action)] + s390x_sysroot: PathBuf, } #[derive(Parser)]