> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 内核探针与跟踪

Linux 内核提供了多种动态插桩机制，让您无需给内核打补丁或重新编译内核，即可插入探针、收集跟踪信息并测量时序。本页介绍用于代码路径断点的 kprobes、用于函数级性能分析的 ftrace，以及用于调试驱动寄存器访问失败的 MMIO 跟踪。

## Kprobes

Kprobes 允许您在任意内核指令地址处设置断点，并在执行到达该点时运行自定义处理程序。该技术是非侵入式的——正在运行的内核不会停止，其他 CPU 会继续执行。

### kprobes 的工作原理

1. 您在某个符号或地址上注册一个探针。
2. 内核将目标指令替换为一条陷阱指令。
3. 当陷阱触发时，kprobe 处理程序在与被中断代码相同的上下文中运行。
4. 内核恢复原始指令并继续执行。

Kprobes 在以下场景特别有用：

* 跟踪调度器事件（`schedule()`、`try_to_wake_up()`）
* 统计某条慢速代码路径被执行的频率
* 捕获调用参数，而无需添加 `printk` 并重新构建

### Kconfig

```text theme={null}
CONFIG_KPROBES=y
CONFIG_KPROBE_EVENTS=y   # enables kprobe trace events via tracefs
```

在目标设备上验证：

```bash theme={null}
zcat /proc/config.gz | grep CONFIG_KPROBE
```

### 通过 tracefs 使用 kprobe 跟踪事件

使用 kprobes 最简单的方式是通过 tracefs 的 `kprobe_events` 接口：

```bash theme={null}
# Register a kprobe on qcom_geni_serial_probe
echo "p:qcom_probe qcom_geni_serial_probe" > /sys/kernel/tracing/kprobe_events

# Enable the event
echo 1 > /sys/kernel/tracing/events/kprobes/qcom_probe/enable

# Start tracing
echo 1 > /sys/kernel/tracing/tracing_on

# ... trigger the probe by loading the driver or booting ...

# Read results
cat /sys/kernel/tracing/trace

# Clean up
echo 0 > /sys/kernel/tracing/tracing_on
echo "-:qcom_probe" >> /sys/kernel/tracing/kprobe_events
```

如需完整的 kprobes 文档，请参阅
[Kernel Probes (kprobes)](https://docs.kernel.org/trace/kprobes.html)。

## Ftrace

Ftrace 是内核内置的函数跟踪器。它可以记录内核中的每一次函数调用、跟踪特定子系统，或对延迟敏感的代码路径进行性能分析。结果通过 tracefs 接口（`/sys/kernel/tracing/`）读取。

### 函数跟踪器

`function` 跟踪器记录每个被调用的内核函数的名称和所在 CPU：

```bash theme={null}
echo function > /sys/kernel/tracing/current_tracer
echo 1 > /sys/kernel/tracing/tracing_on
sleep 1
echo 0 > /sys/kernel/tracing/tracing_on
cat /sys/kernel/tracing/trace | head -30
```

### 函数图跟踪器

`function_graph` 跟踪器记录每个函数的进入和退出，包括执行时间。对于识别慢速代码路径非常有用：

```bash theme={null}
echo function_graph > /sys/kernel/tracing/current_tracer
echo 1 > /sys/kernel/tracing/tracing_on
# ... trigger the code path ...
echo 0 > /sys/kernel/tracing/tracing_on
cat /sys/kernel/tracing/trace | grep -E "qcom|remoteproc" | head -20
```

示例输出：

```text theme={null}
 2)   0.432 us    |          qcom_geni_serial_isr();
 2)   1.201 us    |        handle_irq_event_percpu();
 2)   3.567 us    |      handle_fasteoi_irq();
```

### 跟踪启动 initcall

在内核命令行中添加以下内容，可在启动时跟踪所有 initcall：

```text theme={null}
initcall_debug
```

使用以下命令解析结果：

```bash theme={null}
dmesg | grep "initcall.*after" \
      | sed 's/.*initcall \(.*\) returned.* after \([0-9]*\) usecs/\2 \1/' \
      | sort -rn | head -20
```

如需完整的 ftrace 文档，请参阅
[Function Tracer](https://docs.kernel.org/trace/ftrace.html)。

## MMIO 跟踪事件

内存映射 I/O（MMIO）跟踪记录内核通过 `__raw_{read,write}{b,l,w,q}` 访问器执行的每一次寄存器读写。它们对于诊断 Qualcomm<sup>®</sup> SoC 上以下几类崩溃至关重要：

**表：MMIO 崩溃场景**

| **场景**    | **说明**                                      | **典型症状**      |
| :-------- | :------------------------------------------ | :------------ |
| 未开时钟的访问   | 在该模块的时钟启用之前尝试访问寄存器                          | 立即重启 / SError |
| 受保护的寄存器空间 | 寄存器区域需要 EL3 特权；来自 EL1/EL2 的访问被 TrustZone 拒绝 | 同步异常 / NoC 错误 |
| xPU 违规    | 内存保护单元阻止了来自该总线主设备的访问                        | 互连挂起或同步中止     |

### 启用 MMIO 跟踪

Kconfig：

```text theme={null}
CONFIG_TRACE_MMIO_ACCESS=y
```

在运行时，通过 tracefs 启用 `rwmmio` 跟踪事件：

```bash theme={null}
# List available rwmmio events
cat /sys/kernel/tracing/available_events | grep rwmmio

# Enable all rwmmio events
cat /sys/kernel/tracing/available_events | grep rwmmio >> /sys/kernel/tracing/set_event

# Enable tracing
echo 1 > /sys/kernel/tracing/tracing_on

# ... reproduce the crash or trigger the driver ...

# Read the trace
echo 0 > /sys/kernel/tracing/tracing_on
cat /sys/kernel/tracing/trace
```

示例输出：

```text theme={null}
rwmmio_read:  gic_peek_irq+0xd0/0xd8       readl  addr=0xffff800010040104
rwmmio_write: gic_poke_irq+0xe4/0xf0       writel addr=0xffff800010040184
rwmmio_read:  gic_do_wait_for_rwp+0x54/0x90 readl  addr=0xffff800010040000
rwmmio_write: gic_set_affinity+0x1bc/0x1e8  writeq addr=0xffff800010046130
```

每行标明了调用函数（含偏移量）、访问类型（`readl`/`writel`/`writeq`）以及物理地址。将该地址与 SoC 技术参考手册进行交叉比对，即可确定崩溃所涉及的寄存器模块。

### 崩溃时在控制台转储 MMIO 跟踪

为了在系统崩溃、来不及读取 tracefs 时也能捕获 MMIO 跟踪，可启用将 ftrace 缓冲区转储到控制台的功能：

```bash theme={null}
echo 1 > /proc/sys/kernel/ftrace_dump_on_oops
```

之后，最后的跟踪条目会包含在串口控制台上的内核 panic 输出中。
