如何读取x86 intel处理器的PMC(Performance Monitoring Counter)

How to read PMC(Performance Monitoring Counter) of x86 intel processor

我的台式机是英特尔 x86_64 处理器和 Ubuntu 操作系统。

我知道有一个 perf 工具可以获取程序的统计信息列表。 但是我想做的是直接读取性能计数器而不使用 perf 工具。

  1. 第一个问题

第一个问题是我从 Github 下载了这段代码:Github Code Reference

它使用 linux-headers-5.3.0-40-generic 内核成功编译,没有任何错误。一旦我使用 "insmod" .ko 文件,系统就会挂起。当我检查 dmesg 时没有插入 .ko 文件,所以我必须在执行 "insmod" .ko 文件后停止它。发生这种情况是因为我试图进行未经授权的访问吗?如果有我可以尝试的建议,我很高兴听到。

对应代码如下

static void set_pce(void *arg)
{
    int to_val = (arg != 0);
    u_int64_t cr4_val;

    cr4_val = __read_cr4();
    if (to_val) {
        cr4_val |= X86_CR4_PCE;
    } else {
        cr4_val &= ~X86_CR4_PCE;
    }

    __write_cr4(cr4_val);
}

static int __init user_rdpmc_init(void){
    int cpu;

    num_cpus = num_online_cpus();

    printk(KERN_INFO "Enabling RDPMC from ring 3 for %d CPUs\n", num_cpus);
    for (cpu = 0; cpu < num_cpus; cpu++) {
    smp_call_function_single(cpu, set_pce, (void *) 1, 1);
    }

   return 0;
}
  1. 第二个问题

第二个问题是我在 Ubuntu 桌面上使用 linux-headers-5.3.0-40-generic 内核版本。我从 kernel.org 下载了内核代码版本 5.5.3。我完全遵循了 5.5.3 内核代码中给出的 perf 代码,发现 linux-5.5.3/arch/x86/events/intel 目录下的 core.c 文件实际上在设置和读取性能计数器。我使用 core.c 文件内容使其成为读取性能计数器的模块。当我编译它时,它会产生一堆错误,因为我使用 linux-headers-5.3.0-40-generic 来构建模块,但我的 ubuntu 内核没有链接到的所有头文件来自 kernel.org.

内核代码的 core.c 文件

如何让我的 Ubuntu 内核使用 kernel.org 中链接到 core.c 的所有文件并构建 .ko 文件?

或者是否有任何模块源代码具有 x86 性能计数器读数,我可以用作参考?

提前感谢您的帮助。

I know there is perf tool to get a list of statistics of a program. But what I am trying to do is read performance counter directly without using the perf tool.

如果你不想使用perf工具,你可以尝试使用oprofile工具或intel vtune或https://github.com/RRZE-HPC/likwid or https://github.com/opcm/pcm. Or you can use perf_event_open syscall which is how perf tool works (you can study or modify perf tool sources from https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf/ - perf工具版本可能不等于内核版本)。

如果您想以 root 身份访问 msr 寄存器,请使用 modprobe msr(这是 standard kernel module, already compiled for your kernel in ubuntu) and wrmsr and rdmsr tools (msr-tools deb/ubuntu package, by intel), like in slide 27 of Performance Monitoring Chris Dahnken Intel SSG EMEA HPCTC 介绍。

我不明白你为什么要在没有 perf 工具的情况下使用性能计数器。如果您想从程序内部获取计数器读数,例如在某些循环之前和之后,您可以直接使用 perf_event_open syscall (具有特定的 ioctl)。 (或尝试使用 perf stat + 相同的 ioctls PERF_EVENT_IOC_* 或尝试学习 perf + JIT 集成)

或者您可以使用现有的内核模块,它将 msr 注册访问权限导出给 root 用户 - the msr.ko. And msr tools - https://01.org/msr-tools. Or with this msr+pmc example https://technicalandstuff.wordpress.com/2015/05/15/using-intels-pcm-in-linux-and-inside-c/ + https://software.intel.com/en-us/articles/intel-performance-counter-monitor (https://github.com/opcm/pcm)

https://github.com/RRZE-HPC/likwid.

中也有一些性能计数器的使用示例

您也可以使用PAPI library to access counters from your code, it will handle most of perf_event_open stuff for you. http://icl.cs.utk.edu/projects/papi/wiki/PAPITopics:Getting_Started

First Questions is I downloaded this code https://github.com/softdevteam/user_rdpmc ... "insmod" the .ko file, the system hangs.

"Stars" 评级太低,代码太旧(2016 年),无法真正对挂起进行任何调查。直接访问 PMC 可能会干扰 NMI 看门狗(以 root 身份执行 echo 0 > /proc/sys/kernel/nmi_watchdog)或其他 perf 会话。使用 perf_event_open 系统调用更安全。

Second question ... discovered that core.c file under linux-5.5.3/arch/x86/events/intel directory actually does setting and reading the performance counters

此文件是 perf_event_open 系统调用实现的一部分(perf_events 内核子系统,https://github.com/torvalds/linux/tree/master/kernel/events + https://github.com/torvalds/linux/tree/master/arch/x86/events)。

要使用此代码,您可以使用 perf 工具或 perf_event_open 系统调用。

你不应该将内核的 perf_events 子系统编译为单独的模块,因为它已经编译到你的内核中(intel/amd 特定部分可以部分 ko)并且子系统本身不支持编译为模块:

https://github.com/torvalds/linux/tree/master/kernel/events

Makefile: obj-y := core.o ring_buffer.o callchain.o

How can I make my Ubuntu kernel use all the files linked to core.c from kernel.org and build the .ko file?

你的 ubuntu 内核已经编译了所有 perf_events 子系统文件,一些链接到内核映像中,其他是已经安装的 .ko 文件,如 intel-rapl-perf.ko

$ grep _PERF_ /boot/config-`uname -r`
$ ls -l /lib/modules/`uname -r`/kernel/arch/x86/events/intel