mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-06 17:43:43 +00:00
clocksource: arm_arch_timer: rework PPI selection
Currently, the arch timer driver uses ARCH_TIMER_PHYS_SECURE_PPI to mean the driver will use the secure PPI *and* potentially also use the non-secure PPI. This is somewhat confusing. For arm64 it never makes sense to use the secure PPI, but we do anyway, inheriting this behaviour from 32-bit arm. For ACPI, we may not even have a valid secure PPI, so we need to be able to only request the non-secure PPI. To that end, this patch reworks the timer driver so that we can request the non-secure PPI alone. The PPI selection is split out into a new function, arch_timer_select_ppi(), and verification of the selected PPI is shifted out to callers (as DT may select the PPI by other means and must handle this anyway). We now consistently use arch_timer_has_nonsecure_ppi() to determine whether we must manage a non-secure PPI *in addition* to a secure PPI. When we only have a non-secure PPI, this returns false. Signed-off-by: Fu Wei <fu.wei@linaro.org> Tested-by: Xiongfeng Wang <wangxiongfeng2@huawei.com> [Mark: reword commit message] Signed-off-by: Mark Rutland <mark.rutland@arm.com>
This commit is contained in:
parent
097cd143dd
commit
4502b6bb72
@ -992,7 +992,7 @@ static int __init arch_timer_register(void)
|
||||
case ARCH_TIMER_PHYS_NONSECURE_PPI:
|
||||
err = request_percpu_irq(ppi, arch_timer_handler_phys,
|
||||
"arch_timer", arch_timer_evt);
|
||||
if (!err && arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]) {
|
||||
if (!err && arch_timer_has_nonsecure_ppi()) {
|
||||
ppi = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI];
|
||||
err = request_percpu_irq(ppi, arch_timer_handler_phys,
|
||||
"arch_timer", arch_timer_evt);
|
||||
@ -1114,39 +1114,41 @@ static int __init arch_timer_common_init(void)
|
||||
return arch_timer_arch_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* arch_timer_select_ppi() - Select suitable PPI for the current system.
|
||||
*
|
||||
* If HYP mode is available, we know that the physical timer
|
||||
* has been configured to be accessible from PL1. Use it, so
|
||||
* that a guest can use the virtual timer instead.
|
||||
*
|
||||
* On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE
|
||||
* accesses to CNTP_*_EL1 registers are silently redirected to
|
||||
* their CNTHP_*_EL2 counterparts, and use a different PPI
|
||||
* number.
|
||||
*
|
||||
* If no interrupt provided for virtual timer, we'll have to
|
||||
* stick to the physical timer. It'd better be accessible...
|
||||
* For arm64 we never use the secure interrupt.
|
||||
*
|
||||
* Return: a suitable PPI type for the current system.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
static int __init arch_timer_init(void)
|
||||
{
|
||||
int ret;
|
||||
/*
|
||||
* If HYP mode is available, we know that the physical timer
|
||||
* has been configured to be accessible from PL1. Use it, so
|
||||
* that a guest can use the virtual timer instead.
|
||||
*
|
||||
* If no interrupt provided for virtual timer, we'll have to
|
||||
* stick to the physical timer. It'd better be accessible...
|
||||
*
|
||||
* On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE
|
||||
* accesses to CNTP_*_EL1 registers are silently redirected to
|
||||
* their CNTHP_*_EL2 counterparts, and use a different PPI
|
||||
* number.
|
||||
*/
|
||||
if (is_hyp_mode_available() || !arch_timer_ppi[ARCH_TIMER_VIRT_PPI]) {
|
||||
bool has_ppi;
|
||||
|
||||
if (is_kernel_in_hyp_mode()) {
|
||||
arch_timer_uses_ppi = ARCH_TIMER_HYP_PPI;
|
||||
has_ppi = !!arch_timer_ppi[ARCH_TIMER_HYP_PPI];
|
||||
} else {
|
||||
arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI;
|
||||
has_ppi = (!!arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI] ||
|
||||
!!arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
|
||||
}
|
||||
|
||||
if (!has_ppi) {
|
||||
pr_warn("No interrupt available, giving up\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = arch_timer_register();
|
||||
if (ret)
|
||||
@ -1188,6 +1190,13 @@ static int __init arch_timer_of_init(struct device_node *np)
|
||||
if (IS_ENABLED(CONFIG_ARM) &&
|
||||
of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
|
||||
arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI;
|
||||
else
|
||||
arch_timer_uses_ppi = arch_timer_select_ppi();
|
||||
|
||||
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
|
||||
pr_err("No interrupt available, giving up\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* On some systems, the counter stops ticking when in suspend. */
|
||||
arch_counter_suspend_stop = of_property_read_bool(np,
|
||||
@ -1333,6 +1342,12 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
|
||||
/* Get the frequency from CNTFRQ */
|
||||
arch_timer_detect_rate(NULL, NULL);
|
||||
|
||||
arch_timer_uses_ppi = arch_timer_select_ppi();
|
||||
if (!arch_timer_ppi[arch_timer_uses_ppi]) {
|
||||
pr_err("No interrupt available, giving up\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Always-on capability */
|
||||
arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user