Linux混入了mmu内存管理之后,ARM的中断是怎么样的呢?和我们在裸板上的中断有没有区别?让我们从源代码入手,做一个粗略的分析:
init/main.c->start_kernel()->trap_init()
//-----------------------------------------------
1.trap_init()
//gliethttp函数位于arch/arm/kernel/traps.c
void __init trap_init(void)
{
extern void __trap_init(unsigned long);
unsigned long base = vectors_base(); //返回中断base基址0xffff0000
__trap_init(base); //以base为vector基址,初始化中断向量表
if (base != 0)
printk(KERN_DEBUG "Relocating machine vectors to 0x%08lx\n",
base);
#ifdef CONFIG_CPU_32
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
#endif
}
//--------------------------------------
2.vectors_base()
//gliethttp include/arch/asm-arm/proc-armv/system.h
extern unsigned long cr_alignment;
#if __LINUX_ARM_ARCH__ >= 4 //at91rm9200是ARMV4结构
#define vectors_base() ((cr_alignment & CR_V) ? 0xffff0000 : 0)
#else
#define vectors_base() (0)
#endif
可以看到ARMv4以下的版本,该地址固定为0;ARMv4及以上版本,ARM中断向量表的地址由CP15协处理器c1寄存器中V位(bit[13])控制,V和中断向量表的对应关系如下:
V=0 ~ 0x00000000~0x0000001C
V=1 ~ 0xffff0000~0xffff001C
//------------------------------------------
2.1 cr_alignment
//gliethttp arch/arm/kernel/entry-armv.S
ENTRY(stext)
mov r12, r0
mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode
msr cpsr_c, r0 @ and all irqs disabled
//__lookup_processor_type 查询处理器类型,[gliethttp
以后补上<浅析head-armv.S>]返回值
//2007-07-04
//r9 = processor ID //读取cp15的c0寄存器
//r10 = pointer to processor structure
//下面会add pc, r10, #12,跳转到__arm920_setup
//gliethttp 在vmlinux-armv.lds.in中
//__proc_info_begin = .;
// *(.proc.info)
// __proc_info_end = .;
//见2.2
bl __lookup_processor_type
teq r10, #0 @ invalid processor?
moveq r0, #'p' @ yes, error 'p'
beq __error
bl __lookup_architecture_type
teq r7, #0 @ invalid architecture?
moveq r0, #'a' @ yes, error 'a'
beq __error
//__create_page_tables 创建arm启动临时使用的前4M页表
bl __create_page_tables
adr lr, __ret @ return address
add pc, r10, #12 @ initialise processor
.type __switch_data, %object
__switch_data: .long __mmap_switched
.long SYMBOL_NAME(__bss_start)
.long SYMBOL_NAME(_end)
.long SYMBOL_NAME(processor_id)
.long SYMBOL_NAME(__machine_arch_type)
.long SYMBOL_NAME(cr_alignment)
.long SYMBOL_NAME(init_task_union)+8192
/*
* Enable the MMU. This completely changes the structure of the visible
* memory space. You will not be able to trace execution through this.
* If you have an enquiry about this, *please* check the linux-arm-kernel
* mailing list archives BEFORE sending another post to the list.
*/
.type __ret, %function
__ret: ldr lr, __switch_data
mcr p15, 0, r0, c1, c0
//将__arm920_setup中设置的r0值,置入cp15协处理器c1寄存器中
mrc p15, 0, r0, c1, c0, 0 @ read it back.
mov r0, r0
//填充armv4中的三级流水线:mov r0,
r0 对应一个nop,所以对应2个nop和一个mov pc,lr刚好三个"无用"操作
mov r0, r0
mov pc, lr
//跳转到__mmap_switched函数 gliethtttp
/*
* The following fragment of code is executed with the MMU on, and uses
* absolute addresses; this is not position independent.
*
* r0 = processor control register
* r1 = machine ID
* r9 = processor ID
*/
.align 5
__mmap_switched:
adr r3, __switch_data + 4
ldmia r3, {r4, r5, r6, r7, r8, sp}@ r2 = compat
//2007-07-04 gliethttp
//r4 ~ __bss_start
//r5 ~ _end
//r6 ~ processor_id
//r7 ~ __machine_arch_type
//r8 ~ cr_alignment
//sp ~ (init_task_union)+8192
//以下几步操作对processor_id,__machine_arch_type,cr_alignment赋值gliethttp
mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r4, r5 //bss区清0
strcc fp, [r4],#4
bcc 1b
str r9, [r6] @ Save processor ID
str r1, [r7] @ Save machine type
#ifdef CONFIG_ALIGNMENT_TRAP
orr r0, r0, #2 @ ...........A.
#endif
bic r2, r0, #2 @ Clear 'A' bit
//r2存放 禁用TRAP队列故障 后的r0值
//r8->cr_alignment,cr_no_alignment
//所以stmia r8, {r0, r2}后,cr_alignment = r0,cr_no_alignment = r2
stmia r8, {r0, r2} @ Save control register values
b SYMBOL_NAME(start_kernel) //进入内核C程序
//--------------------------------------
2.2 __arm920_proc_info
//gliethttp arch/arm/mm/proc-arm920.S
.section ".proc.info", #alloc, #execinstr
.type __arm920_proc_info,#object
__arm920_proc_info:
//该地址存储到r10中
.long 0x41009200
.long 0xff00fff0
.long 0x00000c1e @ mmuflags
b __arm920_setup
//add pc, r10, #12 gliethttp将使cpu执行b __arm920_setup跳转指令
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
.long cpu_arm920_info
.long arm920_processor_functions
.size __arm920_proc_info, . - __arm920_proc_info
//----------------------------------------
2.3 __arm920_setup
.section ".text.init", #alloc, #execinstr
__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
mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
mcr p15, 0, r4, c2, c0 @ load page table pointer
mov r0, #0x1f @ Domains 0, 1 = client
mcr p15, 0, r0, c3, c0 @ load domain access register
mrc p15, 0, r0, c1, c0 @ get control register v4
/*
* Clear out 'unwanted' bits (then put them in if we need them)
*/
//gliethttp r0单元存放了cp15协处理器c1寄存器的值,如下代码对该值进行加工
@ VI ZFRS BLDP WCAM
bic r0, r0, #0x0e00 //清0 bit[9..11]
bic r0, r0, #0x0002 //清0 bit[1]
bic r0, r0, #0x000c
bic r0, r0, #0x1000 @ ...0 000. .... 000.
/*
* Turn on what we want
*/
orr r0, r0, #0x0031 //bit0=1 使能mmu
orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1
//bit13=1 中断向量表基址为0xFFFF0000
#ifndef CONFIG_CPU_DCACHE_DISABLE
orr r0, r0, #0x0004 @ .... .... .... .1..
#endif
#ifndef CONFIG_CPU_ICACHE_DISABLE
orr r0, r0, #0x1000 @ ...1 .... .... ....
#endif
mov pc, lr |