Skip to content

arch: arm: Fix Cortex-R power management interrupt handling #21758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

stephanosio
Copy link
Member

@stephanosio stephanosio commented Jan 8, 2020

The system power management handling code in the '_isr_wrapper' enables
interrupts by executing the 'cpsie i' instruction, which causes a
system crash on the Cortex-R devices because the Cortex-R arch port
does not support nested interrupts at this time.

This commit restricts the interrupt state manipulations in the system
power management code to the Cortex-M arch, in order to prevent
interrupt nesting on other AArch32 family archs (only Cortex-R for
now).

Signed-off-by: Stephanos Ioannidis <[email protected]>

p.s. I am planning to implement arch-level interrupt nesting support for the Cortex-R (and AArch32 Cortex-A) in the near future.

Copy link
Member

@ioannisg ioannisg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine with me, I've got two comments

  • we're mixing CPU_CORTEX_M and ARMV..... Kconfig options here; could we stick to one variant of Kconfigs?
  • would it be possible to explain inline why the change-processor-state instructions are not used for cotex-R?

@stephanosio
Copy link
Member Author

stephanosio commented Jan 8, 2020

  • we're mixing CPU_CORTEX_M and ARMV..... Kconfig options here; could we stick to one variant of Kconfigs?

The main reason I went with defined(CONFIG_CPU_CORTEX_M) instead of defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) || defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) is that the former is much shorter and simpler to use (it would be nice if there is a symbol like CONFIG_ARM_M or CONFIG_ARMVX_M, but then that is pretty much what CONFIG_CPU_CORTEX_M is in the current configuration layout).

If you still think we should stick with the longer form, I will change it.

  • would it be possible to explain inline why the change-processor-state instructions are not used for cotex-R?

The cpsid i and cpsie i instructions used there basically translate to irq_lock() and irq_unlock(), respectively, for checking/updating _kernel.idle and calling z_sys_power_save_idle_exit (many things will go wrong if an ISR is preempted by a higher priority IRQ while this happens).

This is necessary on the Cortex-M because the it supports interrupt nesting and hence interrupts are enabled by default when entering an ISR (this is automatically done by the NVIC core).

As for the Cortex-R, the current arch port does not/cannot support interrupt nesting because context preservation is implemented in a quite incorrect/non-standard way (I am planning to address this in the near future). Note that, without interrupt nesting support, interrupts are (and must be) disabled inside an ISR; hence, it is not necessary to use a lock for checking and updating _kernel.idle.

I will add FIXME comments referencing this PR, since they should be removed once interrupt nesting support is implemented in the Cortex-R arch port (which will eventually become AArch32 Cortex-A port as well).

The system power management handling code in the '_isr_wrapper' enables
interrupts by executing the 'cpsie i' instruction, which causes a
system crash on the Cortex-R devices because the Cortex-R arch port
does not support nested interrupts at this time.

This commit restricts the interrupt state manipulations in the system
power management code to the Cortex-M arch, in order to prevent
interrupt nesting on other AArch32 family archs (only Cortex-R for
now).

Signed-off-by: Stephanos Ioannidis <[email protected]>
@ioannisg ioannisg added the Trivial Changes that can be reviewed by anyone, i.e. doc changes, minor build system tweaks, etc. label Jan 8, 2020
@ioannisg
Copy link
Member

ioannisg commented Jan 8, 2020

Thanks for the update @stephanosio , I think the fixme text looks fine

The cpsid i and cpsie i instructions used there basically translate to irq_lock() and irq_unlock(), respectively, for checking/updating _kernel.idle and calling z_sys_power_save_idle_exit (many things will go wrong if an ISR is preempted by a higher priority IRQ while this happens).

As discussed offline this is not accurate for ARMv7-M where CPS does more than IRQ_lock/unlock, which just modify the BASEPRI.

@ioannisg ioannisg added this to the v2.2.0 milestone Jan 8, 2020
@ioannisg ioannisg added the bug The issue is a bug, or the PR is fixing a bug label Jan 8, 2020
@ioannisg ioannisg self-assigned this Jan 8, 2020
@ioannisg ioannisg merged commit 916a8eb into zephyrproject-rtos:master Jan 8, 2020
@stephanosio stephanosio deleted the cortex_r_fix_pm_isr branch April 23, 2020 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ARM ARM (32-bit) Architecture area: Kernel area: Power Management bug The issue is a bug, or the PR is fixing a bug Trivial Changes that can be reviewed by anyone, i.e. doc changes, minor build system tweaks, etc.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants