twizzler_abi/syscall/
trace.rs

1use twizzler_rt_abi::{error::TwzError, object::ObjID};
2
3use super::{convert_codes_to_result, twzerr, Syscall};
4use crate::{
5    arch::syscall::raw_syscall,
6    trace::{TraceEntryHead, TraceFlags, TraceKind},
7};
8
9/// Tracing specification. Note that events can be disabled and enabled in one spec. It is
10/// unspecified if events are disabled or enabled first.
11#[derive(Debug, Clone, Copy)]
12pub struct TraceSpec {
13    /// The event kind to track.
14    pub kind: TraceKind,
15    /// Flags for this specification.
16    pub flags: TraceFlags,
17    /// Events to enable.
18    pub enable_events: u64,
19    /// Events to disable.
20    pub disable_events: u64,
21    /// Optionally restrict events to given security context.
22    pub sctx: Option<ObjID>,
23    /// Optionally restrict events to given memory context.
24    pub mctx: Option<ObjID>,
25    /// Optionally restrict events to given thread.
26    pub thread: Option<ObjID>,
27    /// Optionally restrict events to given CPU.
28    pub cpuid: Option<u64>,
29    /// Extra data passed in trace events that match this spec.
30    pub extra: ObjID,
31}
32
33impl TraceSpec {
34    /// Check if the given trace entry header matches this spec.
35    pub fn accepts(&self, header: &TraceEntryHead) -> bool {
36        if header.kind != self.kind {
37            return false;
38        }
39
40        let events_match = (self.enable_events & (header.event & !self.disable_events)) != 0;
41
42        let cpu_ok = self.cpuid.is_none_or(|x| x == header.cpuid);
43        let sctx_ok = self.sctx.is_none_or(|x| x == header.sctx);
44        let mctx_ok = self.mctx.is_none_or(|x| x == header.mctx);
45        let thread_ok = self.thread.is_none_or(|x| x == header.thread);
46
47        cpu_ok && sctx_ok && mctx_ok && thread_ok && events_match
48    }
49}
50
51/// Trace events in the kernel, storing them in the provided object.
52///
53/// If spec is Some(_), then that TraceSpec will be used to modify the traced events
54/// that will be placed into the object. Note that events can be disabled or enabled
55/// with fine grained control.
56///
57/// If spec is None, all associated tracing events to the supplied object are disabled.
58/// Any buffered trace events are flushed to the object.
59pub fn sys_ktrace(object: ObjID, spec: Option<&TraceSpec>) -> Result<(), TwzError> {
60    let [hi, lo] = object.parts();
61    let (code, val) = unsafe {
62        raw_syscall(
63            Syscall::Ktrace,
64            &[
65                hi,
66                lo,
67                spec.map(|spec| spec as *const _ as usize as u64)
68                    .unwrap_or(0),
69            ],
70        )
71    };
72    convert_codes_to_result(code, val, |c, _| c != 0, |_, _| (), twzerr)
73}