ARM64 el1_irq 处理

 
 .align 6
el1_irq:
 kernel_entry 1
 msr daifclr, #1    //enable fiq
 enable_dbg_if_not_stepping x0
#ifdef CONFIG_TRACE_IRQFLAGS
 bl trace_hardirqs_off
#endif
#ifdef CONFIG_PREEMPT
 get_thread_info tsk
 ldr w24, [tsk, #TI_PREEMPT]  // get preempt count
 add w0, w24, #1   // increment it
 str w0, [tsk, #TI_PREEMPT]
#endif
 
 irq_handler
 
#ifdef CONFIG_PREEMPT
 str w24, [tsk, #TI_PREEMPT]  // restore preempt count
 cbnz w24, 1f    // preempt count != 0
 ldr x0, [tsk, #TI_FLAGS]  // get flags
 tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
 bl el1_preempt
1:
#endif
 
#ifdef CONFIG_TRACE_IRQFLAGS
 bl trace_hardirqs_on
#endif
 
 kernel_exit 1
ENDPROC(el1_irq)
 
  
 
  
/*
 * Interrupt handling.
 */
 .macro irq_handler
 ldr_l x1, handle_arch_irq
 mov x0, sp
 irq_stack_entry
 blr x1
 irq_stack_exit
 .endm 
 
相关栈处理:
 
  

 .macro irq_stack_entry  mov x19, sp   // preserve the original sp

 /*   * Compare sp with the current thread_info, if the top   * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and   * should switch to the irq stack.   */  and x25, x19, #~(THREAD_SIZE - 1)  cmp x25, tsk  b.ne 9998f

 this_cpu_ptr irq_stack, x25, 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

 
 
 /*
  * x19 should be preserved between irq_stack_entry and
  * irq_stack_exit.
  */
 .macro irq_stack_exit
 mov sp, x19
 .endm
 
 
初始化处理:
kernel/irq.c
 
  

void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) {  if (handle_arch_irq)   return;

 handle_arch_irq = handle_irq; }

需要注意的是,这里设置的handle_irq是主irq_chip下的处理函数,比如对于GIC来说,其设置是:gic_handle_irq。
 
 
  

static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) {  u32 irqstat, irqnr;  struct gic_chip_data *gic = &gic_data[0];  void __iomem *cpu_base = gic_data_cpu_base(gic);

 do {   irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);   irqnr = irqstat & GICC_IAR_INT_ID_MASK;//#define GICC_IAR_INT_ID_MASK  0x3ff

上面两个操作说明,中断号是中断处理程序去读状态寄存器后得到的。

  if (likely(irqnr > 15 && irqnr < 1020)) {    if (static_key_true(&supports_deactivate))     writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);    handle_domain_irq(gic->domain, irqnr, regs);    continue;   }

  if (irqnr < 16) {    writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);    if (static_key_true(&supports_deactivate))     writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE); #ifdef CONFIG_SMP    /*     * Ensure any shared data written by the CPU sending     * the IPI is read after we've read the ACK register     * on the GIC.     *     * Pairs with the write barrier in gic_raise_softirq     */    smp_rmb();    handle_IPI(irqnr, regs); #endif    continue;   }   break;  } while (1);

}

 
 

你可能感兴趣的:(ARM64,体系架构)