重新编译 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 的情况下对系统裸机进行编程,但这可能超出了此处的范围。
我正在做一个实验,将循环索引写入 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 的情况下对系统裸机进行编程,但这可能超出了此处的范围。