ARMv8-中斷處理接口

不考慮EL2和EL3,IRQ處理分兩種情況:用戶態發生的中斷和內核態發生的中斷,相應的中斷處理接口分別爲:

el1_irq
el0_irq

以內核態el1發生的irq爲例:

358     .align  6
359 el1_irq:
360     kernel_entry 1 //壓棧,保存上下文;
361     enable_dbg
362 #ifdef CONFIG_TRACE_IRQFLAGS
363     bl  trace_hardirqs_off
364 #endif
365    
366     irq_handler /*調用中斷處理默認函數*/
367    
368 #ifdef CONFIG_PREEMPT
369     get_thread_info tsk
370     ldr w24, [tsk, #TI_PREEMPT]     // get preempt count
371     cbnz    w24, 1f             // preempt count != 0          
372     ldr x0, [tsk, #TI_FLAGS]        // get flags 
373     tbz x0, #TIF_NEED_RESCHED, 1f   // needs rescheduling?
374     bl  el1_preempt
375 1: 
376 #endif
377 #ifdef CONFIG_TRACE_IRQFLAGS
378     bl  trace_hardirqs_on
379 #endif
380     kernel_exit 1
381 ENDPROC(el1_irq)

irq_handler也是一個僞指令宏操作:

187 /* 
188  * Interrupt handling.    
189  */
190     .macro  irq_handler   
191     adrp    x1, handle_arch_irq  //把handle_arch_irq地址放到x1, handle_arch_irq是一個指針;
192     ldr x1, [x1, #:lo12:handle_arch_irq]//取出指針所指向的值;
193     mov x0, sp            
194     blr x1  //跳轉到handle_arch_irq              
195     .endm

handle_arch_irq 在arch/arm64/kernel/irq.c設置:

 45 void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
 46 {
 47     if (handle_arch_irq)
 48         return;
 49 
 50     handle_arch_irq = handle_irq;  
 51 }

根據不同的中斷控制器會設置不同的處理接口,通過在驅動控制器設置,代碼在drivers/irqchip/,以irq-gic.c(通用中斷控制器)爲例,設置set_handle_irq(gic_handle_irq):

 437 static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 438 { 
 439     u32 irqstat, irqnr;
 440     struct gic_chip_data *gic = &gic_data[0];
 441     void __iomem *cpu_base = gic_data_cpu_base(gic);
 442   
 443     do {
 444         irqstat = readl_relaxed_no_log(cpu_base + GIC_CPU_INTACK);
 445         irqnr = irqstat & GICC_IAR_INT_ID_MASK;
 446   
 447         if (likely(irqnr > 15 && irqnr < 1021)) {
 448             uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
 449             handle_domain_irq(gic->domain, irqnr, regs);//根據中斷號調用相應的中斷處理函數;
 450             continue;
 451         }
 452         if (irqnr < 16) {
 453             writel_relaxed_no_log(irqstat, cpu_base + GIC_CPU_EOI);
 454             uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
 455 #ifdef CONFIG_SMP        
 456             handle_IPI(irqnr, regs);       
 457 #endif
 458             continue;
 459         }
 460         break;           
 461     } while (1);         
 462 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章