Linux异常体系之stubs_offset(__vectors_start + 0x200 - __stubs_star)

来源:互联网 发布:寂寞的季节 知乎 编辑:程序博客网 时间:2024/05/01 14:07

在ARM V4及V4T以后的大部分处理器中,中断向量表的位置可以有两个位置:一个是0x00000000,另一个是0xffff0000。可以通过CP15协处理器c1寄存器中V位(bit[13])控制。V和中断向量表的对应关系如下:

        V=0        ~        0x00000000~0x0000001C

        V=1        ~        0xffff0000~0xffff001C

在arch/arm/mm/proc-arm920.S中:

    .type   __arm920_setup, #function__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#ifdef CONFIG_MMU    mcr p15, 0, r0, c8, c7      @ invalidate I,D TLBs on v4#endif    adr r5, arm920_crval    ldmia   r5, {r5, r6}    mrc p15, 0, r0, c1, c0      @ get control register v4    bic r0, r0, r5    orr r0, r0, r6    mov pc, lr    .size   __arm920_setup, . - __arm920_setup       /*    ┊*  R    ┊* .RVI ZFRS BLDP WCAM    ┊* ..11 0001 ..11 0101    ┊*     ┊*/    .type   arm920_crval, #objectarm920_crval:    crval   clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130

V(bit13)=1,中断向量表基址为0xFFFF0000。


在linux中,向量表建立的函数为:

init/main.c --> start_kernel() --> trap_init()。

void __init trap_init(void){    unsigned long vectors = CONFIG_VECTORS_BASE;    ...    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);    ...}


在2.6.26内核中CONFIG_VECTORS_BASE最初是在各个平台的配置文件中设定的,如:

arch/arm/configs/s3c2410_defconfig中:

CONFIG_VECTORS_BASE=0xffff0000


__vectors_end 至 __vectors_start之间为异常向量表。

位于arch/arm/kernel/entry-armv.S中:

    .globl  __vectors_start__vectors_start: ARM(   swi SYS_ERROR0  ) THUMB( svc #0      ) THUMB( nop         )        W(b)    vector_und + stubs_offset    W(ldr)  pc, .LCvswi + stubs_offset    W(b)    vector_pabt + stubs_offset    W(b)    vector_dabt + stubs_offset    W(b)    vector_addrexcptn + stubs_offset    W(b)    vector_irq + stubs_offset    W(b)    vector_fiq + stubs_offset                 .globl  __vectors_end__vectors_end:


__stubs_end 至 __stubs_start之间是异常处理的位置。也位于文件arch/arm/kernel/entry-armv.S中。vector_und、vector_pabt、vector_irq、vector_fiq都在它们中间。


stubs_offset值如下:

    .equ    stubs_offset, __vectors_start + 0x200 - __stubs_start

stubs_offset的确定:

http://image41.360doc.com/DownloadImg/2011/10/3120/18908403_1.gif

当汇编器看到B指令后会把要跳转的标签转化为相对于当前PC的偏移量(±32M)写入指令码。从上面的代码可以看到中断向量表和stubs都发生了代码搬移,所以如果中断向量表中仍然写成b vector_irq,那么实际执行的时候就无法跳转到搬移后的vector_irq处,因为指令码里写的是原来的偏移量,所以需要把指令码中的偏移量写成搬移后的。我们把搬移前的中断向量表中的irq入口地址记irq_PC,它在中断向量表的偏移量就是irq_PC-vectors_start, vector_irq在stubs中的偏移量是vector_irq-stubs_start,这两个偏移量在搬移前后是不变的。搬移后 vectors_start在0xffff0000处,而stubs_start在0xffff0200处,所以搬移后的vector_irq相对于中断 向量中的中断入口地址的偏移量就是

    200+(vector_irq-stubs_start)-(irq_PC-vectors_star) = (vector_irq-irq_PC) + vectors_start+200-stubs_start

对于括号内的值实际上就是中断向量表中写的vector_irq,减去irq_PC是由汇编器完成的,而后面的 vectors_start+200-stubs_start就应该是stubs_offset,实际上在entry-armv.S中也是这样定义的。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小天才电话手表停机怎么办 移动手机卡不知道号码怎么办 天猫退款手机号换了怎么办 科目二考试脚抖怎么办 面试新工作没打电话怎么办 怀孕5个月胎位低怎么办 做业务很害怕打电话怎么办 固定电话总是接到骚扰电话怎么办 电话卡通话被限制了怎么办? 手机名单拉黑了怎么办 被苹果6s被拉黑怎么办 重庆福利企业解聘残疾职工怎么办 被银行拉入黑名单怎么办 借的钱还不起了怎么办 支付宝手机号空号了怎么办 到处贷不到钱了怎么办 还不起钱借不到怎么办 闯红灯收到短信不去扣分怎么办 被一家公司骗了怎么办 oppo手机无线网信号差怎么办 oppo手机无线网网速慢怎么办 电脑无法解析dns地址怎么办 vivox9手机卡顿反应慢怎么办 vivo手机设置成英文怎么办 wi-fi模块坏了怎么办 苹果手机dns被劫持怎么办 圆通快递一直不派送怎么办 凯越没有高压火怎么办 理财回执单丢了怎么办 余额宝超10万怎么办 商场主题经营改变商户怎么办 一个好的项目需要资金怎么办 没有做暂估入库的凭证怎么办 电脑显示宽带连接已断开怎么办 电脑ip地址连不上网怎么办 百度网盘资源打不开怎么办 百度网盘视频格式不支持怎么办 origin注册邮箱填错了怎么办 58同城手机输入不合法怎么办 银行卡密码输入错误三次怎么办 私密相册系统升级后打不开怎么办