微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux中断向量表搬移设计过程

ARM Linux中断向量表搬移设计过程

时间:11-09 来源:互联网 点击:

_svc@3 (SVC_26 / SVC_32)

。。。

.long__pabt_invalid@f

/*

* Undef instr entry dispatcher

* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC

*/

vector_stubund, UND_MODE

.long__und_usr@0 (USR_26 / USR_32)

.long__und_invalid@1 (FIQ_26 / FIQ_32)

.long__und_invalid@2 (IRQ_26 / IRQ_32)

.long__und_svc@3 (SVC_26 / SVC_32)

。。。

.long__und_invalid@f

.align5

vector_fiq:

disable_fiq

subspc, lr, #4

vector_addrexcptn:

bvector_addrexcptn

/*

* We group all the following data together to optimise

* for CPUs with separate I & D caches.

*/

.align5

.LCvswi:

.wordvector_swi

.globl__stubs_end

__stubs_end:

.equstubs_offset, __vectors_start + 0x200 - __stubs_start

.globl__vectors_start

__vectors_start:

swiSYS_ERROR0

bvector_und + stubs_offset

ldrpc, .LCvswi + stubs_offset

bvector_pabt + stubs_offset

bvector_dabt + stubs_offset

bvector_addrexcptn + stubs_offset

bvector_irq + stubs_offset

bvector_fiq + stubs_offset

.globl__vectors_end

__vectors_end:

为了让大家看得更清,我把代码的结构再次简化成这样:

.globl__stubs_start

__stubs_start:

.align5

vector_irq:

[code part]//展开代码

[jump table part]//地址跳转表

。。。

.align5

vector_dabt:

[code part]

[jump table part]

。。。

.align5

vector_ pabt:

[code part]

[jump table part]

。。。

.align5

vector_und:

[code part]

[jump table part]

。。。

.align5

vector_fiq:

。。。

.globl__stubs_end

__stubs_end:

.globl__vectors_start

__vectors_start:

swiSYS_ERROR0

bvector_und + stubs_offset

ldrpc, .LCvswi + stubs_offset

bvector_pabt + stubs_offset

bvector_dabt + stubs_offset

bvector_addrexcptn + stubs_offset

bvector_irq + stubs_offset

bvector_fiq + stubs_offset

.globl__vectors_end

__vectors_end:

在这里我不花过多的篇幅去解释代码的意思,这不是本文的目的,只要你把结构看清,就达到目的了。但我会花点时间研究一下展开代码部分(蓝色)的特征,这部分代码是与位置无关的代码,我们稍微研究一下,它为什么会这么写。

.align5

vector_irq:

[code part]//展开代码

[jump table part]//地址跳转表

。。。

首先这部分代码大致都是一样的结构,前面是一些代码,后面跟着一个跳转表。跳转表里面定义了一些地址。我们截取这部分看

。。。

@ the branch table must immediately follow this code

@

andlr, lr, #0x0f(1)// lr中当前存储了上一个状态寄存器的值,对后几位做与,

//就是取在中断前处在用户态还是核心态,这个值用作跳

//转表的索引

movr0, sp(2)//用做他用,sp值当第一个参数传给后面函数

ldrlr, [pc, lr, lsl #2](3)// pc是当前执行指令地址加8,即跳转表的基地址,lr是索引

//很好的技巧,取pc找当前地址什么时候都没错

movpc, lr@ branch to handler in SVC mode

[jump table]

.long__irq_usr@0(USR_26 / USR_32)

.long__irq_invalid@1(FIQ_26 / FIQ_32)

.long__irq_invalid@2(IRQ_26 / IRQ_32)

.long__irq_svc@3(SVC_26 / SVC_32)

真正的跳转在最后一句完成,大家都看得很清楚。跳到哪里去了,如果中断以前是svc模式,就会跳到__irq_svc。我们发现这里不会直接用b(bl,bx等)个,

ü一是b跳转后面是个偏移,而这个偏移是有限制的,不能太大

ü二是b跳转后面的偏移你不知道在代码拷贝后还是不是那个样子,因为我们要搬移代码,所以如果你不能确定搬移后的偏移不变,那你就用绝对地址,而上面的代码前三句就是算出绝对地址来,然后用绝对地址赋值给pc直接完成跳转。

这些都是一些技巧,总之你要注意的是写位置无关的代码时涉及到跳转部分,用b跳转还是直接赋成绝对地址(通过跳转表实现),如果你不能保证搬移后的偏移一致,写这部分就要注意了,要用一些技巧的。

大家可以去用gcc的-fPIC和-S选项汇编一个小的函数看看,fPIC就是与位置无关选项,相信编译过动态库的人都熟悉,看看它是怎么做的。你会发现异曲同工。

Scenario 3第三场景大搬移

我用一个章节来介绍大搬移的过程,以及一些在搬移中Linux出现的问题及解决方案。我把整个的搬移过程做成一张图里,然后讨论了一些技术细节。我们看到这是一个巨大无比的图,我们这章节的所阐述的内容都在图里。

我们将搬移前的代码组织称为Code/Load视图,因为这是代码中的(或image中的)组织情况,把搬移后的代码组织称为Exec视图,反映的是代码执行时代码在内存中的情况。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top