如何使用RDMSR/WRMSR指令读取Intel Skylake处理器的PMC?
我之前在调试Skylake平台的PMC(性能监控计数器)时也踩过不少类似的坑,结合Intel卷3B手册和实际调试经验,给你梳理几个必须检查的点:
先确认计数器是否真的被启用
你写入IA32_PERFEVTSEL1(0x187)的0x412e,拆成二进制看的话,bit24(EN位,启用计数器的关键位)是0!这意味着你根本没打开计数器,读IA32_PMC1(0xC2)自然拿不到有效计数。正确的配置需要把EN位置1,也就是至少要写0x100412e(如果只保留你原来的其他位设置),或者根据需求调整USR/OS位(分别控制用户态/内核态计数)。严格遵循PMC初始化的正确顺序
乱序操作很容易导致计数异常,标准流程应该是:- 先读取并保存
IA32_PERFEVTSEL1的原有值(避免影响其他工具的使用) - 写入
IA32_PERFEVTSEL1为0,暂时禁用计数器 - 把
IA32_PMC1清零,避免累加历史计数 - 写入你需要的配置值(记得置EN位为1)
- 运行你的测试负载(比如触发L3缓存缺失的代码)
- 读取
IA32_PMC1获取计数 - 恢复之前保存的
IA32_PERFEVTSEL1值
- 先读取并保存
绑定CPU核心再操作
PMC是每个CPU核心独立的寄存器,如果你驱动代码没固定核心,可能出现“写核心A的配置,读核心B的计数器”的情况。可以用内核里的get_cpu()/put_cpu()来绑定核心,比如:preempt_disable(); int cpu = get_cpu(); // 这里执行MSR读写操作 put_cpu(); preempt_enable();检查BIOS是否禁用了性能监控
不少Skylake平台的BIOS会默认关闭CPU性能监控功能,你需要进BIOS找类似「Performance Monitoring Counters」「CPU Performance Features」的选项,确保它处于开启状态——如果BIOS锁了,软件层面再怎么调都没用。用perf工具做交叉验证
先抛开驱动,用Linux自带的perf工具验证硬件是否能正常统计L3缺失:perf stat -e LLC-load-misses ./your_test_program如果这个命令能输出合理的计数,说明硬件和系统层面没问题,问题肯定出在你的驱动代码逻辑里;如果perf也读不到有效数据,那优先排查BIOS或系统内核的性能监控限制。
内容的提问来源于stack exchange,提问作者nickeys

