亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Linux服務器 > 正文

淺析Arm Linux中斷Vector向量表建立流程

2024-09-05 23:01:53
字體:
來源:轉載
供稿:網友

Linux混入了mmu內存管理之后,ARM的中斷是怎么樣的呢?和我們在裸板上的中斷有沒有區別?讓我們從源代碼入手,做一個粗略的分析:

init/main.c->start_kernel()->trap_init()
//-----------------------------------------------
1.trap_init()
//gliethttp函數位于arch/arm/kernel/traps.c
void __init trap_init(void)
{
    extern void __trap_init(unsigned long);
    unsigned long base = vectors_base(); //返回中斷base基址0xffff0000
    __trap_init(base);                   //以base為vector基址,初始化中斷向量表
    if (base != 0)
        printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx/n",
            base);
#ifdef CONFIG_CPU_32
    modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
#endif
}
//--------------------------------------
2.vectors_base()
//gliethttp include/arch/asm-arm/proc-armv/system.h
extern unsigned long cr_alignment;
#if __LINUX_ARM_ARCH__ >= 4                //at91rm9200是ARMV4結構
#define vectors_base()    ((cr_alignment & CR_V) ? 0xffff0000 : 0)
#else
#define vectors_base()    (0)
                  #endif

  可以看到ARMv4以下的版本,該地址固定為0;ARMv4及以上版本,ARM中斷向量表的地址由CP15協處理器c1寄存器中V位(bit[13])控制,V和中斷向量表的對應關系如下:

V=0    ~    0x00000000~0x0000001C
V=1    ~    0xffff0000~0xffff001C
//------------------------------------------
2.1 cr_alignment
//gliethttp arch/arm/kernel/entry-armv.S
ENTRY(stext)
        mov    r12, r0
        mov    r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode
        msr    cpsr_c, r0                @ and all irqs disabled
//__lookup_processor_type 查詢處理器類型,[gliethttp 以后補上<淺析head-armv.S>]返回值
//2007-07-04
//r9 = processor ID                    //讀取cp15的c0寄存器
//r10 = pointer to processor structure //下面會add pc, r10, #12,跳轉到__arm920_setup
//gliethttp 在vmlinux-armv.lds.in中
//__proc_info_begin = .;
//             *(.proc.info)
// __proc_info_end = .;
//見2.2
        bl    __lookup_processor_type
        teq    r10, #0                   @ invalid processor?
        moveq    r0, #'p'                @ yes, error 'p'
        beq    __error
        bl    __lookup_architecture_type
        teq    r7, #0                    @ invalid architecture?
        moveq    r0, #'a'                @ yes, error 'a'
        beq    __error
//__create_page_tables 創建arm啟動臨時使用的前4M頁表
        bl    __create_page_tables
        adr    lr, __ret                 @ return address
        add    pc, r10, #12              @ initialise processor
        .type    __switch_data, %object
__switch_data:    .long    __mmap_switched
        .long    SYMBOL_NAME(__bss_start)
        .long    SYMBOL_NAME(_end)
        .long    SYMBOL_NAME(processor_id)
        .long    SYMBOL_NAME(__machine_arch_type)
        .long    SYMBOL_NAME(cr_alignment)
        .long    SYMBOL_NAME(init_task_union)+8192
/*
 * Enable the MMU. This completely changes the structure of the visible
 * memory space. You will not be able to trace execution through this.
 * If you have an enquiry about this, *please* check the linux-arm-kernel
 * mailing list archives BEFORE sending another post to the list.
 */
        .type    __ret, %function
__ret:        ldr    lr, __switch_data
        mcr    p15, 0, r0, c1, c0
//將__arm920_setup中設置的r0值,置入cp15協處理器c1寄存器中
        mrc    p15, 0, r0, c1, c0, 0     @ read it back.
        mov    r0, r0
//填充armv4中的三級流水線:mov r0,
r0 對應一個nop,所以對應2個nop和一個mov pc,lr剛好三個"無用"操作
        mov    r0, r0
        mov    pc, lr
//跳轉到__mmap_switched函數 gliethtttp
/*
 * The following fragment of code is executed with the MMU on, and uses
 * absolute addresses; this is not position independent.
 *
 * r0 = processor control register
 * r1 = machine ID
 * r9 = processor ID
 */
        .align    5
__mmap_switched:
        adr    r3, __switch_data + 4
        ldmia    r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
//2007-07-04 gliethttp
//r4    ~    __bss_start
//r5    ~    _end
//r6    ~    processor_id
//r7    ~    __machine_arch_type
//r8    ~    cr_alignment
//sp    ~    (init_task_union)+8192
//以下幾步操作對processor_id,__machine_arch_type,cr_alignment賦值gliethttp
        mov    fp, #0                                @ Clear BSS (and zero fp)
1:      cmp    r4, r5                                //bss區清0
        strcc    fp, [r4],#4
        bcc    1b
        str    r9, [r6]                              @ Save processor ID
        str    r1, [r7]                              @ Save machine type
#ifdef CONFIG_ALIGNMENT_TRAP
        orr    r0, r0, #2                            @ ...........A.
#endif
        bic    r2, r0, #2                            @ Clear 'A' bit
//r2存放 禁用TRAP隊列故障 后的r0值
//r8->cr_alignment,cr_no_alignment
//所以stmia    r8, {r0, r2}后,cr_alignment = r0,cr_no_alignment = r2
        stmia    r8, {r0, r2}           @ Save control register values
        b    SYMBOL_NAME(start_kernel)        //進入內核C程序
//--------------------------------------
2.2 __arm920_proc_info
//gliethttp arch/arm/mm/proc-arm920.S
.section ".proc.info", #alloc, #execinstr
    .type    __arm920_proc_info,#object
__arm920_proc_info:
//該地址存儲到r10中
    .long    0x41009200
    .long    0xff00fff0
    .long    0x00000c1e 
          @ mmuflags
    b    __arm920_setup
//add pc, r10, #12 gliethttp將使cpu執行b __arm920_setup跳轉指令
    .long    cpu_arch_name
    .long    cpu_elf_name
    .long    HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
    .long    cpu_arm920_info
    .long    arm920_processor_functions
    .size    __arm920_proc_info, . - __arm920_proc_info
//----------------------------------------
2.3 __arm920_setup
    .section ".text.init", #alloc, #execinstr
__arm920_setup:
    mov    r0, #0
    mcr    p15, 0, r0, c7, c7        @ invalidate I,D caches on v4
    mcr    p15, 0, r0, c7, c10, 4    @ drain write buffer on v4
    mcr    p15, 0, r0, c8, c7        @ invalidate I,D TLBs on v4
    mcr    p15, 0, r4, c2, c0        @ load page table pointer
    mov    r0, #0x1f                 @ Domains 0, 1 = client
    mcr    p15, 0, r0, c3, c0        @ load domain access register
    mrc    p15, 0, r0, c1, c0        @ get control register v4
/*
 * Clear out 'unwanted' bits (then put them in if we need them)
 */
//gliethttp r0單元存放了cp15協處理器c1寄存器的值,如下代碼對該值進行加工
                                          @ VI ZFRS BLDP WCAM
    bic    r0, r0, #0x0e00                           //清0 bit[9..11]
    bic    r0, r0, #0x0002                           //清0 bit[1]
    bic    r0, r0, #0x000c
    bic    r0, r0, #0x1000                @ ...0 000. .... 000.
/*
 * Turn on what we want
 */
    orr    r0, r0, #0x0031                           //bit0=1 使能mmu
    orr    r0, r0, #0x2100                @ ..1. ...1 ..11 ...1//bit13=1 中斷向量表基址為0xFFFF0000
#ifndef CONFIG_CPU_DCACHE_DISABLE
    orr    r0, r0, #0x0004                @ .... .... .... .1..
#endif
#ifndef CONFIG_CPU_ICACHE_DISABLE
    orr    r0, r0, #0x1000                @ ...1 .... .... ....
#endif
                      mov    pc, lr

 

小結:通過以上的源碼分析,我們可以清楚的看到vectors_base()返回的中斷向量基址值為0xFFFF0000,接下來我們繼續分析下面的源碼:


3.__trap_ini()
//gliethttp函數位于arch/arm/kernel/entry-armv.S
        .align    5
__stubs_start:
/*
 * Interrupt dispatcher
 * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
 */
vector_IRQ:    @
        @ save mode specific registers
        @
        ldr    r13, .LCsirq
        sub    lr, lr, #4
        str    lr, [r13]            @ save lr_IRQ
        mrs    lr, spsr
        str    lr, [r13, #4]        @ save spsr_IRQ
...略...
vector_addrexcptn:
        b    vector_addrexcptn
/*
 * We group all the following data together to optimise
 * for CPUs with separate I & D caches.
 */
        .align    5
.LCvswi:    .word    vector_swi
.LCsirq:    .word    __temp_irq
.LCsund:    .word    __temp_und
.LCsabt:    .word    __temp_abt
__stubs_end:
        .equ    __real_stubs_start, .LCvectors + 0x200
.LCvectors:    swi    SYS_ERROR0
        b    __real_stubs_start + (vector_undefinstr - __stubs_start)
        ldr    pc, __real_stubs_start + (.LCvswi - __stubs_start)
        b    __real_stubs_start + (vector_prefetch - __stubs_start)
        b    __real_stubs_start + (vector_data - __stubs_start)
        b    __real_stubs_start + (vector_addrexcptn - __stubs_start)
        b    __real_stubs_start + (vector_IRQ - __stubs_start)
        b    __real_stubs_start + (vector_FIQ - __stubs_start)
ENTRY(__trap_init)
        stmfd     {r4 - r6, lr}
        adr    r1, .LCvectors    @ set up the vectors
//通過adr指令獲得與pc地址為偏移地址數據,最后r1=pc-0x2c
        ldmia    r1, {r1, r2, r3, r4, r5, r6, ip, lr}
//將中斷向量表跳轉數據分別轉存到r1,r2,r3,r4,r5,r6,ip,lr寄存器
        stmia    r0, {r1, r2, r3, r4, r5, r6, ip, lr}
//根據編譯器規則r0存放了函數__trap_init(base)傳入的參數值base,其值為
//0xFFFF0000
//將r1,r2,r3,r4,r5,r6,ip,lr數據順序轉儲到以虛擬地址0xFFFF0000為起始地址的空間
        add    r2, r0, #0x200
//r2=0xFFFF0000+0x200=0xFFFF2000
        adr    r0, __stubs_start@ copy stubs to 0x200
//r0=pc相對地址=pc-0x26c
        adr    r1, __stubs_end
//r1=pc相對地址=pc-0x40
1:      ldr    r3, [r0], #4
        str    r3, [r2], #4
//將__stubs_start
和__stubs_end之間的中斷處理代碼拷貝到以虛擬地址0xFFFF2000為起始地址的順序空間
        cmp    r0, r1
        blt    1b
                          LOADREGS(fd, {r4 - r6, pc})


  這樣我們來看看空間分布圖:

虛擬地址     異常              處理代碼
0xffff0000   reset             swi SYS_ERROR0
0xffff0004   undefined  b __real_stubs_start + (vector_undefinstr - __stubs_start)
0xffff0008   軟件中斷     ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)
0xffff000c   取指令異常   b __real_stubs_start + (vector_prefetch - __stubs_start)
0xffff0010   數據異常     b __real_stubs_start + (vector_data - __stubs_start)
0xffff0014   reserved   b __real_stubs_start + (vector_addrexcptn - __stubs_start)
0xffff0018   irq        b __real_stubs_start + (vector_IRQ - __stubs_start)
0xffff001c   fiq        b __real_stubs_start + (vector_FIQ - __stubs_start)
       ...
0xffff2000   __stubs_start:    ldr    r13, .LCsirq
0xffff2004                     sub    lr, lr, #4
0xffff2008                     str    lr, [r13] @ save lr_IRQ
       ...
0xffff21a4                  &nb
sp;  .LCsirq:    .word    __temp_irq
0xffff21a8                     .LCsund:    .word    __temp_und
                  0xffff21ac                     .LCsabt:    .word    __temp_abt

 


  如果你現在有這樣一種疑惑?程序為什么編譯地址是0xc0008000,將其直接拷貝到0xffff0000和0xffff2000為什么還能順利執行,請參考我的另一篇blog《arm相對跳轉到底是怎么回事》,主要原因是b指令是相對跳轉指令,adr也是基于pc的前后偏移指令,當然對于ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)是絕對地址賦值,所以最后pc會跳轉到0xc000xxxx空間執行代碼,其他的跳轉如:b __real_stubs_start + (vector_IRQ - __stubs_start)都會到0xffff2xxxx相應的vector_IRQ處執行向量中斷處理函數,還有一個要分析的問題是:.equ __real_stubs_start,

  .LCvectors + 0x200,語句b __real_stubs_start

  + (vector_undefinstr - __stubs_start)就是跳轉到LCvectors+0x200空間執行。舉一個例子:

org 0x8000
        reset    b    InitRest
        ...
        InitRest:
        ...
        那么reset標號的地址為0x8000,他的意思是在0x8000處向前跳轉到InitRest,        我們也可以這樣來構造跳轉:
        org 0x8000
        reset b (0x8000+(.InitRest - .reset))
        ...
        InitRest:
        ...
                          以上的構造語句同樣實現了相對0x8000地址的跳轉

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91情侣偷在线精品国产| 久久91亚洲精品中文字幕| 欧美电影免费观看高清完整| 精品久久久精品| 国产成人亚洲综合| 久久久中精品2020中文| 奇米4444一区二区三区| 国产精品视频导航| 日韩中文字幕第一页| 日韩免费不卡av| 欧美电影免费观看网站| 国产精品美乳在线观看| 欧美xxxwww| 日本精品性网站在线观看| 欧美日韩国产成人高清视频| 91久久久亚洲精品| 成人xxxx视频| 国产亚洲精品一区二555| 韩国欧美亚洲国产| 亚洲另类激情图| 国产精品自在线| 欧美中文在线观看| 久久成人精品电影| 68精品久久久久久欧美| 日韩影视在线观看| 亚洲欧美日本伦理| 欧美中在线观看| 欧美日本亚洲视频| 国产精品久久久久久久久免费看| 91极品视频在线| 久久久久久久久久国产精品| 国产精品免费一区二区三区都可以| 91精品免费久久久久久久久| 国产综合在线看| 最近2019年手机中文字幕| 亚洲欧美日本伦理| 奇门遁甲1982国语版免费观看高清| 久久91精品国产91久久跳| 亚洲日韩中文字幕在线播放| 日韩在线中文字幕| 久久深夜福利免费观看| 久久成人免费视频| 91精品综合久久久久久五月天| 国内偷自视频区视频综合| 欧美国产激情18| 日韩av免费一区| 欧美视频中文字幕在线| 久久久免费观看| 国产一区二区三区丝袜| 欧美一区二区三区……| 国产精品你懂得| 狠狠躁夜夜躁人人躁婷婷91| 日韩视频免费观看| 国产精品入口夜色视频大尺度| 国产日产欧美精品| 国产精品成人av性教育| 欧美成人激情图片网| 日韩亚洲欧美中文高清在线| 日韩国产精品亚洲а∨天堂免| 国内伊人久久久久久网站视频| 成人网欧美在线视频| 青青草成人在线| 亚洲精品理论电影| 欧美日韩成人在线视频| 在线日韩中文字幕| 最近日韩中文字幕中文| 久久久久日韩精品久久久男男| 欧美另类69精品久久久久9999| 亚洲影院色在线观看免费| 亚洲激情第一页| 色多多国产成人永久免费网站| 精品久久久久久久久国产字幕| 亚洲黄页网在线观看| 亚洲成色777777在线观看影院| 久久久久久91香蕉国产| 国产91精品久久久久久| 国产手机视频精品| 亚洲视频国产视频| 久久成人综合视频| 亚洲欧美精品在线| 国产精品综合久久久| 精品亚洲永久免费精品| 成人午夜激情网| 操人视频在线观看欧美| 亚洲网站在线看| 久久999免费视频| 欧美老女人www| 国产精品爱久久久久久久| 欧美一级免费看| 亚洲人成电影在线观看天堂色| 亚洲成人免费在线视频| 亚洲国产精品专区久久| 国产精品普通话| 欧美日韩亚洲系列| 久久综合久中文字幕青草| 色播久久人人爽人人爽人人片视av| 中文字幕国内精品| 午夜精品久久久久久久男人的天堂| 亚洲欧洲日产国产网站| 亚洲人午夜色婷婷| 日日摸夜夜添一区| 国产精品久久久久久久久免费看| 久久久欧美精品| 国产一区二区日韩精品欧美精品| 欧美尤物巨大精品爽| 亚洲色图校园春色| 伊人激情综合网| 日韩中文字幕免费视频| 欧美成人性色生活仑片| 成人a在线观看| 98精品国产高清在线xxxx天堂| 国产精品久久99久久| 日韩精品在线观看视频| 亚洲精品ady| 国产精品日韩欧美综合| 亚洲欧美精品中文字幕在线| 日韩在线视频免费观看高清中文| 欧美在线国产精品| 欧美在线观看网址综合| 在线午夜精品自拍| 久久久精品2019中文字幕神马| 国产精品专区第二| 精品国产老师黑色丝袜高跟鞋| 成人美女av在线直播| 欧美激情亚洲一区| 另类美女黄大片| 精品日韩中文字幕| 欧美精品福利视频| 国产精品一区二区女厕厕| 欧美精品九九久久| 久久精品国产久精国产一老狼| 日韩欧亚中文在线| 久久人人爽亚洲精品天堂| 久久久免费精品视频| 亚洲欧美中文日韩在线| 亚洲成年网站在线观看| 亚洲电影免费观看高清完整版在线| 国产91久久婷婷一区二区| 亚洲国产欧美一区二区三区久久| 在线视频中文亚洲| 黄网动漫久久久| 亚洲综合一区二区不卡| 日本精品中文字幕| 日韩av一区二区在线观看| 亚洲女人初尝黑人巨大| 精品色蜜蜜精品视频在线观看| 国精产品一区一区三区有限在线| 欧美激情精品久久久久久变态| 亚洲一区亚洲二区| 欧美日韩视频免费播放| 久久久久久久久久av| 成人国产在线激情| 久久久久久久久中文字幕| 欧美一级淫片播放口| 久久久久国产精品免费| 色偷偷噜噜噜亚洲男人的天堂| 成人福利视频在线观看| 国产精品av免费在线观看| 久久露脸国产精品| 欧美孕妇孕交黑巨大网站| 亚洲人成电影网站色www| 中文日韩在线视频| 久久五月情影视| 欧洲成人免费aa|