重新编译 Linux 内核不使用特定的 CPU 寄存器

Recompile Linux Kernel not to use specific CPU register

我正在做一个实验,将循环索引写入 CPU 寄存器 R11,然后用 gcc -ffixed-r11 构建它,尝试让编译器知道不要使用该寄存器,最后使用性能来衡量它。

但是当我查看报告时(使用perf script),大多数记录条目的R11值不是我所期望的,应该是1..2..3或1这样的数字序列..4..7等。但实际上它只是几个固定值。 (可能受系统调用覆盖影响?)

如何让perf记录我在程序中设置到寄存器的值?或者我必须用 -ffixed-r11 重新编译整个内核才能实现?

谢谢大家

当你只想用 perf 采样一些寄存器时,你不应该尝试重新编译内核。据我了解,内核有自己的一组寄存器,不会覆盖用户 R11。 syscall 接口使用一些无法更改的固定寄存器(您可以尝试不同的寄存器吗?)并且通常有 glibc 系统调用网关可能会使用一些额外的寄存器(它们不在内核中,它们是用户-space 代码;通常用汇编程序生成或编写)。您可以尝试使用 gdb 来监视要更改的寄存器以找出是谁做的。它可以做到这一点(嗯,对 SO 上的同一个用户再 link):gdb: breakpoint when register will have value 0xffaa 喜欢 gdb ./program 然后 gdb 命令 start; watch $r11; continue; where.

两周前有关于使用 perf 进行寄存器值采样的问题

I follow this document and using perf record with --intr-regs=ax,bx,r15, trying to log additional CPU register information with PEBS record.

虽然有 x86 和 PEBS,但 ARM 可能也实现了 --intr-regs。检查 perf record --intr-regs=\? (man perf-record: "To list the available registers use --intr-regs=\?") 的输出以查找支持状态和注册名称。

要打印寄存器,请使用 perf script -F ip,sym,iregs 命令。在一些 linux 提交中有示例:

  # perf record --intr-regs=AX,SP usleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.016 MB perf.data (8 samples) ]
  # perf script -F ip,sym,iregs | tail -5
   ffffffff8105f42a native_write_msr_safe   AX:0xf    SP:0xffff8802629c3c00
   ffffffff8105f42a native_write_msr_safe   AX:0xf    SP:0xffff8802629c3c00
   ffffffff81761ac0 _raw_spin_lock   AX:0xffff8801bfcf8020    SP:0xffff8802629c3ce8
   ffffffff81202bf8 __vma_adjust_trans_huge   AX:0x7ffc75200000    SP:0xffff8802629c3b30
   ffffffff8122b089 dput   AX:0x101    SP:0xffff8802629c3c78
  #

如果您需要金属的周期精确轮廓 CPU activity 那么 perf 不是正确的工具,因为它最多只是一个近似值,因为它仅在以下位置对程序进行采样select 点。参见 this video on perf by Clang developer Chandler Carruth

相反,您应该单步执行程序以准确监视寄存器发生的情况。或者您可以在没有 OS 的情况下对系统裸机进行编程,但这可能超出了此处的范围。