字符设备驱动-Linux内核异常处理体系结构
来源:互联网 发布:网络兼职平台 编辑:程序博客网 时间:2024/06/05 20:04
Linux异常处理体系结构
以中断这种异常来举例分析:
当我们在裸机操作中断时候:
① 构建异常向量表
② cpu发生中断,跳到异常向量入口执行
③ 跳转到某函数
③-a 保存被中断的现场
③-b 执行中断处理函数
④-c 恢复现场
Linux驱动层面同样如此:
① 通过trap_init构造异常向量表
② cpu发生中断,跳到异常向量入口执行(b vector_irq + stubs_offset)
③ 跳转到vector_irq用宏实现保存、执行、恢复
下面来分析一下内核怎样处理中断这种异常的:
内核在
asmlinkage void __init start_kernel(void)
(源码在init/main.c)中调用trap_init函数来设置异常的处理函数。
Ⅰ.trap_init函数(arch/arm/kernel/traps.c)
通过
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
来将异常向量表拷贝到ARM架构CPU的异常向量基址0xffff0000(还有一种0x00000000)
void __init trap_init(void){#if defined(CONFIG_KGDB) return;}void __init early_trap_init(void){memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);}
Ⅱ. 搜索__vectors_start
(arch\arm\kernel\entry-armv.S)查看异常向量表
.globl __vectors_start__vectors_start: swi SYS_ERROR0 b vector_und + stubs_offset ldr pc, .LCvswi + stubs_offset b vector_pabt + stubs_offset b vector_dabt + stubs_offset b vector_addrexcptn + stubs_offset b vector_irq + stubs_offset b vector_fiq + stubs_offset .globl __vectors_end__vectors_end: .data .globl cr_alignment .globl cr_no_alignmentcr_alignment: .space 4cr_no_alignment: .space 4
Ⅲ.以irq中断异常为例b vector_irq + stubs_offset
,搜索整个文件找不到vector_irq
,往上查询得知这是通过vector_stub宏(arch\arm\kernel\entry-armv.S)来定义的:
vector_stub irq, IRQ_MODE, 4 .long __irq_usr @ 0 (USR_26 / USR_32) .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) .long __irq_invalid @ 2 (IRQ_26 / IRQ_32) .long __irq_svc @ 3 (SVC_26 / SVC_32) .long __irq_invalid @ 4 .long __irq_invalid @ 5 .long __irq_invalid @ 6 .long __irq_invalid @ 7 .long __irq_invalid @ 8 .long __irq_invalid @ 9 .long __irq_invalid @ a .long __irq_invalid @ b .long __irq_invalid @ c .long __irq_invalid @ d .long __irq_invalid @ e .long __irq_invalid @ f
Ⅳ. 通过搜索vector_stub
来查找宏定义
.macro vector_stub, name, mode, correction=0 .align 5vector_\name: .if \correction sub lr, lr, #\correction .endif @ @ Save r0, lr_<exception> (parent PC) and spsr_<exception> @ (parent CPSR) @ stmia sp, {r0, lr} @ save r0, lr mrs lr, spsr str lr, [sp, #8] @ save spsr @ @ Prepare for SVC32 mode. IRQs remain disabled. @ mrs r0, cpsr eor r0, r0, #(\mode ^ SVC_MODE) msr spsr_cxsf, r0 @ @ the branch table must immediately follow this code @ and lr, lr, #0x0f mov r0, sp ldr lr, [pc, lr, lsl #2] movs pc, lr @ branch to handler in SVC mode .endm
Ⅴ. 将vector_stub irq, IRQ_MODE, 4
参数代入进去
.macro vector_stub, name, mode, correction=0 .align 5vector_irq: sub lr, lr, #4 .endif @ @ Save r0, lr_<exception> (parent PC) and spsr_<exception> @ (parent CPSR) @ stmia sp, {r0, lr} @ save r0, lr mrs lr, spsr str lr, [sp, #8] @ save spsr @ @ Prepare for SVC32 mode. IRQs remain disabled. @ mrs r0, cpsr eor r0, r0, #(\mode ^ SVC_MODE) msr spsr_cxsf, r0 @ @ the branch table must immediately follow this code @ and lr, lr, #0x0f mov r0, sp ldr lr, [pc, lr, lsl #2] movs pc, lr @ branch to handler in SVC mode .endm .long __irq_usr @ 0 (USR_26 / USR_32) .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) .long __irq_invalid @ 2 (IRQ_26 / IRQ_32) .long __irq_svc @ 3 (SVC_26 / SVC_32) .long __irq_invalid @ 4 .long __irq_invalid @ 5 .long __irq_invalid @ 6 .long __irq_invalid @ 7 .long __irq_invalid @ 8 .long __irq_invalid @ 9 .long __irq_invalid @ a .long __irq_invalid @ b .long __irq_invalid @ c .long __irq_invalid @ d .long __irq_invalid @ e .long __irq_invalid @ f
Ⅵ. 进入__irq_usr
中断模式
__irq_usr: usr_entry#ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off#endif get_thread_info tsk#ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count add r7, r8, #1 @ increment it str r7, [tsk, #TI_PREEMPT]#endif irq_handler#ifdef CONFIG_PREEMPT ldr r0, [tsk, #TI_PREEMPT] str r8, [tsk, #TI_PREEMPT] teq r0, r7 strne r0, [r0, -r0]#endif#ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_on#endif mov why, #0 b ret_to_user .ltorg .align 5
Ⅶ. 进入irq_handler
来调用中断处理总入口函数asm_do_IRQ
.macro irq_handler get_irqnr_preamble r5, lr1: get_irqnr_and_base r0, r6, r5, lr movne r1, sp @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ adrne lr, 1b bne asm_do_IRQ
ARM架构Linux内核的异常处理体系结构
阅读全文
1 0
- 字符设备驱动-Linux内核异常处理体系结构
- Linux内核异常处理体系结构
- Linux内核异常处理体系结构
- 详解Linux内核异常处理体系结构
- linux内核ioctl(字符设备驱动)
- linux 内核编程之字符设备驱动
- LINUX内核字符设备驱动模型
- Linux内核模块编程-字符设备驱动
- Linux内核之字符设备驱动
- Linux内核编程七:字符设备驱动
- Linux异常处理体系结构
- linux异常处理体系结构
- linux异常处理体系结构
- 【Linux内核驱动】字符设备驱动框架模板
- Linux 内核--总线设备驱动模型(字符设备 && misc字符设备)
- 内核字符设备驱动框架
- LINUX内核设备驱动
- linux内核驱动设备
- shell中“空格”使用总结
- hadoop HA集群的搭建
- transient关键字小结
- ccf 窗口 java 2014_3_2
- MyBatis学习路上打的那些码(四、查询多个User和一个优化typeAlias)
- 字符设备驱动-Linux内核异常处理体系结构
- android 百度云ocr识别快速集成
- 高仿iOS 滚轮实现 省市区 城市选择三级联动,无需自己配置省市区域的数据
- Struts2执行流程及环境搭建
- Java8 新特性 接口中的default方法
- Android中的class动态加载机制
- 双检锁安全性
- 锁定文件失败 开启模块diskearly的操作失败
- chapter12_1对比度与亮度调整