异常向量表的安装与调用

112 阅读2分钟

本文已参与【新人创作礼】活动,一起开启掘金创作之路。

一、中断的发生、处理过程

  • 中断发生的硬件过程 在这里插入图片描述

中断处理的过程和中断发生的过程正好相反

  • 中断处理的软件处理流程
    • CPU执行完当前指令,检查到发生了中断,跳到向量表
    • 保存现场、执行GIC提供的处理函数、回复现场

二、异常向量表的安装

对于arm结构来说,异常向量表有两个地址,一个是地址0x00000000,一个是地址0xffff0000。 这个0xffff0000是一个虚拟地址,它需要映射到某个物理的地址,这个物理地址存放的就是异常向量表。

2.1 复制向量表

arch/arm/kernel/entry-armv.S程序入口,需要把这个复制到内核种,并映射:

    .section .vectors, "ax", %progbits
.L__vectors_start:
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)  pc, .L__vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq

    .data

从源头开始看,对于arm架构,这是第一个运行的文件:

// arch\arm\kernel\head.S
    mrc p15, 0, r9, c0, c0      @ get processor id
    bl  __lookup_processor_type     @ r5=procinfo r9=cpuid
	//.....
    bl  __create_page_tables		@ 建立虚拟地址和物理地址的映射关系
    ldr r13, =__mmap_switched       @ address to jump to after @ 记录函数地址
                        @ mmu has been enabled
	//....
1:  b   __enable_mmu
	//....

__enable_mmu:
	//....
	b   __turn_mmu_on			@ 打开mmu
ENDPROC(__enable_mmu)

ENTRY(__turn_mmu_on)
	//....
    mov r3, r13				@ 把r13 赋值给r3
    ret r3						@ 返回r3
__turn_mmu_on_end:
ENDPROC(__turn_mmu_on)

__mmap_switched:		@开始执行
	//....
	b   start_kernel		@进入c函数的start_kernel
ENDPROC(__mmap_switched)
  • 复制向量表
// init/main.c
asmlinkage __visible void __init start_kernel(void)
{
	//...
	setup_arch(&command_line);		//设置架构
    paging_init(mdesc);		// arch/arm/kernel/setup.c	页的初始化
    	devicemaps_init(mdesc);		// arch/arm/mm/mmu.c 设备映射,复制异常向量表的关键
    		vectors = early_alloc(PAGE_SIZE * 2);		//1.分配新向量表 8k内存
    		early_trap_init(vectors);							//2.从代码把向量表复制到新向量表

				//3.映射新向量表到虚拟地址0xffff0000
				map.pfn = __phys_to_pfn(virt_to_phys(vectors));	//物理地址就是上面分配的
				map.virtual = 0xffff0000;		//虚拟地址,发生异常时会执行vectors
				map.length = PAGE_SIZE;
#ifdef CONFIG_KUSER_HELPERS
				map.type = MT_HIGH_VECTORS;
#else
				map.type = MT_LOW_VECTORS;
#endif
				create_mapping(&map);

	//...
}

在这里插入图片描述

把vectors的向量,复制到对应的地址。

2.2 向量表在哪

上面代码中可以看到代码中向量表位于__vectors_start,它在arch/arm/kernel/vmlinux.lds中定义:

 __vectors_start = .;
 .vectors 0xffff0000 : AT(__vectors_start) {
  *(.vectors)
 }
 . = __vectors_start + SIZEOF(.vectors);
 __vectors_end = .;
 __stubs_start = .;
 .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
  *(.stubs)
 }

在代码里搜.vectors,可以找到向量表: 在这里插入图片描述

三、中断向量

发生中断时,CPU跳到向量表去执行b vector_irq。 vector_irq函数使用宏来定义: 在这里插入图片描述

四、处理流程

在这里插入图片描述

五、处理函数

在这里插入图片描述