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