ARM 上的内核入口点

kernel entry points on ARM

我正在通读 ARM 内核源代码以加深理解并发现了一些有趣的东西。

arch/arm/kernel/entry-armv.S 中有一个名为 vector_stub 的宏,它生成一小块程序集,然后是针对各种 ARM 模式的跳转 table。例如,调用 vector_stub irq, IRQ_MODE, 4 会导致宏扩展为带有标签 vector_irq 的主体; vector_dabtvector_pabtvector_undvector_fiq.

也是如此

在每一个vector_*跳转table中,恰好有1个DWORD带有_usr后缀的标签地址

我想确认一下我的理解是否准确,请看下面。

  1. 这是否意味着具有 _usr 后缀的标签被执行,只有当内核线程在 CPU 上执行时在用户空间上下文中发生中断时才会执行?例如,如果内核线程在用户空间上下文中发生中断,则执行irq_usr,如果内核线程在用户空间上下文中发生中断,则执行dabt_usr,依此类推。
  2. 如果 [1] 为真,那么哪些内核线程负责处理,比如 irqs,具有不同的后缀,例如 irq_svc。我假设这是在 SVC 模式下发生的中断请求的处理程序。如果是这样,哪个内核线程处理这个?当前处于 SVC 模式的内核线程,以 CPU 为准收到中断?
  3. 如果 [2] 为真,那么内核线程在什么时候完成处理第二个中断,并且 return 回到它停止的地方(也是在 SVC 模式下)?是ret_from_intr吗?

Inside each of these vector_* jump tables, there is exactly 1 DWORD with the address of a label with a _usr suffix.

这是正确的。 table 由当前模式索引。例如,irq 只有三个条目; irq_usrirq_svcirq_invalid。在数据中止、FIQ 和其他模式期间应禁用 Irq。在这段简短的 'vector stub' 代码之后,Linux 将 总是 转移到 svc 模式。它是通过

完成的
@
@ Prepare for SVC32 mode.  IRQs remain disabled.
@
mrs r0, cpsr
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0

@@@ ... other unrelated code

movs    pc, lr          @ branch to handler in SVC mode

这就是 irq_invalid 用于所有其他模式的原因。执行此向量存根代码时不应发生异常。

Does this mean that labels with the _usr suffix are executed, only if the interrupt arises when the kernel thread executing on that CPU is in userspace context? For instance, irq_usr is executed if the interrupt occurs when the kernel thread is in userspace context, dabt_usr is executed if the interrupt occurs when the kernel thread is in userspace context, and so on.

是的,spsr是中断模式,table由这些模式位索引。

If 1 is true, then which kernel threads are responsible for handling, say irqs, with a different suffix such as irq_svc. I am assuming that this is the handler for an interrupt request that happens in SVC mode. If so, which kernel thread handles this? The kernel thread currently in SVC mode, on whichever CPU receives the interrupt?

我想你对这里有些误解。用户 space 进程有一个 'kernel thread'。 irq_usr 负责存储用户模式寄存器,因为可能会发生重新安排。 irq_svc 的上下文不同,因为正在使用内核堆栈,并且与 IRQ 代码将使用的相同。当用户任务调用 read() 时会发生什么?它使用系统调用,代码在内核上下文中执行。每个进程都有一个用户和 svc/kernel 堆栈(和线程信息)。内核线程是没有任何用户 space 堆栈的进程。

If is true, then at what point does the kernel thread finish processing the second interrupt, and return to where it had left off(also in SVC mode)? Is it ret_from_intr?

通常 Linux returns 到被中断的内核线程,以便它可以完成它的工作。但是,有一个用于抢占 svc threads/contexts 的配置选项。如果中断导致重新安排事件,则如果 CONFIG_PREEMPT 处于活动状态,则可能会导致 process/context 切换。有关此代码,请参阅 svc_preempt

另请参阅:

  • Linux kernel arm exception stack init