linux phy 初始化过程,【转帖】ARM linux的中断向量表初始化分析

Author:     jimmy.li

Time:        2007-06-09

本文分析基于linux2.4.19 source,pxa 270 cpu.

ARM linux内核启动时,通过start_kernel()->trap_init()的调用关系,初始化内核的中断异常向量表.

/* arch/arm/kernel/traps.c */

void __init trap_init(void)

{

extern void __trap_init(unsigned long);

unsigned long base = vectors_base();

__trap_init(base);

if (base != 0)

oopsprintk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n", base);

#ifdef CONFIG_CPU_32

modify_domain(DOMAIN_USER, DOMAIN_CLIENT);

#endif

}

vectors_base是一个宏,它的作用是获取ARM异常向量的地址,该宏在include/arch/asm-arm/proc-armv/system.h中定义:

extern unsigned long cr_no_alignment; /* defined in entry-armv.S */

extern unsigned long cr_alignment; /* defined in entry-armv.S */

#if __LINUX_ARM_ARCH__ >= 4

#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0)

#else

#define vectors_base() (0)

#endif

对于ARMv4以下的版本,这个地址固定为0;ARMv4及其以上的版本,ARM异常向量表的地址受协处理器CP15的c1寄存器 (control register)中V位(bit[13])的控制,如果V=1,则异常向量表的地址为0x00000000~0x0000001C;如果V=0,则 为:0xffff0000~0xffff001C。(详情请参考ARM Architecture Reference Manual)

下面分析一下cr_alginment的值是在哪确定的,我们在arch/arm/kernel/entry-armv.S找到cr_alignment的定义:

.globl SYMBOL_NAME(cr_alignment)

.globl SYMBOL_NAME(cr_no_alignment)

SYMBOL_NAME(cr_alignment):

.space 4

SYMBOL_NAME(cr_no_alignment):

.space 4

分析过head-armv.S文件的朋友都会知道,head-armv.S是非压缩内核的入口:

1               .section ".text.init",#alloc,#execinstr

2               .type   stext, #function

3ENTRY(stext)

4               mov     r12, r0

6               mov     r0, #F_BIT | I_BIT | MODE_SVC   @ make sure svc mode

7               msr     cpsr_c, r0                      @ and all irqs disabled

8               bl      __lookup_processor_type

9               teq     r10, #0                         @ invalid processor?

10               moveq   r0, #'p'                        @ yes, error 'p'

11               beq     __error

12               bl      __lookup_architecture_type

13               teq     r7, #0                          @ invalid architecture?

14               moveq   r0, #'a'                        @ yes, error 'a'

15               beq     __error

16               bl      __create_page_tables

17               adr     lr, __ret                       @ return address

18               add     pc, r10, #12                    @ initialise processor

19                                                       @ (return control reg)

20

21               .type   __switch_data, %object

22__switch_data: .long   __mmap_switched

23                .long   SYMBOL_NAME(__bss_start)

24                .long   SYMBOL_NAME(_end)

25                .long   SYMBOL_NAME(processor_id)

26                .long   SYMBOL_NAME(__machine_arch_type)

27                .long   SYMBOL_NAME(cr_alignment)

28                .long   SYMBOL_NAME(init_task_union)+8192

29

30                .type   __ret, %function

31__ret:          ldr     lr, __switch_data

32                mcr     p15, 0, r0, c1, c0

33                mrc     p15, 0, r0, c1, c0, 0           @ read it back.

34                mov     r0, r0

35                mov     r0, r0

36                mov     pc, lr

这里我们关心的是从17行开始,17行code处将lr放置为__ret标号处的相对地址,以便将来某处返回时跳转到31行继续运行;

18行,对于我所分析的pxa270平台,它将是跳转到arch/arm/mm/proc-xscale.S中执行__xscale_setup函数, 在__xscale_setup中会读取CP15的control register(c1)的值到r1寄存器,并在r1寄存器中设置相应的标志位(其中包括设置V位=1),但在__xscale_setup中,r1寄存 器并不立即写回到Cp15的control register中,而是在返回后的某个地方,接下来会慢慢分析到。__xscale_setup调用move pc, lr指令返回跳转到31行。

31行,在lr寄存器中放置__switch_data中的数据__mmap_switched,在36行程序会跳转到__mmap_switched处。

32,33行,把r0寄存器中的值写回到cp15的control register(c1)中,再读出来放在r0中。

接下来再来看一下跳转到__mmap_switched处的代码:

40 _mmap_switched:

41                 adr     r3, __switch_data + 4

42                 ldmia   r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat

43                                                        @ sp = stack pointer

44

45                 mov     fp, #0                          @ Clear BSS (and zero fp)

46 1:              cmp     r4, r5

47                 strcc   fp, [r4],#4

48                 bcc     1b

49

50                 str     r9, [r6]                        @ Save processor ID

51                 str     r1, [r7]                        @ Save machine type

52                 bic     r2, r0, #2                      @ Clear 'A' bit

53                 stmia   r8, {r0, r2}                    @ Save control register values

54                 b       SYMBOL_NAME(start_kernel)

41~42行的结果是:r4=__bss_start,r5=__end,...,r8=cr_alignment,..,这里r8保存的是cr_alignment变量的地址.

到了53行,由于之前r0保存的是cp15的control register(c1)的值,这里把r0的值写入r8指向的地址,即cr_alignment=r0.到此为止,我们就看清楚了cr_alignment的赋值过程。

让我们回到trap_init()函数,经过上面的分析,我们知道vectors_base返回0xffff0000。函数__trap_init由汇编代码编写,在arch/arm/kernel/entry-arm.S:

.align 5

__stubs_start:

vector_IRQ:

...

vector_data:

....

vector_prefetch:

...

vector_undefinstr:

...

vector_FIQ: disable_fiq

subs pc, lr, #4

vector_addrexcptn:

b vector_addrexcptn

...

__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 sp!, {r4 - r6, lr}   /* 压栈,保存数据*/

/* 复制异常向量表(.LCvectors起始的8个地址)到r0指向的地址(异常向量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值