[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <aCbhBttvi8mvsyGE@perf>
Date: Fri, 16 May 2025 15:53:58 +0900
From: Youngmin Nam <youngmin.nam@...sung.com>
To: Mark Rutland <mark.rutland@....com>, Marc Zyngier <maz@...nel.org>,
Daniel Lezcano <daniel.lezcano@...aro.org>, Thomas Gleixner
<tglx@...utronix.de>
Cc: linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
junhosj.choi@...sung.com, hajun.sung@...sung.com, joonki.min@...sung.com,
d7271.choe@...sung.com, jkkkkk.choi@...sung.com, jt1217.kim@...sung.com,
qperret@...gle.com, willdeacon@...gle.com, dhyun.cha@...sung.com,
kn_hong.choi@...sung.com, mankyum.kim@...sung.com
Subject: [QUESTION] arch_counter_register() restricts CNTPT access when
booted in EL1, even if EL2 is supported
Hi arm arch timer experts,
While reviewing the arm_arch_timer code in Linux 6.12,
I noticed that the function arch_counter_register() restricts the use of the physical counter (cntpct_el0)
on systems where the kernel is running in EL1, even if EL2 is supported and cntpct_el0 is accessible.
In our case:
- We are not using pKVM.
- The kernel is booted in EL1.
- We disabled VIRT_PPI and explicitly selected PHYS_NONSECURE_PPI for the timer refering to below code.
static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
{
if (is_kernel_in_hyp_mode())
return ARCH_TIMER_HYP_PPI;
if (!is_hyp_mode_available() && arch_timer_ppi[ARCH_TIMER_VIRT_PPI])
return ARCH_TIMER_VIRT_PPI;
if (IS_ENABLED(CONFIG_ARM64))
return ARCH_TIMER_PHYS_NONSECURE_PPI;
return ARCH_TIMER_PHYS_SECURE_PPI;
}
Despite this, the `arch_counter_register()` logic selects `cntvct_el0` unconditionally
due to the `!is_hyp_mode_available()` condition.
static void __init arch_counter_register(unsigned type)
{
u64 (*scr)(void);
u64 start_count;
int width;
/* Register the CP15 based counter if we have one */
if (type & ARCH_TIMER_TYPE_CP15) {
u64 (*rd)(void);
if ((IS_ENABLED(CONFIG_ARM64) && !is_hyp_mode_available()) ||
arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) {
if (arch_timer_counter_has_wa()) {
rd = arch_counter_get_cntvct_stable;
scr = raw_counter_get_cntvct_stable;
} else {
rd = arch_counter_get_cntvct;
scr = arch_counter_get_cntvct;
}
} else {
if (arch_timer_counter_has_wa()) {
rd = arch_counter_get_cntpct_stable;
scr = raw_counter_get_cntpct_stable;
} else {
rd = arch_counter_get_cntpct;
scr = arch_counter_get_cntpct;
}
}
As I understand it, `is_hyp_mode_available()` checks whether the kernel booted into EL2
— not whether EL2 is *supported* by the hardware.
Therefore, even on systems where EL2 exists and `cntpct_el0` is accessible from EL1,
the kernel still forces the use of `cntvct_el0` if the boot EL is EL1.
Is this restriction to `cntvct_el0` in EL1 an architectural requirement,
or simply a conservative default to avoid possible traps on some systems?
If the hardware clearly supports EL2 and allows CNTPT access from EL1, could this restriction be relaxed?
Any guidance would be appreciated.
Powered by blists - more mailing lists