linux - 将 perf_event 与 gem5 内的 ARM PMU 结合使用

标签 linux arm gem5

得益于 gem5 源代码和一些出版物,我知道 ARM PMU 已部分实现。

我有一个二进制文件,它使用 perf_event 访问 ARM 处理器下基于 Linux 的操作系统上的 PMU。它可以在 ARM ISA 下使用 Linux 内核的 gem5 全系统模拟中使用 perf_event 吗?

到目前为止,我还没有找到正确的方法。如果有人知道,我将不胜感激!

最佳答案

截至 2020 年 9 月,需要修补gem5才能使用ARM PMU

编辑:截至 2020 年 11 月,gem5 现已修补,并将包含在下一版本中。感谢开发者!

如何修补gem5

这不是一个干净的补丁(非常简单),它更旨在了解它是如何工作的。尽管如此,这是要从 gem5 源存储库应用 git apply 的补丁:

diff --git i/src/arch/arm/ArmISA.py w/src/arch/arm/ArmISA.py
index 2641ec3fb..3d85c1b75 100644
--- i/src/arch/arm/ArmISA.py
+++ w/src/arch/arm/ArmISA.py
@@ -36,6 +36,7 @@
from m5.params import *
from m5.proxy import *

+from m5.SimObject import SimObject
from m5.objects.ArmPMU import ArmPMU
from m5.objects.ArmSystem import SveVectorLength
from m5.objects.BaseISA import BaseISA
@@ -49,6 +50,8 @@ class ArmISA(BaseISA):
cxx_class = 'ArmISA::ISA'
cxx_header = "arch/arm/isa.hh"

+    generateDeviceTree = SimObject.recurseDeviceTree
+
system = Param.System(Parent.any, "System this ISA object belongs to")

pmu = Param.ArmPMU(NULL, "Performance Monitoring Unit")
diff --git i/src/arch/arm/ArmPMU.py w/src/arch/arm/ArmPMU.py
index 047e908b3..58553fbf9 100644
--- i/src/arch/arm/ArmPMU.py
+++ w/src/arch/arm/ArmPMU.py
@@ -40,6 +40,7 @@ from m5.params import *
from m5.params import isNullPointer
from m5.proxy import *
from m5.objects.Gic import ArmInterruptPin
+from m5.util.fdthelper import *

class ProbeEvent(object):
def __init__(self, pmu, _eventId, obj, *listOfNames):
@@ -76,6 +77,17 @@ class ArmPMU(SimObject):

_events = None

+    def generateDeviceTree(self, state):
+        node = FdtNode("pmu")
+        node.appendCompatible("arm,armv8-pmuv3")
+        # gem5 uses GIC controller interrupt notation, where PPI interrupts
+        # start to 16. However, the Linux kernel start from 0, and used a tag
+        # (set to 1) to indicate the PPI interrupt type.
+        node.append(FdtPropertyWords("interrupts", [
+            1, int(self.interrupt.num) - 16, 0xf04
+        ]))
+        yield node
+
def addEvent(self, newObject):
if not (isinstance(newObject, ProbeEvent)
or isinstance(newObject, SoftwareIncrement)):
diff --git i/src/cpu/BaseCPU.py w/src/cpu/BaseCPU.py
index ab70d1d7f..66a49a038 100644
--- i/src/cpu/BaseCPU.py
+++ w/src/cpu/BaseCPU.py
@@ -302,6 +302,11 @@ class BaseCPU(ClockedObject):
node.appendPhandle(phandle_key)
cpus_node.append(node)

+        # Generate nodes from the BaseCPU children (and don't add them as
+        # subnode). Please note: this is mainly needed for the ISA class.
+        for child_node in self.recurseDeviceTree(state):
+            yield child_node
+
yield cpus_node

def __init__(self, **kwargs):

补丁解决了什么问题

Linux 内核使用设备树 Blob (DTB)(一个常规文件)来声明内核所在的硬件在跑。这用于使内核在不同体系结构之间可移植,而无需针对每个硬件更改进行重新编译。 DTB 遵循设备树引用,并从设备树源 (DTS) 文件(一个常规文本文件)进行编译。您可以了解更多 herehere

问题是PMU应该通过DTB声明给Linux内核。您可以了解更多 herehere 。在模拟系统中,由于系统是由用户指定的,gem5必须自己生成DTB传递给内核,以便后者能够识别模拟的硬件。但是,问题是 gem5 不会为我们的 PMU 生成 DTB 条目。

补丁的作用

该补丁向ISACPU文件添加了一个条目,以启用DTB生成递归来查找PMU。层次结构如下:CPU => ISA => PMU。然后,它在PMU中添加生成函数,以生成一个唯一的DTB条目来声明PMU,并使用中断声明的正确符号在内核中。

使用我们的补丁运行模拟后,我们可以从 DTB 中看到 DTS,如下所示:

cd m5out    
# Decompile the DTB to get the DTS.
dtc -I dtb -O dts system.dtb > system.dts
# Find the PMU entry.
head system.dts

dtc 是设备树编译器,与 sudo apt-get install device-tree-compiler 一起安装。我们最终在根节点 (pmu) 下得到了这个 / DTB 条目:

/dts-v1/;

/ {
    #address-cells = <0x02>;
    #size-cells = <0x02>;
    interrupt-parent = <0x05>;
    compatible = "arm,vexpress";
    model = "V2P-CA15";
    arm,hbi = <0x00>;
    arm,vexpress,site = <0x0f>;

    memory@80000000 {
        device_type = "memory";
        reg = <0x00 0x80000000 0x01 0x00>;
    };

    pmu {
        compatible = "arm,armv8-pmuv3";
        interrupts = <0x01 0x04 0xf04>;
    };

    cpus {
        #address-cells = <0x01>;
        #size-cells = <0x00>;

        cpu@0 {
            device_type = "cpu";
            compatible = "gem5,arm-cpu";

[...]

interrupts = <0x01 0x04 0xf04>; 行中,0x01 用于指示数字 0x04PPI 中断的编号(在 gem5 中用数字 20 声明的中断,区别16 在补丁代码中进行了解释)。 0xf04 对应于一个标志(0x4),指示它是一个“有效高电平敏感”中断,以及一个位掩码(0xf),指示中断应连接到连接到<的所有PE。 em>GIC。您可以了解更多here

如果补丁有效并且您的 ArmPMU 已正确声明,您应该在启动时看到此消息:

  [    0.239967] hw perfevents: enabled with armv8_pmuv3 PMU driver, 32 counters available

关于linux - 将 perf_event 与 gem5 内的 ARM PMU 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63988672/

相关文章:

c++ - 从c/cpp程序中的进程ID获取进程名称(我不能使用/proc/<pid>/cmdline)

Linux命令行排队系统

linux - DevOps Linux 代理 - 以管理员身份运行

assembly - Cortex M3 上的非 Thumb ARM 代码

c - 如果我只有设备缓冲区 (PCIe) 的物理地址,我该如何将此缓冲区映射到用户空间?

ios - iPhone 和 iPad 上的缓存行大小是多少?

assembly - 如何知道程序入口点是ARM还是Thumb模式

gem5 - gem5模拟环境中测量时间的最佳方法是什么

c - 为什么一个简单的 C 程序需要系统调用?

python - 是否可以运行 python 文件,编辑它,然后在第二个终端中运行它