diff --git a/.github/workflows/build-aya-bpf.yml b/.github/workflows/build-aya-bpf.yml index 1f147d3d..1de4c951 100644 --- a/.github/workflows/build-aya-bpf.yml +++ b/.github/workflows/build-aya-bpf.yml @@ -21,8 +21,7 @@ jobs: - x86_64 - aarch64 - arm - # Disable riscv64 due to missing pt_regs handling in aya-bpf/args.rs - # - riscv64 + - riscv64 runs-on: ubuntu-20.04 steps: diff --git a/bpf/aya-bpf-cty/src/lib.rs b/bpf/aya-bpf-cty/src/lib.rs index 7828e0ee..df48d030 100644 --- a/bpf/aya-bpf-cty/src/lib.rs +++ b/bpf/aya-bpf-cty/src/lib.rs @@ -26,6 +26,9 @@ mod ad { #[cfg(bpf_target_arch = "aarch64")] pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "riscv64")] + pub type c_char = super::c_uchar; + #[cfg(any(bpf_target_arch = "x86", bpf_target_arch = "x86_64"))] pub type c_char = super::c_schar; diff --git a/bpf/aya-bpf/src/args.rs b/bpf/aya-bpf/src/args.rs index fea024eb..437fe329 100644 --- a/bpf/aya-bpf/src/args.rs +++ b/bpf/aya-bpf/src/args.rs @@ -1,11 +1,15 @@ use crate::{cty::c_void, helpers::bpf_probe_read}; // aarch64 uses user_pt_regs instead of pt_regs -#[cfg(not(bpf_target_arch = "aarch64"))] +#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] use crate::bindings::pt_regs; + #[cfg(bpf_target_arch = "aarch64")] use crate::bindings::user_pt_regs as pt_regs; +#[cfg(bpf_target_arch = "riscv64")] +use crate::bindings::user_regs_struct as pt_regs; + /// A trait that indicates a valid type for an argument which can be coerced from a BTF /// context. /// @@ -60,7 +64,7 @@ pub struct PtRegs { regs: *mut pt_regs, } -/// A portable wrapper around pt_regs and user_pt_regs. +/// A portable wrapper around pt_regs, user_pt_regs and user_regs_struct. impl PtRegs { pub fn new(regs: *mut pt_regs) -> Self { PtRegs { regs } @@ -146,6 +150,27 @@ impl FromPtRegs for *const T { } } +#[cfg(bpf_target_arch = "riscv64")] +impl FromPtRegs for *const T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + match n { + 0 => unsafe { bpf_probe_read(&ctx.a0).map(|v| v as *const _).ok() }, + 1 => unsafe { bpf_probe_read(&ctx.a1).map(|v| v as *const _).ok() }, + 2 => unsafe { bpf_probe_read(&ctx.a2).map(|v| v as *const _).ok() }, + 3 => unsafe { bpf_probe_read(&ctx.a3).map(|v| v as *const _).ok() }, + 4 => unsafe { bpf_probe_read(&ctx.a4).map(|v| v as *const _).ok() }, + 5 => unsafe { bpf_probe_read(&ctx.a5).map(|v| v as *const _).ok() }, + 6 => unsafe { bpf_probe_read(&ctx.a6).map(|v| v as *const _).ok() }, + 7 => unsafe { bpf_probe_read(&ctx.a7).map(|v| v as *const _).ok() }, + _ => None, + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.ra).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 { @@ -195,6 +220,27 @@ impl FromPtRegs for *mut T { } } +#[cfg(bpf_target_arch = "riscv64")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + match n { + 0 => unsafe { bpf_probe_read(&ctx.a0).map(|v| v as *mut _).ok() }, + 1 => unsafe { bpf_probe_read(&ctx.a1).map(|v| v as *mut _).ok() }, + 2 => unsafe { bpf_probe_read(&ctx.a2).map(|v| v as *mut _).ok() }, + 3 => unsafe { bpf_probe_read(&ctx.a3).map(|v| v as *mut _).ok() }, + 4 => unsafe { bpf_probe_read(&ctx.a4).map(|v| v as *mut _).ok() }, + 5 => unsafe { bpf_probe_read(&ctx.a5).map(|v| v as *mut _).ok() }, + 6 => unsafe { bpf_probe_read(&ctx.a6).map(|v| v as *mut _).ok() }, + 7 => unsafe { bpf_probe_read(&ctx.a7).map(|v| v as *mut _).ok() }, + _ => None, + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.ra).map(|v| v as *mut _).ok() } + } +} + /// Helper macro to implement [`FromPtRegs`] for a primitive type. macro_rules! impl_from_pt_regs { ($type:ident) => { @@ -246,6 +292,27 @@ macro_rules! impl_from_pt_regs { Some(ctx.regs[0] as *const $type as _) } } + + #[cfg(bpf_target_arch = "riscv64")] + impl FromPtRegs for $type { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + match n { + 0 => Some(ctx.a0 as *const $type as _), + 1 => Some(ctx.a1 as *const $type as _), + 2 => Some(ctx.a2 as *const $type as _), + 3 => Some(ctx.a3 as *const $type as _), + 4 => Some(ctx.a4 as *const $type as _), + 5 => Some(ctx.a5 as *const $type as _), + 6 => Some(ctx.a6 as *const $type as _), + 7 => Some(ctx.a7 as *const $type as _), + _ => None, + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + Some(ctx.ra as *const $type as _) + } + } }; } diff --git a/bpf/aya-bpf/src/programs/probe.rs b/bpf/aya-bpf/src/programs/probe.rs index 77d9334b..25694845 100644 --- a/bpf/aya-bpf/src/programs/probe.rs +++ b/bpf/aya-bpf/src/programs/probe.rs @@ -2,12 +2,15 @@ use core::ffi::c_void; use crate::{args::FromPtRegs, BpfContext}; -// aarch64 uses user_pt_regs instead of pt_regs -#[cfg(not(bpf_target_arch = "aarch64"))] +#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] use crate::bindings::pt_regs; + #[cfg(bpf_target_arch = "aarch64")] use crate::bindings::user_pt_regs as pt_regs; +#[cfg(bpf_target_arch = "riscv64")] +use crate::bindings::user_regs_struct as pt_regs; + pub struct ProbeContext { pub regs: *mut pt_regs, }