【问题标题】:How ARM system mode is useful in nested interrupt?ARM 系统模式在嵌套中断中有何用处?
【发布时间】:2014-04-25 06:01:47
【问题描述】:

谁能解释一下,当我们有嵌套中断时,系统模式究竟是如何工作的?

根据 ARM 网站

ARMv4 和更高版本的体系结构包括一种称为系统模式的特权模式,以解决这个问题。系统模式与用户模式共享相同的寄存器,它可以运行需要特权访问的任务,并且异常不再覆盖链接寄存器。

那么系统模式如何利用用户模式的寄存器呢?

最多可以处理什么层次的嵌套中断?

【问题讨论】:

  • 这似乎是the referred page。请注意,它是在谈论 exceptions 而不是中断。 中断是一个执行,然而,FIQ数据中止程序中止未定义的异常等都是独立的模式。您可以将这些模式的状态,特别是lrspsr,保存到系统堆栈,然后进入系统模式。此时,所有异常的所有代码都使用相同的堆栈。这很有价值,因为sp 不仅可以用作堆栈;即,进程上下文。

标签: kernel arm interrupt-handling


【解决方案1】:

尝试在 IRQ 模式下处理嵌套中断:

  • (USER) 您处于用户模式,您的 PC 寄存器会告诉您您在哪里。

  • (USER) 你得到一个中断。

  • (IRQ) 内核切换到中断模式,禁用中断(通过屏蔽 cpsr.i) 在 IRQ 模式下将 PC 从用户模式保存到 LR。

  • (IRQ) 此时您无法获得更多中断,因为中断是 已禁用。

  • (IRQ) 您处于 IRQ 模式并且确实启用了中断。

  • (IRQ) 你调用一个函数来处理相关的中断。函数调用 LR 包含后,返回地址到顶级 IRQ 处理程序。

  • (IRQ) 发生另一个中断,LR 被函数处理中断覆盖。此时你不能有一个稳定的状态,仅仅是因为你不能在 IRQ 模式下将 LR 用于你自己的目的,并且启用了中断来支持嵌套中断。您认为您可以将 LR 保存到堆栈中,但这可能会导致竞争条件,从而导致不定式循环。

通过系统模式处理嵌套中断:

  • (USER) 您处于用户模式,您的 PC 寄存器会告诉您您在哪里。

  • (USER) 你得到一个中断。

  • (IRQ) 内核切换到中断模式,禁用中断(通过屏蔽 cpsr.i) 在 IRQ 模式下将 PC 从用户模式保存到 LR。

  • (IRQ) 此时您无法获得更多中断,因为中断是 已禁用。

  • (IRQ) 您切换到系统模式,启用 IRQ。

  • (SYSTEM) 发生另一个中断,但一切正常,只是因为您没有与硬件竞争以保持 LR 正常。

Look below 查看哪些寄存器存储在哪些状态。

【讨论】:

  • 为什么 IRQ 代码不能将当前上下文保存到中断堆栈然后启用中断?我认为可能需要一个变量来跟踪 IRQ 嵌套,因此当嵌套级别返回零时,需要检查调度(用于此的另一个变量,如果 IRQ 处理程序调用解除阻塞的内核信号函数,则设置待处理任务)在需要时执行上下文切换到不同的用户任务。
  • @auselen 你能多解释一下这条线吗You think you may save LR to stack, but that would be open to a race condition which would lead to inifinitive loops. 我想知道会发生什么竞争条件?
  • @auselen - 是的,我记得的工作是在汇编中实现的,使用 R12 作为伪 LR,知道 R12 不会被嵌套中断破坏。我还记得一些迷你操作系统,其中“用户”代码在超级用户模式下运行,另一个也是如此,使用系统模式进行嵌套 IRQ,正如你提到的那样。
  • @Rahul 您处于启用中断的 IRQ 模式,您的 PC 可以说是 0xA4,您执行 BL 0xB4 进行呼叫,PC 变为 0xB4,LR 变为 0xA4。如果你想返回,你知道你可以使用 LR。然而,就在另一个中断发生的时候,LR 变为 0xB4,你失去了你在哪里(你不能及时保存 LR)。
【解决方案2】:

如果你想嵌套处理 IRQ,你必须处理非常底层的 asm,这是操作系统核心的一部分。

回到代码。我假设您对 ARM 核心寄存器有所了解。嵌套 IRQ 中最重要的事情是保存 ISR 将返回的状态。当 IRQ 发生时,CPU 会将旧的 CPSR 保存到 SPSR_irq 和旧的 PCLR_irq 并且 IRQ 将被禁用。因此,在进入真正的 ISR 之前,您必须将 {R0-R12}LR_irqSPSR_irq 推入堆栈。请注意,IRQ 现在被禁用,没有什么会打扰您(除非 FIQ,但 FIQ 使用其他不干扰 IRQ 寄存器的寄存器集)。之后,您就可以安全地跳转到真正的 ISR 并启用 IRQ。

当从 ISR 返回时,禁用 IRQ,并从堆栈中检索 SPSR,然后执行 LDM {R0-R12,PC}^ 将使您从中断发生的位置返回。

附:如果只针对 AAPCS,则只能在条目中保存 {R0-R3, R12},因为 C 函数不会破坏 {R4-R11}

【讨论】:

    猜你喜欢
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 2014-04-14
    • 2011-06-22
    • 2012-06-04
    相关资源
    最近更新 更多