Hi Giacomo, Thank you for your reply. Your hint about the DTB gives me a great starting point to make a lot of research about it, and its relation between the Linux kernel and the ARM PMU. I though that I would be able to fix this myself, by studying how gem5 generate the DTB and how the PMU is declared in a DTB. However, despite that I have learned a lot of things, I was wrong.
In my system script, I declare and attach a PMU like this: > ints = [20, 21, 22, 23] > assert len(ints) == len(system.cpu_cluster.cpus) > for cpu, pint in zip(system.cpu_cluster.cpus, ints): > for isa in cpu.isa: > isa.pmu = ArmPMU(interrupt=ArmPPI(num=pint)) > isa.pmu.addArchEvents( > cpu=cpu, dtb=cpu.dtb, itb=cpu.itb, > icache=getattr(cpu, "dcache", None), > dcache=getattr(cpu, "icache", None), > l2cache=getattr(system.cpu_cluster, "l2", None)) And I applied this patch to gem5: > 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..e5d0ed3dd 100644 > --- i/src/cpu/BaseCPU.py > +++ w/src/cpu/BaseCPU.py > @@ -302,6 +302,9 @@ class BaseCPU(ClockedObject): > node.appendPhandle(phandle_key) > cpus_node.append(node) > + for subnode in self.recurseDeviceTree(state): > + node.append(subnode) > + > yield cpus_node > def __init__(self, **kwargs): I end up with a DTB with this: > pmu { > compatible = "arm,armv8-pmuv3"; > interrupts = <0x01 0x04 0xf04>; > }; > pmu { > compatible = "arm,armv8-pmuv3"; > interrupts = <0x01 0x05 0xf04>; > }; > pmu { > compatible = "arm,armv8-pmuv3"; > interrupts = <0x01 0x06 0xf04>; > }; > pmu { > compatible = "arm,armv8-pmuv3"; > interrupts = <0x01 0x07 0xf04>; > }; One PMU declaration for one core. However, it does not work. I don't even know if this kind of declaration is correct, maybe we have to declare the PMU once for all cores -- instead of one by core ? Note that the configuration of the kernel is correct to normally initialize perf_event (in /proc/config.gz). Many thanks if you help me, and many thanks also if you post a patch in the future. Best, Pierre > De: "Giacomo Travaglini" <giacomo.travagl...@arm.com> > À: "gem5-users" <gem5-users@gem5.org> > Cc: "Pierre Ayoub" <pierre.ay...@irisa.fr> > Envoyé: Jeudi 24 Septembre 2020 12:09:17 > Objet: RE: Using perf_event with the ARM PMU inside gem5 on Linux > Hi Pierre, > First of all many thanks for explaining in detail what is your problem. This > is > very helpful. > The reason why you are not able to use perf_events is probably because the > kernel is not aware of the presence of PMUs. This is usually communicated to > Linux via the DTB. I can see how we are not enabling DTB autogen for the > ArmPMU. > I will post a patch > Kind Regards > Giacomo > From: Pierre Ayoub via gem5-users <gem5-users@gem5.org> > Sent: 23 September 2020 08:45 > To: gem5-users@gem5.org > Cc: Pierre Ayoub <pierre.ay...@irisa.fr> > Subject: [gem5-users] Using perf_event with the ARM PMU inside gem5 on Linux > Hi gem5's users, > TL;DR: > ------ > I know that the ARM PMU is partially implemented, thanks to the gem5 source > code and some publications. I have a binary which uses perf_event to access > the > PMU on a Linux-based OS, under an ARM processor, on real hardware. Could it > use > perf_event inside a gem5 full-system simulation with a Linux kernel, under the > ARM ISA? So far, I haven't found the right way to do it. If someone knows, I > will be very grateful! > Detailed information: > --------------------- > I have a binary (developed by myself) which uses perf_event on real ARM > hardware, to get cache misses and mispredicted branches, and it works well. My > "perf_event_attr.type" is configured with "PERF_TYPE_HARDWARE" and the > ".config" field with "PERF_COUNT_HW_CACHE_MISSES" and another with > "PERF_COUNT_HW_BRANCH_MISSES." However, when I put this binary on a gem5 fs > simulation, configured with the DerivO3CPU, ArmSystem, and RealView platform, > I > got the following error: > "ENOENT (2): No such file or directory" > The perf_event file descriptor is not created by the kernel (equal to -1). I > wish to precise that this error arrives at the return of the perf_event_open() > syscall. Finally, this error is documented in the perf_event_open.2 manpage, > and also discussed here. However, it didn't help me to understand the error > regarding gem5. > I don't know if we can access the PMU through perf_event into gem5. If so, > maybe we have to use RAW events? (i.e., do you know if perf_event is supposed > to be initialized with PERF_EVENT_HARDWARE or PERF_EVENT_RAW, to be used with > gem5?) In the gem5 example code under configs, I have found a snippet in > devices.py which "Instantiates 1 ArmPMU per PE" (addPMUs()). However, after > few > tries, I don't understand how to use this correctly and how it is related to > perf_event. > I used a code similar to addPMUs() in devices.py, with PPI interrupts number > 20, 21, 22, and 23 (one by core) according to the RealView interrupts mapping, > with the ArmPPI class. However, perf_event_open() still return the same > error. Note also that I got this message during the boot: > src/arch/arm/pmu.cc:293: warn: Not doing anything for write to miscreg > pmuserenr_el0. > This register is documented in the ARMv8-A architecture manual. I have checked > the pmu.cc file, and saw that writing to this register is not implemented > (TODO > state). Normally, it should not be a problem since this register allows (when > set to 1) userland access to the PMU, which we don't want because I want to > access it through the Linux kernel perf_event interface. > With --debug-flags=PMUVerbose, I get the following: > 0: system.cpu_cluster.cpus0.isa.pmu: Initializing the PMU. > [...] > 0: system.cpu_cluster.cpus0.isa.pmu: PMU: Adding Probe Driven event with id > '0x2'as probe system.cpu_cluster.cpus0.itb:Refills > [...] > 8687351673751: system.cpu_cluster.cpus0.isa.pmu: Assigning PMU to ContextID 0. > [...] > 8687351673751: system.cpu_cluster.cpus0.isa.pmu: updateCounter(31): Disabling > counter > [...] > Now, you know all I know about this issue! > IMPORTANT NOTICE: The contents of this email and any attachments are > confidential and may also be privileged. If you are not the intended > recipient, > please notify the sender immediately and do not disclose the contents to any > other person, use it for any purpose, or store or copy the information in any > medium. Thank you.
_______________________________________________ gem5-users mailing list -- gem5-users@gem5.org To unsubscribe send an email to gem5-users-le...@gem5.org %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s