#![allow(non_upper_case_globals)]
use core::fmt;
use core::mem;
use crate::PerfByteReader;
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventAttrType(pub u32);
impl PerfEventAttrType {
pub const Hardware: Self = Self(0);
pub const Software: Self = Self(1);
pub const Tracepoint: Self = Self(2);
pub const HwCache: Self = Self(3);
pub const Raw: Self = Self(4);
pub const Breakpoint: Self = Self(5);
pub const fn as_string(self) -> Option<&'static str> {
const NAMES: [&str; 6] = [
"Hardware",
"Software",
"Tracepoint",
"HwCache",
"Raw",
"Breakpoint",
];
let index = self.0 as usize;
if index < NAMES.len() {
return Some(NAMES[index]);
} else {
return None;
}
}
}
impl From<u32> for PerfEventAttrType {
fn from(val: u32) -> Self {
Self(val)
}
}
impl From<PerfEventAttrType> for u32 {
fn from(val: PerfEventAttrType) -> Self {
val.0
}
}
impl fmt::Display for PerfEventAttrType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(s) = self.as_string() {
return f.pad(s);
} else {
return self.0.fmt(f);
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventAttrSize(pub u32);
impl PerfEventAttrSize {
pub const Zero: Self = Self(0);
pub const Ver0: Self = Self(64);
pub const Ver1: Self = Self(72);
pub const Ver2: Self = Self(80);
pub const Ver3: Self = Self(96);
pub const Ver4: Self = Self(104);
pub const Ver5: Self = Self(112);
pub const Ver6: Self = Self(120);
pub const Ver7: Self = Self(128);
}
impl From<u32> for PerfEventAttrSize {
fn from(val: u32) -> Self {
Self(val)
}
}
impl From<PerfEventAttrSize> for u32 {
fn from(val: PerfEventAttrSize) -> Self {
val.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventAttrSampleType(pub u64);
impl PerfEventAttrSampleType {
pub const None: Self = Self(0);
pub const IP: Self = Self(1 << 0);
pub const Tid: Self = Self(1 << 1);
pub const Time: Self = Self(1 << 2);
pub const Addr: Self = Self(1 << 3);
pub const Read: Self = Self(1 << 4);
pub const Callchain: Self = Self(1 << 5);
pub const Id: Self = Self(1 << 6);
pub const Cpu: Self = Self(1 << 7);
pub const Period: Self = Self(1 << 8);
pub const StreamId: Self = Self(1 << 9);
pub const Raw: Self = Self(1 << 10);
pub const BranchStack: Self = Self(1 << 11);
pub const RegsUser: Self = Self(1 << 12);
pub const StackUser: Self = Self(1 << 13);
pub const Weight: Self = Self(1 << 14);
pub const DataSrc: Self = Self(1 << 15);
pub const Identifier: Self = Self(1 << 16);
pub const Transaction: Self = Self(1 << 17);
pub const RegsIntr: Self = Self(1 << 18);
pub const PhysAddr: Self = Self(1 << 19);
pub const Aux: Self = Self(1 << 20);
pub const Cgroup: Self = Self(1 << 21);
pub const DataPageSize: Self = Self(1 << 22);
pub const CodePageSize: Self = Self(1 << 23);
pub const WeightStruct: Self = Self(1 << 24);
pub const WeightType: Self = Self(Self::Weight.0 | Self::WeightStruct.0);
pub const fn has_flag(self, mask: Self) -> bool {
0 != (self.0 & mask.0)
}
pub const fn or(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl From<u64> for PerfEventAttrSampleType {
fn from(val: u64) -> Self {
Self(val)
}
}
impl From<PerfEventAttrSampleType> for u64 {
fn from(val: PerfEventAttrSampleType) -> Self {
val.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventAttrReadFormat(pub u64);
impl PerfEventAttrReadFormat {
pub const None: Self = Self(0);
pub const TotalTimeEnabled: Self = Self(1 << 0);
pub const TotalTimeRunning: Self = Self(1 << 1);
pub const Id: Self = Self(1 << 2);
pub const Group: Self = Self(1 << 3);
pub const Lost: Self = Self(1 << 4);
pub const fn has_flag(self, mask: Self) -> bool {
0 != (self.0 & mask.0)
}
pub const fn or(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl From<u64> for PerfEventAttrReadFormat {
fn from(val: u64) -> Self {
Self(val)
}
}
impl From<PerfEventAttrReadFormat> for u64 {
fn from(val: PerfEventAttrReadFormat) -> Self {
val.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventAttrOptions(pub u64);
impl PerfEventAttrOptions {
pub const None: Self = Self(0);
pub const Disabled: Self = Self(1 << 0);
pub const Inherit: Self = Self(1 << 1);
pub const Pinned: Self = Self(1 << 2);
pub const Exclusive: Self = Self(1 << 3);
pub const ExcludeUser: Self = Self(1 << 4);
pub const ExcludeKernel: Self = Self(1 << 5);
pub const ExcludeHypervisor: Self = Self(1 << 6);
pub const ExcludeIdle: Self = Self(1 << 7);
pub const Mmap: Self = Self(1 << 8);
pub const Comm: Self = Self(1 << 9);
pub const Freq: Self = Self(1 << 10);
pub const InheritStat: Self = Self(1 << 11);
pub const EnableOnExec: Self = Self(1 << 12);
pub const Task: Self = Self(1 << 13);
pub const Watermark: Self = Self(1 << 14);
pub const PreciseIPSkidConstant: Self = Self(1 << 15);
pub const PreciseIPSkidZero: Self = Self(1 << 16);
pub const MmapData: Self = Self(1 << 17);
pub const SampleIdAll: Self = Self(1 << 18);
pub const ExcludeHost: Self = Self(1 << 19);
pub const ExcludeGuest: Self = Self(1 << 20);
pub const ExcludeCallchainKernel: Self = Self(1 << 21);
pub const ExcludeCallchainUser: Self = Self(1 << 22);
pub const Mmap2: Self = Self(1 << 23);
pub const CommExec: Self = Self(1 << 24);
pub const UseClockId: Self = Self(1 << 25);
pub const ContextSwitch: Self = Self(1 << 26);
pub const WriteBackward: Self = Self(1 << 27);
pub const Namespaces: Self = Self(1 << 28);
pub const Ksymbol: Self = Self(1 << 29);
pub const BpfEvent: Self = Self(1 << 30);
pub const AuxOutput: Self = Self(1 << 31);
pub const Cgroup: Self = Self(1 << 32);
pub const TextPoke: Self = Self(1 << 33);
pub const BuildId: Self = Self(1 << 34);
pub const InheritThread: Self = Self(1 << 35);
pub const RemoveOnExec: Self = Self(1 << 36);
pub const Sigtrap: Self = Self(1 << 37);
pub const fn has_flag(self, mask: Self) -> bool {
0 != (self.0 & mask.0)
}
pub const fn or(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl From<u64> for PerfEventAttrOptions {
fn from(val: u64) -> Self {
Self(val)
}
}
impl From<PerfEventAttrOptions> for u64 {
fn from(val: PerfEventAttrOptions) -> Self {
val.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct PerfEventAttr {
pub attr_type: PerfEventAttrType,
pub size: PerfEventAttrSize,
pub config: u64,
pub sample_time: u64,
pub sample_type: PerfEventAttrSampleType,
pub read_format: PerfEventAttrReadFormat,
pub options: PerfEventAttrOptions,
pub wakeup_value: u32,
pub bp_type: u32,
pub config1: u64,
pub config2: u64,
pub branch_sample_type: u64,
pub sample_regs_user: u64,
pub sample_stack_user: u32,
pub clockid: u32,
pub sample_regs_intr: u64,
pub aux_watermark: u32,
pub sample_max_stack: u16,
pub reserved2: u16,
pub aux_sample_size: u32,
pub reserved3: u32,
pub sig_data: u64,
}
impl PerfEventAttr {
pub const ATTR_TYPE_OFFSET: usize = 0;
pub const SIZE_OFFSET: usize = 4;
pub const CONFIG_OFFSET: usize = 8;
pub fn byte_swap(&mut self) {
self.attr_type.0 = self.attr_type.0.swap_bytes();
self.size.0 = self.size.0.swap_bytes();
self.config = self.config.swap_bytes();
self.sample_time = self.sample_time.swap_bytes();
self.sample_type.0 = self.sample_type.0.swap_bytes();
self.read_format.0 = self.read_format.0.swap_bytes();
let options_u64 = self.options.0.reverse_bits(); self.options.0 = options_u64.swap_bytes();
self.wakeup_value = self.wakeup_value.swap_bytes();
self.bp_type = self.bp_type.swap_bytes();
self.config1 = self.config1.swap_bytes();
self.config2 = self.config2.swap_bytes();
self.branch_sample_type = self.branch_sample_type.swap_bytes();
self.sample_regs_user = self.sample_regs_user.swap_bytes();
self.sample_stack_user = self.sample_stack_user.swap_bytes();
self.aux_watermark = self.aux_watermark.swap_bytes();
self.sample_max_stack = self.sample_max_stack.swap_bytes();
self.aux_sample_size = self.aux_sample_size.swap_bytes();
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventHeaderType(pub u32);
impl PerfEventHeaderType {
pub const None: Self = Self(0);
pub const Mmap: Self = Self(1);
pub const Lost: Self = Self(2);
pub const Comm: Self = Self(3);
pub const Exit: Self = Self(4);
pub const Throttle: Self = Self(5);
pub const Unthrottle: Self = Self(6);
pub const Fork: Self = Self(7);
pub const Read: Self = Self(8);
pub const Sample: Self = Self(9);
pub const Mmap2: Self = Self(10);
pub const Aux: Self = Self(11);
pub const ItraceStart: Self = Self(12);
pub const LostSamples: Self = Self(13);
pub const Switch: Self = Self(14);
pub const SwitchCpuWide: Self = Self(15);
pub const Namespaces: Self = Self(16);
pub const Ksymbol: Self = Self(17);
pub const BpfEvent: Self = Self(18);
pub const Cgroup: Self = Self(19);
pub const TextPoke: Self = Self(20);
pub const AuxOutputHwId: Self = Self(21);
pub const HeaderAttr: Self = Self(64);
pub const UserTypeStart: Self = Self::HeaderAttr;
pub const HeaderEventType: Self = Self(65);
pub const HeaderTracingData: Self = Self(66);
pub const HeaderBuildId: Self = Self(67);
pub const FinishedRound: Self = Self(68);
pub const IdIndex: Self = Self(69);
pub const AuxtraceInfo: Self = Self(70);
pub const Auxtrace: Self = Self(71);
pub const AuxtraceError: Self = Self(72);
pub const ThreadMap: Self = Self(73);
pub const CpuMap: Self = Self(74);
pub const StatConfig: Self = Self(75);
pub const Stat: Self = Self(76);
pub const StatRound: Self = Self(77);
pub const EventUpdate: Self = Self(78);
pub const TimeConv: Self = Self(79);
pub const HeaderFeature: Self = Self(80);
pub const Compressed: Self = Self(81);
pub const FinishedInit: Self = Self(82);
pub const fn as_string(self) -> Option<&'static str> {
match self {
Self::None => Some("None"),
Self::Mmap => Some("Mmap"),
Self::Lost => Some("Lost"),
Self::Comm => Some("Comm"),
Self::Exit => Some("Exit"),
Self::Throttle => Some("Throttle"),
Self::Unthrottle => Some("Unthrottle"),
Self::Fork => Some("Fork"),
Self::Read => Some("Read"),
Self::Sample => Some("Sample"),
Self::Mmap2 => Some("Mmap2"),
Self::Aux => Some("Aux"),
Self::ItraceStart => Some("ItraceStart"),
Self::LostSamples => Some("LostSamples"),
Self::Switch => Some("Switch"),
Self::SwitchCpuWide => Some("SwitchCpuWide"),
Self::Namespaces => Some("Namespaces"),
Self::Ksymbol => Some("Ksymbol"),
Self::BpfEvent => Some("BpfEvent"),
Self::Cgroup => Some("Cgroup"),
Self::TextPoke => Some("TextPoke"),
Self::AuxOutputHwId => Some("AuxOutputHwId"),
Self::HeaderAttr => Some("HeaderAttr"),
Self::HeaderEventType => Some("HeaderEventType"),
Self::HeaderTracingData => Some("HeaderTracingData"),
Self::HeaderBuildId => Some("HeaderBuildId"),
Self::FinishedRound => Some("FinishedRound"),
Self::IdIndex => Some("IdIndex"),
Self::AuxtraceInfo => Some("AuxtraceInfo"),
Self::Auxtrace => Some("Auxtrace"),
Self::AuxtraceError => Some("AuxtraceError"),
Self::ThreadMap => Some("ThreadMap"),
Self::CpuMap => Some("CpuMap"),
Self::StatConfig => Some("StatConfig"),
Self::Stat => Some("Stat"),
Self::StatRound => Some("StatRound"),
Self::EventUpdate => Some("EventUpdate"),
Self::TimeConv => Some("TimeConv"),
Self::HeaderFeature => Some("HeaderFeature"),
Self::Compressed => Some("Compressed"),
Self::FinishedInit => Some("FinishedInit"),
_ => None,
}
}
}
impl From<u32> for PerfEventHeaderType {
fn from(val: u32) -> Self {
Self(val)
}
}
impl From<PerfEventHeaderType> for u32 {
fn from(val: PerfEventHeaderType) -> Self {
val.0
}
}
impl fmt::Display for PerfEventHeaderType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(s) = self.as_string() {
return f.pad(s);
} else {
return self.0.fmt(f);
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventHeaderMiscCpuMode(pub u8);
impl PerfEventHeaderMiscCpuMode {
pub const Unknown: Self = Self(0);
pub const Kernel: Self = Self(1);
pub const User: Self = Self(2);
pub const Hypervisor: Self = Self(3);
pub const GuestKernel: Self = Self(4);
pub const GuestUser: Self = Self(5);
}
impl From<u8> for PerfEventHeaderMiscCpuMode {
fn from(val: u8) -> Self {
Self(val)
}
}
impl From<PerfEventHeaderMiscCpuMode> for u8 {
fn from(val: PerfEventHeaderMiscCpuMode) -> Self {
val.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PerfEventHeaderMisc(pub u16);
impl PerfEventHeaderMisc {
pub const fn cpu_mode(self) -> PerfEventHeaderMiscCpuMode {
PerfEventHeaderMiscCpuMode((self.0 & 0x7) as u8)
}
pub const fn proc_map_parse_timeout(self) -> bool {
(self.0 & 0x1000) != 0
}
pub const fn mmap_data(self) -> bool {
(self.0 & 0x2000) != 0
}
pub const fn comm_exec(self) -> bool {
(self.0 & 0x2000) != 0
}
pub const fn fork_exec(self) -> bool {
(self.0 & 0x2000) != 0
}
pub const fn switch_out(self) -> bool {
(self.0 & 0x2000) != 0
}
pub const fn exact_ip(self) -> bool {
(self.0 & 0x4000) != 0
}
pub const fn switch_out_preempt(self) -> bool {
(self.0 & 0x4000) != 0
}
pub const fn mmap_build_id(self) -> bool {
(self.0 & 0x4000) != 0
}
pub const fn ext_reserved(self) -> bool {
(self.0 & 0x8000) != 0
}
}
impl From<u16> for PerfEventHeaderMisc {
fn from(val: u16) -> Self {
Self(val)
}
}
impl From<PerfEventHeaderMisc> for u16 {
fn from(val: PerfEventHeaderMisc) -> Self {
val.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct PerfEventHeader {
pub ty: PerfEventHeaderType,
pub misc: PerfEventHeaderMisc,
pub size: u16,
}
impl PerfEventHeader {
pub const fn new() -> Self {
Self {
ty: PerfEventHeaderType::None,
misc: PerfEventHeaderMisc(0),
size: 0,
}
}
pub const fn from_bytes(bytes: &[u8; 8], byte_reader: PerfByteReader) -> Self {
let header: PerfEventHeader = unsafe { mem::transmute_copy(bytes) };
if byte_reader.byte_swap_needed() {
return header.byte_swap_copy();
} else {
return header;
}
}
pub fn byte_swap(&mut self) {
*self = self.byte_swap_copy();
}
pub const fn byte_swap_copy(mut self) -> Self {
self.ty.0 = self.ty.0.swap_bytes();
self.misc.0 = self.misc.0.swap_bytes();
self.size = self.size.swap_bytes();
return self;
}
}