Skip to content

Commit

Permalink
rust: add tracepoint support
Browse files Browse the repository at this point in the history
Make it possible to have Rust code call into tracepoints defined by C
code. It is still required that the tracepoint is declared in a C
header, and that this header is included in the input to bindgen.

Signed-off-by: Alice Ryhl <[email protected]>
  • Loading branch information
Darksonn committed Jun 3, 2024
1 parent c3ded95 commit a528226
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
1 change: 1 addition & 0 deletions rust/bindings/bindings_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/refcount.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/tracepoint.h>
#include <linux/wait.h>
#include <linux/workqueue.h>

Expand Down
1 change: 1 addition & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub mod str;
pub mod sync;
pub mod task;
pub mod time;
pub mod tracepoint;
pub mod types;
pub mod workqueue;

Expand Down
80 changes: 80 additions & 0 deletions rust/kernel/tracepoint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0

// Copyright (C) 2024 Google LLC.

//! Logic for tracepoints.
/// Declare the Rust entry point for a tracepoint.
#[macro_export]
macro_rules! declare_trace {
($(#[$attr:meta])* $pub:vis fn $name:ident($($argname:ident : $argtyp:ty),* $(,)?);) => {
$crate::macros::paste! {
$( #[$attr] )*
#[inline(always)]
$pub fn [< trace_ $name >]($($argname : $argtyp),*) {
#[cfg(CONFIG_TRACEPOINTS)]
{
use $crate::bindings::*;

let should_trace = unsafe {
$crate::static_key::static_key_false!(
[< __tracepoint_ $name >],
$crate::bindings::tracepoint,
key
)
};

if should_trace {
// TODO: cpu_online(raw_smp_processor_id())
let cond = true;
$crate::tracepoint::do_trace!($name($($argname : $argtyp),*), cond);
}
}
}
}
}
}

#[doc(hidden)]
#[macro_export]
macro_rules! do_trace {
($name:ident($($argname:ident : $argtyp:ty),* $(,)?), $cond:expr) => {{
if !$cond {
return;
}

// SAFETY: This call is balanced with the call below.
unsafe { $crate::bindings::preempt_disable_notrace() };

#[cfg(CONFIG_HAVE_STATIC_CALL)]
unsafe {
let it_func_ptr: *mut $crate::bindings::tracepoint_func =
$crate::bindings::rcu_dereference_raw(
::core::ptr::addr_of!(
$crate::macros::concat_idents!(__tracepoint_, $name).funcs
)
);

if !it_func_ptr.is_null() {
let __data = (*it_func_ptr).data;
$crate::macros::paste! {
$crate::static_call::static_call! {
[< tp_func_ $name >] (__data, $($argname),*)
};
}
}
}

#[cfg(not(CONFIG_HAVE_STATIC_CALL))]
unsafe {
$crate::macros::concat_idents!(__traceiter_, $name)(
::core::ptr::null_mut(),
$($argname),*
);
}

unsafe { $crate::bindings::preempt_enable_notrace() };
}}
}

pub use {declare_trace, do_trace};

0 comments on commit a528226

Please sign in to comment.