每个cpu都有一个16K的中断栈

在kernel/entry.S中定义irq的entry,这里以el1_irq为例

ENTRY(vectors)
     ventry  el1_sync_invalid        // Synchronous EL1t
     ventry  el1_irq_invalid         // IRQ EL1t
     ventry  el1_fiq_invalid         // FIQ EL1t
     ventry  el1_error_invalid       // Error EL1t
 
     ventry  el1_sync            // Synchronous EL1h
     ventry  el1_irq             // IRQ EL1h

在el1_irq 中会调用irq_handler
 el1_irq:
     kernel_entry 1
     enable_dbg
 #ifdef CONFIG_TRACE_IRQFLAGS
     bl  trace_hardirqs_off
 #endif
 
     irq_handler

irq_handler 源码如下: 其中会调用irq_stack_entry

  .macro  irq_handler
     ldr_l   x1, handle_arch_irq
     mov x0, sp
     irq_stack_entry
     blr x1
     irq_stack_exit

irq_stack_entry源码如下,这个函数就是我们重点要说的。这个函数会将当前的stack从task stack 切换到irq stack
 .macro  irq_stack_entry
     mov x19, sp         // preserve the original sp
 
     /*
      * Compare sp with the base of the task stack.
      * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
      * and should switch to the irq stack.
      */
     ldr x25, [tsk, TSK_STACK]
     eor x25, x25, x19
     and x25, x25, #~(THREAD_SIZE - 1)
     cbnz    x25, 9998f
 
     adr_this_cpu x25, irq_stack, x26
     mov x26, #IRQ_STACK_START_SP
     add x26, x25, x26
 
     /* switch to the irq stack */
     mov sp, x26
 
     /*
      * Add a dummy stack frame, this non-standard format is fixed up
      * by unwind_frame()
      */
     stp     x29, x19, [sp, #-16]!
     mov x29, sp
 
 9998:
     .endm

目前kernel中每个cpu 都有一个16k的中断栈
irq的定义在arch/arm64/include/asm/irq.h中
DECLARE_PER_CPU(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);

/*
 * The highest address on the stack, and the first to be used. Used to
 * find the dummy-stack frame put down by el?_irq() in entry.S, which
 * is structured as follows:
 *
 *       ------------
 *       |          |  <- irq_stack_ptr
 *   top ------------
 *       |   x19    | <- irq_stack_ptr - 0x08
 *       ------------
 *       |   x29    | <- irq_stack_ptr - 0x10
 *       ------------
 *
 * where x19 holds a copy of the task stack pointer where the struct pt_regs
 * from kernel_entry can be found.
从DECLARE_PER_CPU 可以知道,每个cpu都有一个16k的中断栈
可以通过#define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP)
来得到每个cpu的中断栈
static inline bool on_irq_stack(unsigned long sp, int cpu)
{
	/* variable names the same as kernel/stacktrace.c */
	unsigned long low = (unsigned long)per_cpu(irq_stack, cpu);
	unsigned long high = low + IRQ_STACK_START_SP;

	return (low <= sp && sp <= high);
}
通过on_irq_stack 很容易判断当前是否在中断栈上.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值