Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在gem5内使用ARM PMU时使用perf_事件_Linux_Arm_Gem5 - Fatal编程技术网

Linux 在gem5内使用ARM PMU时使用perf_事件

Linux 在gem5内使用ARM PMU时使用perf_事件,linux,arm,gem5,Linux,Arm,Gem5,我知道ARM PMU已经部分实现,这要感谢gem5源代码和一些出版物 我有一个二进制文件,它使用perf_事件在基于Linux的操作系统上访问ARM处理器下的PMU。它是否可以在ARMISA下使用Linux内核的gem5完整系统模拟中使用perf_事件 到目前为止,我还没有找到正确的方法。如果有人知道,我将非常感激 上下文 由于gem5的未实现功能,我无法使用性能监视单元(PMU)。可以找到邮件列表上的参考。个人补丁后,可通过perf\u event访问PMU。幸运的是,一个类似的补丁将很快在官

我知道ARM PMU已经部分实现,这要感谢gem5源代码和一些出版物

我有一个二进制文件,它使用perf_事件在基于Linux的操作系统上访问ARM处理器下的PMU。它是否可以在ARMISA下使用Linux内核的gem5完整系统模拟中使用perf_事件

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

上下文 由于gem5的未实现功能,我无法使用性能监视单元(PMU)。可以找到邮件列表上的参考。个人补丁后,可通过
perf\u event
访问PMU。幸运的是,一个类似的补丁将很快在官方的gem5版本中发布,可以看到。由于一条消息中的链接数量限制,补丁将在另一个答案中描述

如何使用PMU C源代码 这是一个使用
perf_event
的C源代码的最小工作示例,用于计算分支预测器单元在特定任务期间预测失误的分支数:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <sys/syscall.h>
#include <linux/perf_event.h>

int main(int argc, char **argv) {
    /* File descriptor used to read mispredicted branches counter. */
    static int perf_fd_branch_miss;
    
    /* Initialize our perf_event_attr, representing one counter to be read. */
    static struct perf_event_attr attr_branch_miss;
    attr_branch_miss.size = sizeof(attr_branch_miss);
    attr_branch_miss.exclude_kernel = 1;
    attr_branch_miss.exclude_hv = 1;
    attr_branch_miss.exclude_callchain_kernel = 1;
    /* On a real system, you can do like this: */
    attr_branch_miss.type = PERF_TYPE_HARDWARE;
    attr_branch_miss.config = PERF_COUNT_HW_BRANCH_MISSES;
    /* On a gem5 system, you have to do like this: */
    attr_branch_miss.type = PERF_TYPE_RAW;
    attr_branch_miss.config = 0x10;
    
    /* Open the file descriptor corresponding to this counter. The counter
       should start at this moment. */
    if ((perf_fd_branch_miss = syscall(__NR_perf_event_open, &attr_branch_miss, 0, -1, -1, 0)) == -1)
        fprintf(stderr, "perf_event_open fail %d %d: %s\n", perf_fd_branch_miss, errno, strerror(errno));
    
    /* Workload here, that means our specific task to profile. */

    /* Get and close the performance counters. */
    uint64_t counter_branch_miss = 0;
    read(perf_fd_branch_miss, &counter_branch_miss, sizeof(counter_branch_miss));
    close(perf_fd_branch_miss);

    /* Display the result. */
    printf("Number of mispredicted branches: %d\n", counter_branch_miss);
}
我们通过
addArchEvents
我们的系统组件(
dtb
itb
等)将PMU与它们链接,因此PMU将使用这些组件的内部计数器(称为探测器)作为系统的公开计数器

for cpu in system.cpu_cluster.cpus:
    for isa in cpu.isa:
        isa.pmu = ArmPMU(interrupt=ArmPPI(num=20))
        # Add the implemented architectural events of gem5. We can
        # discover which events is implemented by looking at the file
        # "ArmPMU.py".
        isa.pmu.addArchEvents(
            cpu=cpu, dtb=cpu.dtb, itb=cpu.itb,
            icache=getattr(cpu, "icache", None),
            dcache=getattr(cpu, "dcache", None),
            l2cache=getattr(system.cpu_cluster, "l2", None))
截至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是一个常规文件。这用于使内核在不同体系结构之间可移植,而无需为每次硬件更改重新编译。DTB遵循设备树引用,并从设备树源(DTS)文件(常规文本文件)编译。你可以学到更多和更多

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

补丁的作用是什么 该补丁向ISA和CPU文件添加一个条目,以支持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设备树编译器一起安装。最后,我们在根节点(
/
)下创建了这个
pmu
DTB条目:


Pierre精彩答案的两个快速补充:

  • 对于截至gem5 937241101fae2cd0755c43c33bab2537b47596a2的fs.py,所缺少的全部内容适用于fs.py,如所示:

  • C示例也可以在
    man perf\u event\u open


嗨,Pierre,您是遇到了gem5的具体问题还是关于如何使用它们的更一般的问题?如果可能的话,试着首先在一个更稳定/快速的模拟器(如QEMU/real hardware)上处理更一般的问题,然后再到gem5(速度较慢且通常更复杂)。虽然不确定QEMU是否支持,但值得检查。嗨,谢谢你的回答。也许我应该更精确些。目前,我有一个二进制文件(由我自己开发),它在真正的ARM硬件上使用perf_事件,以获取缓存未命中和预测失误的分支,并且工作良好。我的perf_event_attr.type配置了perf_type_HARDWARE和.config字段,其中perf_COUNT_HW_CACHE_MISSES和另一个perf_COUNT_HW_BRANCH_MISSES。然而,当我把这个二进制文件放在gem5 fs模拟中,配置了DerivO3CPU、ArmSystem和RealView平台时,我得到了以下错误“eNote(2):没有这样的文件或目录”,我不知道我们是否可以通过perf_事件访问gem5中的PMU。如果是这样,也许我们必须使用原始事件?在configs下的gem5示例代码中,我在devices.py中发现了一个代码片段,它“每个PE实例化1个ArmPMU”(addPMUs())。然而,经过几次尝试,我不明白如何使用它以及它与perf_event的关系。好的,感谢您的澄清。因此,基于enoint的
perf_事件
文件不是由Linux内核创建的,是吗?我会四处打听的。
perf\u事件
文件。。。你是说?是的,它不是由内核创建的(等于
-1
)。我希望明确指出,此错误在
perf\u event\u open()
syscall返回时出现。最后,此错误记录在
perf_event_open.2
手册页中,也讨论了此错误。非常感谢您提供的宝贵信息,并感谢Gem5开发人员。补丁版本何时发布?我有稳定的版本(v20.1.0.0/2020年10月1日),但是,我遇到了相同的问题,到目前为止,我还没有找到解决方案,即我无法访问Gem5中模拟ARM中的HPCs。
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
/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";

[...]
  [    0.239967] hw perfevents: enabled with armv8_pmuv3 PMU driver, 32 counters available
for  cpu in test_sys.cpu:
    if buildEnv['TARGET_ISA'] in "arm":
        for isa in cpu.isa:
            isa.pmu = ArmPMU(interrupt=ArmPPI(num=20))
            isa.pmu.addArchEvents(
                cpu=cpu, dtb=cpu.mmu.dtb, itb=cpu.mmu.itb,
                icache=getattr(cpu, "icache", None),
                dcache=getattr(cpu, "dcache", None),
                l2cache=getattr(test_sys, "l2", None))