Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2707775
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类:

2012-12-09 14:34:17

原文地址:linux异常处理体系结构 作者:rxy429

内核部分:内核版本linux 2.6.22.6
   1. 从start_kernel() // 在 init/main.c中

点击(此处)折叠或打开

  1. start_kernel()
  2. ...
  3.   trap_init()
  4. ...   

点击(此处)折叠或打开

  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);
  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. }
trap_init实现的功能是将脚本文件定义的中断向量连接地址映射到0xffff0000为起始的地址中。

   2.中断过程分析:以irq中断为例
   在main函数执行过程中如果有中断产生那么会跳到中断入口   (entry-asmv.S)

 

点击(此处)折叠或打开

  1. .LCvswi:
  2. .word vector_swi

  3. .globl __stubs_end
  4. __stubs_end:

  5. .equ stubs_offset, __vectors_start + 0x200 - __stubs_start

  6. .globl __vectors_start
  7. __vectors_start:
  8.    swi SYS_ERROR0
  9.    b vector_und + stubs_offset
  10.    ldr pc, .LCvswi + stubs_offset
  11.    b vector_pabt + stubs_offset
  12.    b vector_dabt + stubs_offset
  13.    b vector_addrexcptn + stubs_offset
  14.    b vector_irq + stubs_offset
  15.    b vector_fiq + stubs_offset

  16. .globl __vectors_end
  17. __vectors_end:
在内核中,当发生异常是就会进入相应的工作模式,内核是通过一个宏来管理这些模式的。

点击(此处)折叠或打开

  1. .macro vector_stub, name, mode, correction=0
  2. .align 5

  3. vector_\name:
  4. .if \correction
  5. sub lr, lr, #\correction
  6. .endif

  7. @
  8. @ Save r0, lr_ (parent PC) and spsr_
  9. @ (parent CPSR)
  10. @
  11. stmia sp, {r0, lr} @ save r0, lr
  12. mrs lr, spsr
  13. str lr, [sp, #8] @ save spsr

  14. @
  15. @ Prepare for SVC32 mode. IRQs remain disabled.
  16. @
  17. mrs r0, cpsr
  18. eor r0, r0, #(\mode ^ SVC_MODE)
  19. msr spsr_cxsf, r0

  20. @
  21. @ the branch table must immediately follow this code
  22. @
  23. and lr, lr, #0x0f
  24. mov r0, sp
  25. ldr lr, [pc, lr, lsl #2]
  26. movs pc, lr @ branch to handler in SVC mode
  27. .endm
  1.保存返回地址,r0,lr,spsr寄存器
  2.切换到管理模式
  3.跳转到相应的入口

点击(此处)折叠或打开

  1. vector_stub irq, IRQ_MODE, 4

  2. .long __irq_usr @ 0 (USR_26 / USR_32)
  3. .long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
  4. .long __irq_invalid @ 2 (IRQ_26 / IRQ_32)
  5. .long __irq_svc @ 3 (SVC_26 / SVC_32)
  6. .long __irq_invalid @ 4
  7. .long __irq_invalid @ 5
  8. .long __irq_invalid @ 6
  9. .long __irq_invalid @ 7
  10. .long __irq_invalid @ 8
  11. .long __irq_invalid @ 9
  12. .long __irq_invalid @ a
  13. .long __irq_invalid @ b
  14. .long __irq_invalid @ c
  15. .long __irq_invalid @ d
  16. .long __irq_invalid @ e
  17. .long __irq_invalid @ f

点击(此处)折叠或打开

  1. __irq_svc:
  2. svc_entry

  3. #ifdef CONFIG_TRACE_IRQFLAGS
  4. bl trace_hardirqs_off
  5. #endif
  6. #ifdef CONFIG_PREEMPT
  7. get_thread_info tsk
  8. ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
  9. add r7, r8, #1 @ increment it
  10. str r7, [tsk, #TI_PREEMPT]
  11. #endif

  12. irq_handler      //这是一个宏
  13. #ifdef CONFIG_PREEMPT
  14. ldr r0, [tsk, #TI_FLAGS] @ get flags
  15. tst r0, #_TIF_NEED_RESCHED
  16. blne svc_preempt
  17. preempt_return:
  18. ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
  19. str r8, [tsk, #TI_PREEMPT] @ restore preempt count
  20. teq r0, r7
  21. strne r0, [r0, -r0] @ bug()
  22. #endif
  23. ldr r0, [sp, #S_PSR] @ irqs are already disabled
  24. msr spsr_cxsf, r0
  25. #ifdef CONFIG_TRACE_IRQFLAGS
  26. tst r0, #PSR_I_BIT
  27. bleq trace_hardirqs_on
  28. #endif
  29. ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr


点击(此处)折叠或打开

  1. .macro irq_handler
  2. get_irqnr_preamble r5, lr
  3. 1: get_irqnr_and_base r0, r6, r5, lr
  4. movne r1, sp
  5. @
  6. @ routine called with r0 = irq number, r1 = struct pt_regs *
  7. @
  8. adrne lr, 1b
  9. bne asm_do_IRQ
到这调用asm_do_IRQ函数  传入的参数为 r0 = irq number, r1 = struct pt_regs *  这个是正真的调用异常处理函数 前面都只是一些调用处理函数前的操作,到这里已经传入了2个参数,其中很重要的一个参数就是irq number.我们把这个函数作为分界点。。。





   



阅读(800) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~