1787 lines
36 KiB
C
1787 lines
36 KiB
C
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd
|
|
//
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include <vmlinux.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_core_read.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
|
|
#include "com.h"
|
|
|
|
#define MAX_ENTRIES 1000
|
|
|
|
#define MAX_EVENT_SIZE 10240
|
|
#define RINGBUF_SIZE (1024 * 256)
|
|
|
|
// Event type definitions
|
|
enum xhci_event_type
|
|
{
|
|
XHCI_ALLOC_DEV = 0,
|
|
XHCI_FREE_DEV,
|
|
XHCI_URB_ENQUEUE,
|
|
XHCI_URB_GIVEBACK,
|
|
XHCI_HANDLE_EVENT,
|
|
XHCI_HANDLE_TRANSFER,
|
|
XHCI_QUEUE_TRB,
|
|
XHCI_SETUP_DEVICE,
|
|
XHCI_RING_ALLOC,
|
|
// New event types
|
|
XHCI_ADD_ENDPOINT,
|
|
XHCI_ADDRESS_CTRL_CTX,
|
|
XHCI_ADDRESS_CTX,
|
|
XHCI_ALLOC_VIRT_DEVICE,
|
|
XHCI_CONFIGURE_ENDPOINT,
|
|
XHCI_CONFIGURE_ENDPOINT_CTRL_CTX,
|
|
XHCI_DBC_ALLOC_REQUEST,
|
|
XHCI_DBC_FREE_REQUEST,
|
|
XHCI_DBC_GADGET_EP_QUEUE,
|
|
XHCI_DBC_GIVEBACK_REQUEST,
|
|
XHCI_DBC_HANDLE_EVENT,
|
|
XHCI_DBC_HANDLE_TRANSFER,
|
|
XHCI_DBC_QUEUE_REQUEST,
|
|
XHCI_DBG_ADDRESS,
|
|
XHCI_DBG_CANCEL_URB,
|
|
XHCI_DBG_CONTEXT_CHANGE,
|
|
XHCI_DBG_INIT,
|
|
XHCI_DBG_QUIRKS,
|
|
XHCI_DBG_RESET_EP,
|
|
XHCI_DBG_RING_EXPANSION,
|
|
XHCI_DISCOVER_OR_RESET_DEVICE,
|
|
XHCI_FREE_VIRT_DEVICE,
|
|
XHCI_GET_PORT_STATUS,
|
|
XHCI_HANDLE_CMD_ADDR_DEV,
|
|
XHCI_HANDLE_CMD_CONFIG_EP,
|
|
XHCI_HANDLE_CMD_DISABLE_SLOT,
|
|
XHCI_HANDLE_CMD_RESET_DEV,
|
|
XHCI_HANDLE_CMD_RESET_EP,
|
|
XHCI_HANDLE_CMD_SET_DEQ,
|
|
XHCI_HANDLE_CMD_SET_DEQ_EP,
|
|
XHCI_HANDLE_CMD_STOP_EP,
|
|
XHCI_HANDLE_COMMAND,
|
|
XHCI_HANDLE_PORT_STATUS,
|
|
XHCI_HUB_STATUS_DATA,
|
|
XHCI_INC_DEQ,
|
|
XHCI_INC_ENQ,
|
|
XHCI_RING_EP_DOORBELL,
|
|
XHCI_RING_EXPANSION,
|
|
XHCI_RING_FREE,
|
|
XHCI_RING_HOST_DOORBELL,
|
|
XHCI_SETUP_ADDRESSABLE_VIRT_DEVICE,
|
|
XHCI_SETUP_DEVICE_SLOT,
|
|
XHCI_STOP_DEVICE,
|
|
XHCI_URB_DEQUEUE,
|
|
};
|
|
|
|
struct
|
|
{
|
|
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
|
__uint(max_entries, RINGBUF_SIZE);
|
|
} events SEC(".maps");
|
|
|
|
struct
|
|
{
|
|
__uint(type, BPF_MAP_TYPE_ARRAY);
|
|
__uint(max_entries, 1);
|
|
__type(key, int);
|
|
__type(value, char[4096]);
|
|
} filter SEC(".maps");
|
|
|
|
struct tp_xhci_alloc_dev_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
struct tp_xhci_free_dev_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
struct tp_xhci_urb_enqueue_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
void *urb;
|
|
unsigned int pipe;
|
|
unsigned int stream;
|
|
int status;
|
|
unsigned int flags;
|
|
int num_mapped_sgs;
|
|
int num_sgs;
|
|
int length;
|
|
int actual;
|
|
int epnum;
|
|
int dir_in;
|
|
int type;
|
|
int slot_id;
|
|
};
|
|
|
|
struct tp_xhci_urb_giveback_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
void *urb;
|
|
unsigned int pipe;
|
|
unsigned int stream;
|
|
int status;
|
|
unsigned int flags;
|
|
int num_mapped_sgs;
|
|
int num_sgs;
|
|
int length;
|
|
int actual;
|
|
int epnum;
|
|
int dir_in;
|
|
int type;
|
|
int slot_id;
|
|
};
|
|
|
|
struct tp_xhci_handle_event_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
u32 field0;
|
|
u32 field1;
|
|
u32 field2;
|
|
u32 field3;
|
|
};
|
|
|
|
struct tp_xhci_handle_transfer_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
u32 field0;
|
|
u32 field1;
|
|
u32 field2;
|
|
u32 field3;
|
|
};
|
|
|
|
struct tp_xhci_queue_trb_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
u32 field0;
|
|
u32 field1;
|
|
u32 field2;
|
|
u32 field3;
|
|
};
|
|
|
|
struct tp_xhci_setup_device_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
void *vdev;
|
|
unsigned long long out_ctx;
|
|
unsigned long long in_ctx;
|
|
int devnum;
|
|
int state;
|
|
int speed;
|
|
u8 portnum;
|
|
u8 level;
|
|
int slot_id;
|
|
};
|
|
|
|
struct tp_xhci_ring_alloc_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
void *ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
// New context structures
|
|
struct tp_xhci_add_endpoint_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 info;
|
|
u32 info2;
|
|
u64 deq;
|
|
u32 tx_info;
|
|
};
|
|
|
|
struct tp_xhci_address_ctx_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
int ctx_64;
|
|
unsigned ctx_type;
|
|
u64 ctx_dma;
|
|
u64 ctx_va;
|
|
unsigned ctx_ep_num;
|
|
u32 ctx_data;
|
|
};
|
|
|
|
struct tp_xhci_alloc_virt_device_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
void *vdev;
|
|
u64 out_ctx;
|
|
u64 in_ctx;
|
|
int devnum;
|
|
int state;
|
|
int speed;
|
|
u8 portnum;
|
|
u8 level;
|
|
int slot_id;
|
|
};
|
|
|
|
struct tp_xhci_configure_endpoint_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
struct tp_xhci_ring_free_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
void *ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
struct tp_xhci_inc_deq_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
void *ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
struct tp_xhci_inc_enq_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 type;
|
|
void *ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
struct tp_xhci_ring_ep_doorbell_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 slot;
|
|
u32 doorbell;
|
|
};
|
|
|
|
struct tp_xhci_urb_dequeue_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
void *urb;
|
|
unsigned int pipe;
|
|
unsigned int stream;
|
|
int status;
|
|
unsigned int flags;
|
|
int num_mapped_sgs;
|
|
int num_sgs;
|
|
int length;
|
|
int actual;
|
|
int epnum;
|
|
int dir_in;
|
|
int type;
|
|
int slot_id;
|
|
};
|
|
|
|
struct tp_xhci_dbg_address_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
char msg[256]; // Simplified for BPF
|
|
};
|
|
|
|
// Generic context structure for simple slot context tracepoints
|
|
struct tp_xhci_slot_ctx_t
|
|
{
|
|
unsigned short common_type;
|
|
unsigned char common_flags;
|
|
unsigned char common_preempt_count;
|
|
int common_pid;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
struct xhci_alloc_dev_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
struct xhci_free_dev_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
struct xhci_urb_enqueue_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u64 urb;
|
|
unsigned int pipe;
|
|
unsigned int stream;
|
|
int status;
|
|
unsigned int flags;
|
|
int num_mapped_sgs;
|
|
int num_sgs;
|
|
int length;
|
|
int actual;
|
|
int epnum;
|
|
int dir_in;
|
|
int type;
|
|
int slot_id;
|
|
};
|
|
|
|
struct xhci_urb_giveback_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u64 urb;
|
|
unsigned int pipe;
|
|
unsigned int stream;
|
|
int status;
|
|
unsigned int flags;
|
|
int num_mapped_sgs;
|
|
int num_sgs;
|
|
int length;
|
|
int actual;
|
|
int epnum;
|
|
int dir_in;
|
|
int type;
|
|
int slot_id;
|
|
};
|
|
|
|
struct xhci_handle_event_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u32 field0;
|
|
u32 field1;
|
|
u32 field2;
|
|
u32 field3;
|
|
};
|
|
|
|
struct xhci_handle_transfer_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u32 field0;
|
|
u32 field1;
|
|
u32 field2;
|
|
u32 field3;
|
|
};
|
|
|
|
struct xhci_queue_trb_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u32 field0;
|
|
u32 field1;
|
|
u32 field2;
|
|
u32 field3;
|
|
};
|
|
|
|
struct xhci_setup_device_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u64 vdev;
|
|
u64 out_ctx;
|
|
u64 in_ctx;
|
|
int devnum;
|
|
int state;
|
|
int speed;
|
|
u8 portnum;
|
|
u8 level;
|
|
int slot_id;
|
|
};
|
|
|
|
struct xhci_ring_alloc_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u64 ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
// New event structures
|
|
struct xhci_add_endpoint_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 info;
|
|
u32 info2;
|
|
u64 deq;
|
|
u32 tx_info;
|
|
};
|
|
|
|
struct xhci_address_ctx_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
int ctx_64;
|
|
unsigned ctx_type;
|
|
u64 ctx_dma;
|
|
u64 ctx_va;
|
|
unsigned ctx_ep_num;
|
|
u32 ctx_data;
|
|
};
|
|
|
|
struct xhci_alloc_virt_device_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u64 vdev;
|
|
u64 out_ctx;
|
|
u64 in_ctx;
|
|
int devnum;
|
|
int state;
|
|
int speed;
|
|
u8 portnum;
|
|
u8 level;
|
|
int slot_id;
|
|
};
|
|
|
|
struct xhci_ring_free_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u64 ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
struct xhci_inc_deq_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u64 ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
struct xhci_inc_enq_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 type;
|
|
u64 ring;
|
|
u64 enq;
|
|
u64 deq;
|
|
u64 enq_seg;
|
|
u64 deq_seg;
|
|
unsigned int num_segs;
|
|
unsigned int stream_id;
|
|
unsigned int cycle_state;
|
|
unsigned int bounce_buf_len;
|
|
};
|
|
|
|
struct xhci_ring_ep_doorbell_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 slot;
|
|
u32 doorbell;
|
|
};
|
|
|
|
struct xhci_urb_dequeue_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u64 urb;
|
|
unsigned int pipe;
|
|
unsigned int stream;
|
|
int status;
|
|
unsigned int flags;
|
|
int num_mapped_sgs;
|
|
int num_sgs;
|
|
int length;
|
|
int actual;
|
|
int epnum;
|
|
int dir_in;
|
|
int type;
|
|
int slot_id;
|
|
};
|
|
|
|
struct xhci_dbg_address_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
char msg[256];
|
|
};
|
|
|
|
// Generic event structure for simple slot context tracepoints
|
|
struct xhci_slot_ctx_event_t
|
|
{
|
|
u32 event_type;
|
|
pid_t pid;
|
|
pid_t tid;
|
|
char comm[TASK_COMM_LEN];
|
|
u64 timestamp;
|
|
u32 info;
|
|
u32 info2;
|
|
u32 tt_info;
|
|
u32 state;
|
|
};
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_alloc_dev")
|
|
int tp_xhci_alloc_dev(struct tp_xhci_alloc_dev_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_alloc_dev_event_t event = {0};
|
|
|
|
event.event_type = XHCI_ALLOC_DEV;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.tt_info = ctx->tt_info;
|
|
event.state = ctx->state;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_alloc_dev: pid: %d, tid: %d, comm: %s, info: %u, info2: %u, "
|
|
"tt_info: %u, state: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.tt_info,
|
|
event.state
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_free_dev")
|
|
int tp_xhci_free_dev(struct tp_xhci_free_dev_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_free_dev_event_t event = {0};
|
|
|
|
event.event_type = XHCI_FREE_DEV;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.tt_info = ctx->tt_info;
|
|
event.state = ctx->state;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_free_dev: pid: %d, tid: %d, comm: %s, info: %u, info2: %u, "
|
|
"tt_info: %u, state: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.tt_info,
|
|
event.state
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_urb_enqueue")
|
|
int tp_xhci_urb_enqueue(struct tp_xhci_urb_enqueue_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_urb_enqueue_event_t event = {0};
|
|
|
|
event.event_type = XHCI_URB_ENQUEUE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.urb = (u64)ctx->urb;
|
|
event.pipe = ctx->pipe;
|
|
event.stream = ctx->stream;
|
|
event.status = ctx->status;
|
|
event.flags = ctx->flags;
|
|
event.num_mapped_sgs = ctx->num_mapped_sgs;
|
|
event.num_sgs = ctx->num_sgs;
|
|
event.length = ctx->length;
|
|
event.actual = ctx->actual;
|
|
event.epnum = ctx->epnum;
|
|
event.dir_in = ctx->dir_in;
|
|
event.type = ctx->type;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_urb_enqueue: pid: %d, tid: %d, comm: %s, urb: %llx, ep%d%s, "
|
|
"slot: %d, len: %d/%d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.urb,
|
|
event.epnum,
|
|
event.dir_in ? "in" : "out",
|
|
event.slot_id,
|
|
event.actual,
|
|
event.length
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_urb_giveback")
|
|
int tp_xhci_urb_giveback(struct tp_xhci_urb_giveback_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_urb_giveback_event_t event = {0};
|
|
|
|
event.event_type = XHCI_URB_GIVEBACK;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.urb = (u64)ctx->urb;
|
|
event.pipe = ctx->pipe;
|
|
event.stream = ctx->stream;
|
|
event.status = ctx->status;
|
|
event.flags = ctx->flags;
|
|
event.num_mapped_sgs = ctx->num_mapped_sgs;
|
|
event.num_sgs = ctx->num_sgs;
|
|
event.length = ctx->length;
|
|
event.actual = ctx->actual;
|
|
event.epnum = ctx->epnum;
|
|
event.dir_in = ctx->dir_in;
|
|
event.type = ctx->type;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_urb_giveback: pid: %d, tid: %d, comm: %s, urb: %llx, ep%d%s, "
|
|
"slot: %d, len: %d/%d, status: %d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.urb,
|
|
event.epnum,
|
|
event.dir_in ? "in" : "out",
|
|
event.slot_id,
|
|
event.actual,
|
|
event.length,
|
|
event.status
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_handle_event")
|
|
int tp_xhci_handle_event(struct tp_xhci_handle_event_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_handle_event_event_t event = {0};
|
|
|
|
event.event_type = XHCI_HANDLE_EVENT;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.field0 = ctx->field0;
|
|
event.field1 = ctx->field1;
|
|
event.field2 = ctx->field2;
|
|
event.field3 = ctx->field3;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_handle_event: pid: %d, tid: %d, comm: %s, type: %u, fields: %u "
|
|
"%u %u %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.field0,
|
|
event.field1,
|
|
event.field2,
|
|
event.field3
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_handle_transfer")
|
|
int tp_xhci_handle_transfer(struct tp_xhci_handle_transfer_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_handle_transfer_event_t event = {0};
|
|
|
|
event.event_type = XHCI_HANDLE_TRANSFER;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.field0 = ctx->field0;
|
|
event.field1 = ctx->field1;
|
|
event.field2 = ctx->field2;
|
|
event.field3 = ctx->field3;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_handle_transfer: pid: %d, tid: %d, comm: %s, type: %u, fields: "
|
|
"%u %u %u %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.field0,
|
|
event.field1,
|
|
event.field2,
|
|
event.field3
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_queue_trb")
|
|
int tp_xhci_queue_trb(struct tp_xhci_queue_trb_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_queue_trb_event_t event = {0};
|
|
|
|
event.event_type = XHCI_QUEUE_TRB;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.field0 = ctx->field0;
|
|
event.field1 = ctx->field1;
|
|
event.field2 = ctx->field2;
|
|
event.field3 = ctx->field3;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_queue_trb: pid: %d, tid: %d, comm: %s, type: %u, fields: %u %u "
|
|
"%u %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.field0,
|
|
event.field1,
|
|
event.field2,
|
|
event.field3
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_setup_device")
|
|
int tp_xhci_setup_device(struct tp_xhci_setup_device_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_setup_device_event_t event = {0};
|
|
|
|
event.event_type = XHCI_SETUP_DEVICE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.vdev = (u64)ctx->vdev;
|
|
event.out_ctx = ctx->out_ctx;
|
|
event.in_ctx = ctx->in_ctx;
|
|
event.devnum = ctx->devnum;
|
|
event.state = ctx->state;
|
|
event.speed = ctx->speed;
|
|
event.portnum = ctx->portnum;
|
|
event.level = ctx->level;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_setup_device: pid: %d, tid: %d, comm: %s, vdev: %llx, devnum: "
|
|
"%d, state: %d, speed: %d, port: %d, slot: %d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.vdev,
|
|
event.devnum,
|
|
event.state,
|
|
event.speed,
|
|
event.portnum,
|
|
event.slot_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_ring_alloc")
|
|
int tp_xhci_ring_alloc(struct tp_xhci_ring_alloc_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_ring_alloc_event_t event = {0};
|
|
|
|
event.event_type = XHCI_RING_ALLOC;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.ring = (u64)ctx->ring;
|
|
event.enq = ctx->enq;
|
|
event.deq = ctx->deq;
|
|
event.enq_seg = ctx->enq_seg;
|
|
event.deq_seg = ctx->deq_seg;
|
|
event.num_segs = ctx->num_segs;
|
|
event.stream_id = ctx->stream_id;
|
|
event.cycle_state = ctx->cycle_state;
|
|
event.bounce_buf_len = ctx->bounce_buf_len;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_ring_alloc: pid: %d, tid: %d, comm: %s, type: %u, ring: %llx, "
|
|
"segs: %u, stream: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.ring,
|
|
event.num_segs,
|
|
event.stream_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_add_endpoint")
|
|
int tp_xhci_add_endpoint(struct tp_xhci_add_endpoint_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_add_endpoint_event_t event = {0};
|
|
|
|
event.event_type = XHCI_ADD_ENDPOINT;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.deq = ctx->deq;
|
|
event.tx_info = ctx->tx_info;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_add_endpoint: pid: %d, tid: %d, comm: %s, info: %u, info2: %u, "
|
|
"deq: %llx, tx_info: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.deq,
|
|
event.tx_info
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_address_ctx")
|
|
int tp_xhci_address_ctx(struct tp_xhci_address_ctx_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_address_ctx_event_t event = {0};
|
|
|
|
event.event_type = XHCI_ADDRESS_CTX;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.ctx_64 = ctx->ctx_64;
|
|
event.ctx_type = ctx->ctx_type;
|
|
event.ctx_dma = ctx->ctx_dma;
|
|
event.ctx_va = (u64)ctx->ctx_va;
|
|
event.ctx_ep_num = ctx->ctx_ep_num;
|
|
event.ctx_data = ctx->ctx_data;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_address_ctx: pid: %d, tid: %d, comm: %s, ctx_64: %d, type: %u, "
|
|
"dma: %llx, va: %llx\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.ctx_64,
|
|
event.ctx_type,
|
|
event.ctx_dma,
|
|
event.ctx_va
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_alloc_virt_device")
|
|
int tp_xhci_alloc_virt_device(struct tp_xhci_alloc_virt_device_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_alloc_virt_device_event_t event = {0};
|
|
|
|
event.event_type = XHCI_ALLOC_VIRT_DEVICE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.vdev = (u64)ctx->vdev;
|
|
event.out_ctx = ctx->out_ctx;
|
|
event.in_ctx = ctx->in_ctx;
|
|
event.devnum = ctx->devnum;
|
|
event.state = ctx->state;
|
|
event.speed = ctx->speed;
|
|
event.portnum = ctx->portnum;
|
|
event.level = ctx->level;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_alloc_virt_device: pid: %d, tid: %d, comm: %s, vdev: %llx, "
|
|
"devnum: %d, state: %d, speed: %d, port: %d, slot: %d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.vdev,
|
|
event.devnum,
|
|
event.state,
|
|
event.speed,
|
|
event.portnum,
|
|
event.slot_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_configure_endpoint")
|
|
int tp_xhci_configure_endpoint(struct tp_xhci_configure_endpoint_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_slot_ctx_event_t event = {0};
|
|
|
|
event.event_type = XHCI_CONFIGURE_ENDPOINT;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.tt_info = ctx->tt_info;
|
|
event.state = ctx->state;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_configure_endpoint: pid: %d, tid: %d, comm: %s, info: %u, info2: "
|
|
"%u, tt_info: %u, state: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.tt_info,
|
|
event.state
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_ring_free")
|
|
int tp_xhci_ring_free(struct tp_xhci_ring_free_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_ring_free_event_t event = {0};
|
|
|
|
event.event_type = XHCI_RING_FREE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.ring = (u64)ctx->ring;
|
|
event.enq = ctx->enq;
|
|
event.deq = ctx->deq;
|
|
event.enq_seg = ctx->enq_seg;
|
|
event.deq_seg = ctx->deq_seg;
|
|
event.num_segs = ctx->num_segs;
|
|
event.stream_id = ctx->stream_id;
|
|
event.cycle_state = ctx->cycle_state;
|
|
event.bounce_buf_len = ctx->bounce_buf_len;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_ring_free: pid: %d, tid: %d, comm: %s, type: %u, ring: %llx, "
|
|
"segs: %u, stream: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.ring,
|
|
event.num_segs,
|
|
event.stream_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_inc_deq")
|
|
int tp_xhci_inc_deq(struct tp_xhci_inc_deq_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_inc_deq_event_t event = {0};
|
|
|
|
event.event_type = XHCI_INC_DEQ;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.ring = (u64)ctx->ring;
|
|
event.enq = ctx->enq;
|
|
event.deq = ctx->deq;
|
|
event.enq_seg = ctx->enq_seg;
|
|
event.deq_seg = ctx->deq_seg;
|
|
event.num_segs = ctx->num_segs;
|
|
event.stream_id = ctx->stream_id;
|
|
event.cycle_state = ctx->cycle_state;
|
|
event.bounce_buf_len = ctx->bounce_buf_len;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_inc_deq: pid: %d, tid: %d, comm: %s, type: %u, ring: %llx, segs: "
|
|
"%u, stream: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.ring,
|
|
event.num_segs,
|
|
event.stream_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_inc_enq")
|
|
int tp_xhci_inc_enq(struct tp_xhci_inc_enq_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_inc_enq_event_t event = {0};
|
|
|
|
event.event_type = XHCI_INC_ENQ;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.type = ctx->type;
|
|
event.ring = (u64)ctx->ring;
|
|
event.enq = ctx->enq;
|
|
event.deq = ctx->deq;
|
|
event.enq_seg = ctx->enq_seg;
|
|
event.deq_seg = ctx->deq_seg;
|
|
event.num_segs = ctx->num_segs;
|
|
event.stream_id = ctx->stream_id;
|
|
event.cycle_state = ctx->cycle_state;
|
|
event.bounce_buf_len = ctx->bounce_buf_len;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_inc_enq: pid: %d, tid: %d, comm: %s, type: %u, ring: %llx, segs: "
|
|
"%u, stream: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.type,
|
|
event.ring,
|
|
event.num_segs,
|
|
event.stream_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_ring_ep_doorbell")
|
|
int tp_xhci_ring_ep_doorbell(struct tp_xhci_ring_ep_doorbell_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_ring_ep_doorbell_event_t event = {0};
|
|
|
|
event.event_type = XHCI_RING_EP_DOORBELL;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.slot = ctx->slot;
|
|
event.doorbell = ctx->doorbell;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_ring_ep_doorbell: pid: %d, tid: %d, comm: %s, slot: %u, "
|
|
"doorbell: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.slot,
|
|
event.doorbell
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_urb_dequeue")
|
|
int tp_xhci_urb_dequeue(struct tp_xhci_urb_dequeue_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_urb_dequeue_event_t event = {0};
|
|
|
|
event.event_type = XHCI_URB_DEQUEUE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.urb = (u64)ctx->urb;
|
|
event.pipe = ctx->pipe;
|
|
event.stream = ctx->stream;
|
|
event.status = ctx->status;
|
|
event.flags = ctx->flags;
|
|
event.num_mapped_sgs = ctx->num_mapped_sgs;
|
|
event.num_sgs = ctx->num_sgs;
|
|
event.length = ctx->length;
|
|
event.actual = ctx->actual;
|
|
event.epnum = ctx->epnum;
|
|
event.dir_in = ctx->dir_in;
|
|
event.type = ctx->type;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_urb_dequeue: pid: %d, tid: %d, comm: %s, urb: %llx, ep%d%s, "
|
|
"slot: %d, len: %d/%d, status: %d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.urb,
|
|
event.epnum,
|
|
event.dir_in ? "in" : "out",
|
|
event.slot_id,
|
|
event.actual,
|
|
event.length,
|
|
event.status
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Slot context tracepoints using generic structure
|
|
SEC("tracepoint/xhci_hcd/xhci_setup_addressable_virt_device")
|
|
int tp_xhci_setup_addressable_virt_device(
|
|
struct tp_xhci_alloc_virt_device_ctx_t *ctx
|
|
)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_alloc_virt_device_event_t event = {0};
|
|
|
|
event.event_type = XHCI_SETUP_ADDRESSABLE_VIRT_DEVICE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.vdev = (u64)ctx->vdev;
|
|
event.out_ctx = ctx->out_ctx;
|
|
event.in_ctx = ctx->in_ctx;
|
|
event.devnum = ctx->devnum;
|
|
event.state = ctx->state;
|
|
event.speed = ctx->speed;
|
|
event.portnum = ctx->portnum;
|
|
event.level = ctx->level;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_setup_addressable_virt_device: pid: %d, tid: %d, comm: %s, vdev: "
|
|
"%llx, devnum: %d, state: %d, speed: %d, port: %d, slot: %d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.vdev,
|
|
event.devnum,
|
|
event.state,
|
|
event.speed,
|
|
event.portnum,
|
|
event.slot_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_free_virt_device")
|
|
int tp_xhci_free_virt_device(struct tp_xhci_alloc_virt_device_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_alloc_virt_device_event_t event = {0};
|
|
|
|
event.event_type = XHCI_FREE_VIRT_DEVICE;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.vdev = (u64)ctx->vdev;
|
|
event.out_ctx = ctx->out_ctx;
|
|
event.in_ctx = ctx->in_ctx;
|
|
event.devnum = ctx->devnum;
|
|
event.state = ctx->state;
|
|
event.speed = ctx->speed;
|
|
event.portnum = ctx->portnum;
|
|
event.level = ctx->level;
|
|
event.slot_id = ctx->slot_id;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_free_virt_device: pid: %d, tid: %d, comm: %s, vdev: %llx, "
|
|
"devnum: %d, state: %d, speed: %d, port: %d, slot: %d\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.vdev,
|
|
event.devnum,
|
|
event.state,
|
|
event.speed,
|
|
event.portnum,
|
|
event.slot_id
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_setup_device_slot")
|
|
int tp_xhci_setup_device_slot(struct tp_xhci_slot_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_slot_ctx_event_t event = {0};
|
|
|
|
event.event_type = XHCI_SETUP_DEVICE_SLOT;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.tt_info = ctx->tt_info;
|
|
event.state = ctx->state;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_setup_device_slot: pid: %d, tid: %d, comm: %s, info: %u, info2: "
|
|
"%u, tt_info: %u, state: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.tt_info,
|
|
event.state
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Handle command tracepoints using generic slot context structure
|
|
SEC("tracepoint/xhci_hcd/xhci_handle_cmd_addr_dev")
|
|
int tp_xhci_handle_cmd_addr_dev(struct tp_xhci_slot_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_slot_ctx_event_t event = {0};
|
|
|
|
event.event_type = XHCI_HANDLE_CMD_ADDR_DEV;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.tt_info = ctx->tt_info;
|
|
event.state = ctx->state;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_handle_cmd_addr_dev: pid: %d, tid: %d, comm: %s, info: %u, "
|
|
"info2: %u, tt_info: %u, state: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.tt_info,
|
|
event.state
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/xhci_hcd/xhci_handle_cmd_config_ep")
|
|
int tp_xhci_handle_cmd_config_ep(struct tp_xhci_slot_ctx_t *ctx)
|
|
{
|
|
long ret = 0;
|
|
struct xhci_slot_ctx_event_t event = {0};
|
|
|
|
event.event_type = XHCI_HANDLE_CMD_CONFIG_EP;
|
|
event.timestamp = bpf_ktime_get_ns();
|
|
event.pid = bpf_get_current_pid_tgid() >> 32;
|
|
event.tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
|
|
ret = bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to get current comm\n");
|
|
}
|
|
|
|
event.info = ctx->info;
|
|
event.info2 = ctx->info2;
|
|
event.tt_info = ctx->tt_info;
|
|
event.state = ctx->state;
|
|
|
|
DEBUG(
|
|
0,
|
|
"xhci_handle_cmd_config_ep: pid: %d, tid: %d, comm: %s, info: %u, "
|
|
"info2: %u, tt_info: %u, state: %u\n",
|
|
event.pid,
|
|
event.tid,
|
|
event.comm,
|
|
event.info,
|
|
event.info2,
|
|
event.tt_info,
|
|
event.state
|
|
);
|
|
|
|
ret = bpf_ringbuf_output(&events, &event, sizeof(event), 0);
|
|
if (ret < 0)
|
|
{
|
|
bpf_err("Failed to output event to ring buffer\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char LICENSE[] SEC("license") = "GPL"; |