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