如何读取x86 Intel处理器的PMC(性能监视计数器)

4

我的桌面电脑装有Ubuntu操作系统和Intel x86_64处理器。

我知道有perf工具可以获取程序的统计数据列表,但是我的目的是直接读取性能计数器而不使用perf工具。

  1. 第一个问题

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

它在linux-headers-5.3.0-40-generic内核下编译成功,并且没有任何错误。但是当我使用“insmod”命令加载.ko文件时,系统会挂起。当我检查dmesg时,发现.ko文件没有被插入,所以我不得不在“insmod”之后终止它。这是因为我试图未经授权访问吗?如果有建议可以尝试的话,我很乐意听取。

对应的代码如下。

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性能计数器读取的模块源代码可以供我参考?

提前感谢您的帮助。


2
使用 perf 工具可以为您完成此操作。 - 0andriy
1
要从程序中获取perfcounter读数,可以使用perf_event_open系统调用(它也被perf使用),或者一些内核模块,这些模块将导出msr访问权限给root,例如msr.ko。您可以重用PAPI库来访问计数器,或者使用https://github.com/RRZE-HPC/likwid或`modprobe msr + https://github.com/opcm/pcm或+一些bash与wrmsr/rdmsr`,就像在https://agenda.cnaf.infn.it/getFile.py/access?resId=13&materialId=slides&confId=466中所示。 - osgx
2
请解释一下,为什么您“试图直接读取性能计数器而不使用perf工具”,您的任务是什么? - osgx
1个回答

4
如果您不想使用perf工具,可以尝试使用oprofile工具或英特尔vtune或https://github.com/RRZE-HPC/likwidhttps://github.com/opcm/pcm。 或者您可以使用perf_event_open系统调用,这是perf工具的工作方式(您可以从https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf/学习或修改perf工具源代码 - perf工具版本可能不等于内核版本)。
如果你想以root身份访问msr寄存器,请使用modprobe msr(这是标准内核模块,已编译到Ubuntu的内核中),和wrmsr以及rdmsr工具(msr-tools deb/ubuntu包,由英特尔提供),就像性能监控Chris Dahnken Intel SSG EMEA HPCTC演示文稿第27页所示。
我不明白为什么你想在没有perf工具的情况下使用性能计数器。如果你想从程序内部获取计数器读数,例如在某些循环之前和之后,可以直接使用 perf_event_open系统调用(带有特定的ioctls)。 (或尝试使用perf stat+相同的ioctls PERF_EVENT_IOC_*,或尝试学习perf + JIT集成)

或者您可以使用现有的内核模块,将msr寄存器访问权限导出给root用户 - the msr.ko。以及msr工具- https://01.org/msr-tools。或者使用这个msr+pmc示例 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)

还有一些perf计数器使用示例在 https://github.com/RRZE-HPC/likwid 中。

你也可以使用PAPI库从代码中访问计数器,它将为您处理大部分perf_event_open的内容。http://icl.cs.utk.edu/projects/papi/wiki/PAPITopics:Getting_Started

首先问题是我下载了这个代码https://github.com/softdevteam/user_rdpmc... "insmod" .ko文件后,系统挂起。

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

第二个问题……发现linux-5.5.3/arch/x86/events/intel目录下的core.c文件实际上可以设置和读取性能计数器

该文件是perf_event_open syscall的实现之一(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 syscall。

不应将perf_events子系统编译为单独的模块,因为它已经编译到您的内核中 (intel/amd特定部分可能是ko形式),而Subsystem本身不支持作为模块编译:

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

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

我该如何让我的Ubuntu内核使用从kernel.org链接到core.c的所有文件并构建.ko文件?
您的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

感谢提供详细信息和一些资源,我需要在研究目的下不使用perf工具读取性能计数器,因此我无法确定为什么需要它。我将尝试您给出的建议,并在有更多问题时再进一步请教。非常感谢。 - rhdhyekw93

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接