收藏本站 收藏本站
积木网首页 - 软件测试 - 常用手册 - 站长工具 - 技术社区
积木学院 > 黑客技术 > 黑客编程 > 正文

windowsCE异常和中断服务程序初探(=)

来源:互联摘选 日期:2008-07-23 16:44

文摘出处:http://www.cnblogs.com/nasiry/archive/2005/01/06/87381.html

Nasiry

继续上次的内容,在上次的分析中我们已经对SWI,FIQ,IRQ的流程有了一个大概的认识,下面继续对DataAbort和PrefetchAbort以及公共分发程序CommonHandler进行一下认识,完整异常处理的流程。

2-4 DataAbort服务程序    
   由数据异常触发,通常有三种指令引发数据异常,这些指令都是访存操作,而且都是由MMU的引入后才可能会发生的情况。1.LDR/STR指令.2.SWAP指令。3.LDM/STM指令。而MMU的失效类型又分为4种:存储访问失效、地址对齐失效、地址变换失效、域控制器失效、访问控制权限失效.因此当异常发生后,需要通过访问CP15来获知异常的产生具体原因和情况。mfc是微软的asmarm宏汇编器专用的宏指令,相当于mcr指令。数据异常和中断模式一样都有可能在互锁时发生,所以同样需要对执行互锁的情形进行处理。正常的情况下在保存完相关的寄存器后就会读取CP15的c6,c5,c13三个寄存器。这三个寄存器分别是失效地址寄存器(FAR)、失效状态寄存器(FSR)、进程号寄存器(这个翻译得不好PCP15)然后根据具体的失效类型来进行处理。在ARM处理器中对于CP15有三种地址类型,VA,PA,MVA。VA(virtual address)也就是我们通常说的虚拟地址或逻辑地址也就是通过CP15按照PT转换后的地址,而PA(physical Address)则是对应于AMBA上的地址,对应的是电气介质也就是物理地址。而MVA(Modified virtual address)则是对应于Cache和TLB中转换地址。

        NESTED_ENTRY    DataAbortHandler
        sub     lr, lr, #8                      ; repair continuation address
        stmfd   sp!, {r0-r3, r12, lr}
        PROLOG_END

        sub     r0, lr, #INTERLOCKED_START
        cmp     r0, #INTERLOCKED_END-INTERLOCKED_START
        bllo    CheckInterlockedRestart
        mfc15   r0, c6                          ; (r0) = FAR       
        mfc15   r1, c5                          ; (r1) = FSR
        mfc15   r2, c13                         ; (r2) = process base address
       
        ;  FAR=Fault address register
    ;  CP = 15: CRn = 6, CRm = 0, op_1 = 0, op_2 = 0
        ;  FSR=Fault status register
        ;  CP = 15: CRn = 5, CRm = 0, op_1 = 0, op_2 = 0
        ;  PCP15: PID  Process ID register
    ;  CP = 15: CRn = 13, CRm = 0, op_1 = 0, op_2 = 0
       
        tst     r0, #0xFE000000                 ; slot 0 reference?
        orreq   r0, r0, r2                      ; (r0) = process slot based address
        and     r1, r1, #0x0D                   ; type of data abort
        cmp     r1, #0x05                       ; translation error?
        movne   r0, #0
        CALLEQ  LoadPageTable                   ; (r0) = !0 if entry loaded
        tst     r0, r0
        ldmnefd sp!, {r0-r3, r12, pc}^          ; restore regs & continue
        ;*********************************************************************
        ldr     lr, =KData-4
        ldmfd   sp!, {r0-r3, r12}
        stmdb   lr, {r0-r3}
        ldmfd   sp!, {r0}
        str     r0, [lr]                        ; save resume address
        mov     r1, #ID_DATA_ABORT              ; (r1) = exception ID
        b       CommonHandler

        ENTRY_END DataAbortHandler

在DataAbort发生后c6中的数据保存的就是导致异常的MVA地址,通过windowsCE memory layout可以了解到,当前进程的运行空间是在slot0,也就是0x0-0x1fffffff的位置,事实上这个slot上的数据仅仅是实际进程的一个副本所以如果数据异常发生在slot0就需要去找到进程所在的实际slot的存放地址,然后尝试将内核的页表复制到硬件实际使用的页表以达到恢复的目的。如果复制动作成功则返回,否则进入异常分发程序CommonHandler。
2-5 PrefetchAbort服务程序
   对于ARM处理器来说,由于其内部使用了哈佛结构---独立的数据的指令总线因此,在数据/指令的读取过程中产生的异常也就很自然地可以区分开来,本质上而言,这些异常都是同属于存储访问失败产生的异常,因此这些异常都由MMU相关,在ARM手册中DataAbort和PrefetchAbort都称为Memory abort。Prefetch也就是在预取指令的动作后产生的,当处理器运行到这个无效的指令时(这个无效与undefined exception中的不可识别不同,是指不存在或是无法得到)就触发该异常。所以不是所有的指令无效都产生异常,例如:一个分支程序指向一个不可访问的区域,而之前的分支指向另一个可访问区域时。后一个区域尽管预取无效但是由于该分支并不执行所以并不产生异常。所以prefetch的准确定义应该是prefetch and executes Abort:).在ARMV5指令集中BKPT也可以产生预取无效但由于这儿的ARM通常都是ARM9的,也就是使用ARMV4指令所以不讨论BKPT的情形。由于数据异常和指令异常同属存储异常而且两个异常不可能会相互中断所以在ARM的设计上这两个异常使用同一组寄存器abort组。

  ALTERNATE_ENTRY PrefetchAbort

        sub     lr, lr, #0xF0000004  ;考察产生异常的地址是否在0xf0000000-0xf0010400  
        cmp     lr, #0x00010400    ;之间,如果是进入系统调用处理
        bhs     ProcessPrefAbort      ;->>正常的预取异常 执行ProcessPrefAbort
    ...      
ProcessPrefAbort
        add     lr, lr, #0xF0000000             ; repair continuation address
        stmfd   sp!, {r0-r3, r12, lr}
 
        mov     r0, lr                          ; (r0) = faulting address
        mfc15   r2, c13                         ; (r2) = process base address
        tst     r0, #0xFE000000                 ; slot 0 reference?
        orreq   r0, r0, r2                      ; (r0) = process slot based address
        CALL    LoadPageTable                   ; (r0) = !0 if entry loaded
        tst     r0, r0
        ldmnefd sp!, {r0-r3, r12, pc}^          ; restore regs & continue
        ldmfd   sp!, {r0-r3, r12}
        ldr     lr, =KData-4
        stmdb   lr, {r0-r3}
        ldmfd   sp!, {r0}
        str     r0, [lr]                        ; save resume address
        mov     r1, #ID_PREFETCH_ABORT          ; (r1) = exception ID
        b       CommonHandler

下面来结合windowsCE的情形。PrefetchAbort就是该服务程序的入口,在程序的一开始将lr,也就是产生异常的地址+4(流水线导致)的地址减掉0xf000 0004并比较是否在0-0x10400之间,这是为什么呢?原来windowsCE除了使用PrefetchAbort服务程序作为正常的异常处理以外还使用这个异常作为系统调用的手段。通过0xf0000000-0xf0010400这段地址的预取异常来进行系统调用。我们下面看处理预取失败的情况,绕开系统调用的先不管。也就是ProcessPrefAbort的分支。 这个分支的内容就与上面DataAbort的内容一样了,我就不再重复了。

推荐阅读

 

热点信息

 
强悍的草根IT技术社区,这里应该有您想要的! 友情链接:b2b电子商务
Copyright © 2010 Gimoo.Net. All Rights Rreserved  京ICP备05050695号