您的位置:首页 > 其它

ARMv8-中断处理接口

2017-05-16 16:22 393 查看
不考虑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 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内核 kernel