Linux中斷處理體繫結構分析(一)

來源:互聯網
上載者:User
    異常,就是可以打斷CPU正常運行流程的一些事情,比如外部中斷、未定義指令、試圖修改唯讀資料、執行swi指令(Software Interrupt Instruction ,軟體中斷指令)等。當這些事情發生時,CPU暫停當前的程式,先處理例外狀況事件,然後再繼續執行被中斷的程式。作業系統中經常通過異常來完成一些特定的功能。其中的中斷也佔有很大的一部分。例如下面的這幾種情況:
  • 當CPU執行未定義的機器指令時將觸發“未定義指令異常”,作業系統可以利用這個特點使用一些自訂的機器指令,它們在異常處理函數中實現。
  • 當使用者程式試圖讀寫的資料或執行的指令不在記憶體中時,也會觸發一個“資料訪問中止異常”或“指令預取中止異常”,在異常處理函數中將這些資料或指令讀入記憶體,然後重新執行被中斷的程式,這樣可以節省記憶體,還使得作業系統可以運行這類程式,它們使用的記憶體遠大於實際的實體記憶體。

  在原先的核心版本中,核心在start_kernel函數(源碼在init/main.c中)中調用trap_init、init_IRQ兩個函數來設定異常和處理函數。在Linux2.6.32.2的核心版本中(也許在之前的版本就有變化),trap_init函數的內容發生了變化,在trap.c中,

void __init trap_init(void)
{
    return;
}

在這個檔案中還有一個函數,

void __init early_trap_init(void)
{
    unsigned long vectors = CONFIG_VECTORS_BASE;
    extern char __stubs_start[], __stubs_end[];
    extern char __vectors_start[], __vectors_end[];
    extern char __kuser_helper_start[], __kuser_helper_end[];
    int kuser_sz = __kuser_helper_end - __kuser_helper_start;

    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
    memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);

     memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
     sizeof(sigreturn_codes));
    memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
     sizeof(syscall_restart_code));

    flush_icache_range(vectors, vectors + PAGE_SIZE);
    modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}

   這個函數才是真正要用到的,在init/mian.c中可以找到,調用了trap_init(),而early_trap_init()函數在setup_arch(&command_line)函數中調用。在Linux/arch/arm/kernel/setup.c

698 void __init setup_arch(char **cmdline_p)
699 {
700 struct tag *tags = (struct tag *)&init_tags;
701 struct machine_desc *mdesc;
702 char *from = default_command_line;

...........
769 early_trap_init();
770 }

   這樣我們就明白了trap_init()函數的具體調用過程了。下面我們具體來看一下這個trap_init()函數,確切的說是earl_trap_init()函數。earl_tarp_init函數(代碼在arch/arm/kernel/traps.c中)被用來設定各種異常的處理向量,包括中斷向量。所謂“向量”,就是一些被安放在固定位置的代碼,當發生異常時,CPU會自動執行這些固定位置上的指令。ARM架構的CPU的異常向量基址可以是0x00000000,也可以是0xffff0000,Linux核心使用後者。earl_trap_init函數將異常向量複製到0xffff0000處,我們可以在該函數中看到下面的兩行代碼。

memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);

vectors等於0xffff0000。地址__vectors_start ~ __vectors_end之間的代碼就是異常向量,在arch/arm/kernel/entry-armv.S中定義,它們複製到地址0xffff0000處。異常向量的代碼很簡單,它們只是一些跳轉指令。發生異常時,CPU自動執行這些指令,跳轉去執行更複雜的代碼,比如儲存被中斷程式的執行環境,調用異常處理函數,恢複被中斷程式的執行環境並重新運行。這些“更複雜的代碼”在地址__stubs_start ~__stubs_end之間,它們在arch/arm/kernel/entry-armv.S中定義。將它們複製到地址0xffff0000+0x200處。 異常向量、異常向量跳去執行的代碼都是使用彙編寫的,它們在arch/arm/kernel/entry-armv.S中。異常向量的代碼如下,其中的“stubs_offset”用來重新置放跳轉的位置(向量被複製到地址0xffff0000處,跳轉的目的代碼被複製到地址0xffff0000+0x200處)。

.equ    stubs_offset, __vectors_start + 0x200 - __stubs_start

    .globl    __vectors_start
__vectors_start:
 ARM(    swi    SYS_ERROR0    ) //複位是,CPU將執行這條指令
 THUMB(    svc    #0        )
 THUMB(    nop            )
    W(b)    vector_und + stubs_offset//未定義異常時,CPU將執行這條指令
    W(ldr)    pc, .LCvswi + stubs_offset//swi異常
    W(b)    vector_pabt + stubs_offset//指令預取中止
    W(b)    vector_dabt + stubs_offset//資料訪問中止
    W(b)    vector_addrexcptn + stubs_offset//沒有用到
    W(b)    vector_irq + stubs_offset//irq異常
    W(b)    vector_fiq + stubs_offset// fiq 異常

    .globl    __vectors_end
__vectors_end:

    其中,vector_und、vector_pabt等表示要跳轉去執行的代碼。以vector_und為例,它仍在arch/arm/kernel/entry-armv.S中,通過vector_stub宏來定義,

vector_stub    und, UND_MODE

    .long    __und_usr      @ 0 (USR_26 / USR_32) 在使用者模式執行了未定
義指令
    .long    __und_invalid   @ 1 (FIQ_26 / FIQ_32)在FIQ模式執行了未定義指令
    .long    __und_invalid   @ 2 (IRQ_26 / IRQ_32)在IRQ模式下執行了未定義指令
    .long    __und_svc       @ 3 (SVC_26 / SVC_32)在管理員模式下執行了未定義指令
    .long    __und_invalid            @ 4
    .long    __und_invalid            @ 5
    .long    __und_invalid            @ 6
    .long    __und_invalid            @ 7
    .long    __und_invalid            @ 8
    .long    __und_invalid            @ 9
    .long    __und_invalid            @ a
    .long    __und_invalid            @ b
    .long    __und_invalid            @ c
    .long    __und_invalid            @ d
    .long    __und_invalid            @ e
    .long    __und_invalid            @ f

    vector_stub是一個宏,它根據後面的參數"und,UND_MODE"定義了以“vector_und”為標號的一段代碼。vector_stub宏的功能為:計算處理完異常後的返回地址、儲存一引起寄存器(比如r0、lr、spsr),然後進行管理員模式,最後根據被中斷的工作模式調用下面的某個跳轉分支。當發生異常時,CPU會根據異常的類型進入某個工作模式,但是很快vector_stub宏又會強制CPU進行管理員模式,在管理員模式下進行後續處理,這種方法簡化了程式的設計,使得異常發生前的工作模式根毛是使用者模式,要麼是管理員模式。
    代碼錶示在各個工作模式下執行未定義指令時,發生異常的處理分支。比如__und_usr表示在使用者模式下執行未定義指令時,所發生的未定義異常將由它來處理;__und_svc表示在管理員模式下執行未定義指令時,所發生的未定義異常將由它來處理。在其他工作模式下不可能發生未定義指令異常,否則使用“__und_invalid”來處理錯誤。ARM架構CPU中使用4位元據來表示工作模式,所以共有16個跳轉分支,目前只有7個工作模式。

     不同的跳轉分支只是在它們的入口下(比如儲存被中斷程式的寄存器)稍有差別,後續的處理大體相同,都在調用相應的C函數,比如未定義指令異常發生時,最終會調用C函數do_undefinstr來進行處理。各種異常C處理函數可以分為5類,它們分布在不同的檔案中
(1)在arch/arm/kernel/traps.c中
 未定義指令異常的C處理函數在這個檔案中定義,總入口函數為do_undefinstr
(2)在arch/arm/mm/fault.c中
 與記憶體訪問相關的異常C處理函數在這個檔案中定義,比如資料訪問中止異常、指令預取中止異常。總入口函數為do_DataAbort、do_prefetchAbort。
(3)在arch/arm/mm/irq.c中
 中斷處理函數的在這個檔案中定義,總入口函數為asm_do_IRQ,它調用其他檔案註冊的中斷處理函數
(4)在arch/arm/kernel/calls.S
在這個檔案中,swi異常的處理函數指標被組織成一個表格;swi指令機器碼的位[23:0]被用來作為索引。這樣,通過不同的swi index指令就可以調用不同的swi異常處理函數,它們被稱為系統調用,比如sys_open、sys_read等。
(5)沒有使用的異常
沒有使用FIQ異常
trap_init函數搭建了各類異常的處理架構。當發生異常時,各種C處理函數會被調用。這些C函數還要進一步細分異常發生的情況,分別調用更具體的處理函數。2.init_IRQ函數分析    中斷也是一種異常,之所以把它單獨的列出來,是因為中斷的處理與具體的開發板密切相關,除一些必須、共用的中斷(比如系統時鐘中斷、片內外設UART中斷)外,必須由驅動開發人員提供處理函數。核心提煉出中斷處理的共性,搭建一個非常容易擴充的中斷處理體系。
     init_IRQ函數(代碼在arch/arm/kernel/irq.c中)被用來初始化中斷和處理架構,設定各種中斷的預設處理函數。當發生中斷時,中斷總入口函數asm_do_IRQ就可以調用這些函數進行下一步處理。轉自:http://blogold.chinaunix.net/u3/104447/showart_2251010.html
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.