聊聊如何從復雜中斷簡單化
本文轉載自微信公眾號「人人都是極客」,作者布道師Peter。轉載本文請聯系人人都是極客公眾號。
中斷處理流程
arm64的異常向量表vectors中設置了各種異常的入口,目前有效的異常入口有兩個同步異常el0_sync,el1_sync和兩個異步異常el0_irq,el1_irq,其他異常入口暫時都invalid。中斷屬于異步異常,所以本文重點關注el0_irq和el1_irq。
通過上圖,我們可以看出中斷的處理分為三個部分,保護現場,中斷處理,恢復現場。其中el0_irq和el1_irq的具體實現略有不同,但處理流程大致是相同的。接下來我們以el0_irq為例對上面三個步驟進行梳理。
保護現場
將CPU寄存器按照pt_regs結構體的定義將第一現場保存到棧上。
- 保存PSTATE到SPSR_ELx寄存器;
- 將PSTATE中的D A I F全部屏蔽;
- 保存PC寄存器的值到ELR_ELx寄存器;
中斷處理
如上圖,大概主要有如下三個動作:
- 進入中斷棧;
- 執行中斷控制器的handle_arch_irq;
- 退出中斷棧;
在處理之前我們先看下什么叫做中斷棧。
中斷棧
中斷棧用來保存中斷的上下文。
中斷棧的創建:內核啟動時中會去為每個cpu創建一個per cpu的中斷棧:start_kernel->init_IRQ->init_irq_stacks
中斷棧的使用:中斷發生和退出的時候調用irq_stack_entry和irq_stack_exit來進入和退出中斷棧。
恢復現場
主要分三步:
- disable中斷;
- 檢查在退出中斷前有沒有需要處理事情,如調度、信號處理等。
- 將之前壓棧的pt_regs彈出,恢復現場。