内核如何与中断号对应上

   在google上输入arm linux,找到全是如何配制,就没有人解释一下吗?靠,我觉得不仅要知其然,还要知其所以然。不知道放哪里好。我喜欢这里,所以来这里投,试试 还有,我的机还在用PII,老是出问题,前不久,分区就没了一会,心痛啊!!!!!!!!!!!好多好东东都没了。顺便问一下大家谁有碰到过没有光驱接上,硬盘就不能启动的问题啊。这个问题可把我这个自称高手的人给难坏了    2004.5.23

    今天开始,我要好好看看arm linux的代码了,好久没有这样的豪言壮语了
    拿哪个开刀呢。翻翻以前的工作,加上正好有人问,所以决定先搞定entry-armv.S文件。
    看我一刀

    文件一开始是一大堆宏定义,用于指明是用的何种芯片。定义了三个针对不同芯片的宏,disable_fiq、get_irqnr_and_base和irq_prio_table。

    跳过这些宏,来到:
    .section “.text.init”, #alloc, #execinstr 这里说明了下面的段是初始化段,有关初始化段的内容参考书籍。

1        vector_IRQ:
2                ldr r13, .LCsirq
3                sub lr, lr, #4
4                str lr, [r13]
5                mrs lr, spsr
6                str lr, [r13, #4]
7                mrs r13, spsr
8                bic r13, r13, #MODE_MASK
9                orr r13, r13, #MODE_SVC|I_BIT
10                msr spsr_c, r13
11                and lr, lr, #15
12                ldr lr, [pc, lr, lsl #2]
13                movs pc, lr
14                .LCtab_irq: .word __irq_usr
15                .word __irq_invalid
16                .word __irq_invalid
17                .word __irq_svc
18                .word __irq_invalid
                …
解释:
1.IRQ中断向量的入口
2.读取.LCsirq地址的内容到r13寄存器中。.LCsirq定义如下:
.LCsirq: .word __temp_irq
即.LCsirq中保存了__temp_irq的地址,而__temp_irq定义如下:
__temp_irq: .word 0 @saved lr_irq
          .word 0 @saved spsr_irq
          .word -1 @old_r0
从这里可以得出r13保存了__temp_irq的地址,而这个地址用来保存了lr_irq、spsr_irq、old_r0的值。具体情况参见下面的解释。
3.恢复发生中断时的地址(该地址即是中断返回地址),参考ARM IRQ异常的书籍。
4.保存返回地址到r13,前面看到了r13的赋值情况,所以地址是被保存在__temp_irq的第一个word中。
5.读取中断发生时的CPSR,有关情况参考ARM IRQ异常的书籍
6.保存CPSR到__temp_irq的第二个word中。
7.将SPSR保存到r13中。注:这里不使用lr,而要另赋值到r13中,是因为要改变SPSR的值,而原来的值也有用。所以改变用r13,原来的值用lr。
8.清除模式位。MODE_MASK的定义参见\linux-2.4.26\include\asm-arm\proc-armv\ ptrace.h文件:
#define MODE_MASK        0x1f
9.在\linux-2.4.26\include\asm-arm\proc-armv\ ptrace.h下还定义了:
#define SVC_MODE        0x13
#define I_BIT                0x80
这时r13被修改为禁止irq中断的svc模式。
10.将修改好的模式放入spsr中。
11.lr保留了原来的cpsr,做与操作后,只保留其模式位。即说明该中断发生自何种模式下。
12.读取.LCtab_irq中的内容,放置于lr寄存器中。而.LCtab_irq中保存了中断发生自各种不同模式下的处理函数。其中使用了pc寄存器,详情参考ARM书籍。
13.切换模式并跳转到相应处理函数。

0        __irq_usr: sub sp, sp, #S_FRAME_SIZE
1                stmia sp, {r0 - r12}
2                ldr r4, .LCirq
3                add r8, sp, #S_PC
4                ldmia r4, {r5 - r7}
5                stmia r8, {r5 - r7}
6                stmdb r8, {sp, lr}^
7                alignment_trap r4, r7, __temp_irq
8                zero_fp
9                get_irqnr_and_base        r0, r6, r5, lr
10                movne r1, sp
11                adrsvc        ne, lr, 1b
12                bne do_IRQ
13                mov why, #0
14                get_current_task tsk
15                b ret_to_usr

解释:
0.此函数是当IRQ中断发生在usr模式时,调用的。它首先从堆栈中保留出存放寄存器的空间,用于保存现场。在entry-header.s中定义了如下宏:
#define S_FRAME_SIZE        72
#define S_OLD_R0        68
#define S_PSR                64
#else
#define S_FRAME_SIZE        68
#define S_OLD_R0        64
#define S_PSR                60
#endif

#define S_PC                60
#define S_LR                56
#define S_SP                52
#define S_IP                48
#define S_FP                44
#define S_R10                40
#define S_R9                36
#define S_R8                32
#define S_R7                28
#define S_R6                24
#define S_R5                20
#define S_R4                16
#define S_R3                12
#define S_R2                8
#define S_R1                4
#define S_R0                0
#define S_OFF                8
#define S_FRAME_SIZE        72
#define S_OLD_R0        68
#define S_PSR                64

从这些宏中,我们可以得到arm linux使用的栈结构如下图:
0  |-------------|
   | S_R0        |
4  |-------------|
   | S_R1        |
8  |-------------|
   | S_R2        |
12 |-------------|
   | S_R3        |
16 |-------------|
   | S_R4        |
20 |-------------|
   | S_R5        |
24 |-------------|
   | S_R6        |
28 |-------------|
   | S_R7        |
32 |-------------|
   | S_R8        |
36 |-------------|
   | S_R9        |
40 |-------------|
   | S_R10       |
44 |-------------|
   | S_FP        |
48 |-------------|
   | S_IP        |
52 |-------------|
   | S_SP        |
56 |-------------|
   | S_LR        |
60 |-------------|
   | S_PC        |
64 |-------------|
   | S_PSR       |
68 |-------------|
   | S_OLD_R0    |
72 |-------------|

注:这个图在arm linux中很重要!

1.保存如上图所示的r0到r12寄存器。因为这些寄存器得以保存。我们现在可以大胆的使用这些寄存器了
2.读取.LCirq的内容到r4寄存器中。.LCirq的定义如下:
.LCirq .word __temp_irq
哈哈,在vector_IRQ中提到的__temp_irq在此显身。我们知道__temp_irq中保存了些什么。我想各位应该猜到了下面的代码是什么了吧
在这里将.LCirq的地址放到r4寄存器中。
3.将r8指到前面所说的保存S_PC的地方。前面保存了r0-r12,还有S_SP、S_LR、S_PC、S_PSR、S_OLD_R0没有保存。
4.读取__temp_irq中的内容
5.保存S_PC、S_PSR、S_OLD_R0。
6.保存S_SP、S_LR,要注意保存的是用户模式的sp和lr。
7.在entry-header.S中,定义了alignment_trap宏:

        .macro        alignment_trap, rbase, rtemp, sym
#ifdef CONFIG_ALIGNMENT_TRAP
#define OFF_CR_ALIGNMENT(x)        cr_alignment - x

        ldr        \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
        mcr        p15, 0, \rtemp, c1, c0
#endif
        .endm
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值