[Need Help] How to Read CNTPCT_EL0 Without Trapping to EL2?
Posted: Thu May 15, 2025 12:31 pm
Hello, I'm having a problem where reads to the CNTPCT_EL0 register traps to EL2 on hardware.
I wrote some basic code to perform delays using the CNTPCT_EL0 and CNTFRQ_EL0 registers. The code is written in Arm64 Assembly and runs at EL1. When I run the code in QEMU, it works perfectly. However, when I run the code on a Raspberry Pi 5, the following instruction always traps to EL2.
I tried to follow the code for the documentation that describes how to access the register from the architecture reference manual.
I set CNTHCTL_EL2.EL1PCTEN to 1. I expected this to fix the issue because I am running at EL1, so the value of CNTPCT_EL0 should be returned. However, the instruction still causes a trap to EL2. The value of ESR_EL2 is 0x6232f921, which just tells me that the instruction to read the register is causing the exception.
I'd appreciate any advice on how to stop this read from trapping to EL2!
I wrote some basic code to perform delays using the CNTPCT_EL0 and CNTFRQ_EL0 registers. The code is written in Arm64 Assembly and runs at EL1. When I run the code in QEMU, it works perfectly. However, when I run the code on a Raspberry Pi 5, the following instruction always traps to EL2.
Code: Select all
mrs x9, CNTPCT_EL0
Code: Select all
if PSTATE.EL == EL0 then
if !(EL2Enabled() && HCR_EL2.<E2H,TGE> == '11') && CNTKCTL_EL1.EL0PCTEN == '0' then
if EL2Enabled() && HCR_EL2.TGE == '1' then
AArch64.SystemAccessTrap(EL2, 0x18);
else
AArch64.SystemAccessTrap(EL1, 0x18);
elsif EL2Enabled() && HCR_EL2.E2H == '0' && CNTHCTL_EL2.EL1PCTEN == '0' then
AArch64.SystemAccessTrap(EL2, 0x18);
elsif EL2Enabled() && HCR_EL2.<E2H,TGE> == '10' && CNTHCTL_EL2.EL1PCTEN == '0' then
AArch64.SystemAccessTrap(EL2, 0x18);
elsif EL2Enabled() && HCR_EL2.<E2H,TGE> == '11' && CNTHCTL_EL2.EL0PCTEN == '0' then
AArch64.SystemAccessTrap(EL2, 0x18);
else
return CNTPCT_EL0;
elsif PSTATE.EL == EL1 then
if EL2Enabled() && CNTHCTL_EL2.EL1PCTEN == '0' then
AArch64.SystemAccessTrap(EL2, 0x18);
else
return CNTPCT_EL0;
elsif PSTATE.EL == EL2 then
return CNTPCT_EL0;
elsif PSTATE.EL == EL3 then
return CNTPCT_EL0;
I'd appreciate any advice on how to stop this read from trapping to EL2!
