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

标签 linux-kernel x86-64 kernel-module perf intel-pmu

我的桌面是 Intel x86_64 处理器和 Ubuntu 操作系统。

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

  1. 第一个问题

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

它使用 linux-headers-5.3.0-40-generic 内核成功编译,没有任何错误。一旦我使用“insmod”.ko 文件,系统就会挂起。当我检查 dmesg 时,没有插入 .ko 文件,所以我必须在对 .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 内核没有从内核代码链接到 core.c 文件的所有头文件来自 kernel.org。

如何让我的 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/likwidhttps://github.com/opcm/pcm .或者你可以使用 perf_event_open syscall这就是 perf 工具的工作原理(您可以从 https://mirrors.edge.kernel.org/pub/linux/kernel/tools/perf/ 研究或修改 perf 工具源 - 并且 perf 工具版本可能不等于内核版本)。

如果您想以 root 身份访问 msr 寄存器,请使用 modprobe msr(这是 standard kernel module,已在 ubuntu 中为您的内核编译)和 wrmsrrdmsr 工具(msr-tools deb/ubuntu 软件包,by intel),如 Performance Monitoring Chris Dahnken Intel SSG EMEA HPCTC 的幻灯片 27 中所示演示文稿。

我不明白您为什么要在没有 perf 工具的情况下使用性能计数器。如果您想从程序内部获取计数器读数,例如在某些循环之前和之后,您可以使用 perf_event_open syscall (使用特定的 ioctl)直接。 (或尝试使用 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 )

https://github.com/RRZE-HPC/likwid 中也有一些性能计数器使用示例.

您还可以使用 PAPI library要从您的代码访问计数器,它将为您处理大部分 perf_event_open 内容。 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.

“星级”评级太低,代码太旧(2016 年),无法真正对挂起进行任何调查。直接访问 PMC 可能会干扰 NMI 看门狗(以 root 身份执行 echo 0 >/proc/sys/kernel/nmi_watchdog)或其他 perf session 。使用 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

关于linux-kernel - 如何读取x86 intel处理器的PMC(Performance Monitoring Counter),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60896826/

相关文章:

cpu - 如果在独占缓存访问期间发生写操作,为什么会出现数据竞争?

linux-kernel - Linux 内核 - 内核中的哪些数据 block 物理写入特定磁盘分区?

kernel-module - 内核模块 mokutil : failed to enroll new keys

linux - 直接从 linux 内核访问系统性能数据

Linux 驱动程序开发 - 我会严重损害我的系统吗?

linux-kernel - 为什么 x86-64 Linux 内核源代码中的系统调用编号在 334 和 424 之间存在差距?

c - 错误 : dereferencing pointer to incomplete type - in a kernel module

在启动过程的早期调试内核

linux-kernel - Linux 内核中的 IPsec - 如何弄清楚发生了什么

c - x86_64:堆栈框架指针几乎没有用吗?