CPU如何在Linux中切换到中断堆栈

时间:2019-06-16 09:59:15

标签: c linux linux-kernel interrupt-handling

我已经阅读了有关Linux如何在每个内核的编译时间确定异常堆栈仅为4KB的情况下如何在每个CPU上使用硬IRQ堆栈和软IRQ堆栈的信息。

现在,我知道在8KB内核模式堆栈的情况下,当CPU在IDT中查找中断处理程序并发现需要更改特权时,他会从TSS获取内核模式堆栈的地址。过程的一部分。 同样在4KB内核模式堆栈的情况下,CPU从TSS段获取异常堆栈的地址。

我不清楚的是在处理中断的情况下CPU如何获取hard_irq堆栈或soft_irq堆栈的地址。

有人可以向我解释吗?

1 个答案:

答案 0 :(得分:0)

在将cpu寄存器保存到堆栈后立即调用的do_IRQ()函数中,检查当前中断处理程序执行的堆栈是否为硬IRQ堆栈。它是通过以下代码(摘自https://elixir.bootlin.com/linux/latest/source/arch/powerpc/kernel/irq.c#L659

void *cursp, *irqsp, *sirqsp;
cursp = (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1));
irqsp = hardirq_ctx[raw_smp_processor_id()];
sirqsp = softirq_ctx[raw_smp_processor_id()];

/* Already there ? */
if (unlikely(cursp == irqsp || cursp == sirqsp)) {
    __do_irq(regs);
    set_irq_regs(old_regs);
    return;
}

如果它尚未在硬IRQ堆栈中执行,那么它将不在异常堆栈中执行,因为这是TSS段包含的堆栈(能够切换到内核模式)。 在那种情况下,函数将明确切换到该堆栈。

注意:

如果在处理另一个中断的过程中发生了中断,则处理程序可能在硬IRQ堆栈中开始执行,因此对另一个堆栈没有任何更改,因为CPU已经在内核模式下执行了。