CPU 发生中断, 强制的跳到异常向量处
跳转到具体函数
保存被中断处的现场(各种寄存器的值)
执行中断处理函数,处理具体任务
恢复被中断的现场
Linux处理异常流程
异常发生时,会去异常向量表找到入口地址,(这算异常发生之后跳转到第一个处理分支),进入异常模式,保护部分现场,强制进入SVC管理模式,根据异常发生前的工作模式,找到异常处理的第二级分支,在该模式下面接过异常模式堆栈中的信息,接着保存异常发生时异常模式还未保存的信息,准备好处理完毕返回处理程序的地址,调用异常处理函数,恢复现场。
处理异常流程中的汇编处理流程:
Linux内核对异常的初始化设置
在内核启动时,内核会在start_kernel函数中调用trap_init,init_IRQ两个函数来设置异常的处理函数
1. trap_init:(arch/arm/kernel/traps.c中定义)
1 void __init trap_init(void) 2 { 3 unsigned long vectors = CONFIG_VECTORS_BASE; /*CONFIG_VECTORS_BASE = 0xffff0000*/ 4 extern char __stubs_start[], __stubs_end[]; 5 extern char __vectors_start[], __vectors_end[]; 6 extern char __kuser_helper_start[], __kuser_helper_end[]; 7 int kuser_sz = __kuser_helper_end - __kuser_helper_start; 8 9 /* 10 * Copy the vectors, stubs and kuser helpers (in entry-armv.S) 11 * into the vector page, mapped at 0xffff0000, and ensure these 12 * are visible to the instruction stream. 13 */ 14 memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); //void *memcpy(void *dest, const void *src, size_t count) 15 memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); 16 memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); 17 18 /* 19 * Copy signal return handlers into the vector page, and 20 * set sigreturn to be a pointer to these. 21 */ 22 memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, 23 sizeof(sigreturn_codes)); 24 25 flush_icache_range(vectors, vectors + PAGE_SIZE); 26 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); 27 }