LINUX-内核-中断分析-中断向量表-arm

Posted sky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LINUX-内核-中断分析-中断向量表-arm相关的知识,希望对你有一定的参考价值。

转自:http://blog.csdn.net/haolianglh/article/details/51986987

arm中断概念

在《ARM体系结构与编程》第9章中说到,ARM 中有个概念叫做“异常中断”,也就是包括外部中断在内的各种异常。显然,ARM体系的“异常中断”概念更加接近MIPS体系中的“异常”概念。
技术分享图片
既然更类似MIPS体系,那么自然的ARM体系就存在“异常中断入口”和“异常中断向量表”的概念。


arm的异常中断向量表

非向量化中断

ARM体系定义了7种异常中断,在《ARM体系结构与编程》第9章的表9.1中标明了这7种异常中断。其中第6中异常中断即是外部中断的统一入口。显然,在ARM中,也类似MIPS一样实行了非向量化的外部中断。应该说RISC类的架构几乎都是采用非向量化中断。

向量化异常中断

虽然外部中断没有被向量化,但是异常中断被向量化了。因此,ARM也有一个所谓异常中断向量表。
技术分享图片
摘自《ARM体系结构与编程》表9-1,如表 4 1所示,ARM的这个异常中断向量表可以是高端向量表,也可以是低端向量表,两者取其一。区别是基地址不同。高端向量是ARM架构可选配置,可以通过硬件外部输入管脚来配置是低端向量还是高端向量,不能通过指令来改变向量的位置,但如果ARM芯片内部有标准ARM协处理器,那么协处理器CP15的寄存器C1的bit13可以用来切换低端和高端向量地址,等于0时为低端向量,等于1时为高端向量。


异常中断向量表的初始化

arm体系在函数early_trap_init()中初始化这个异常中断向量表,相比x86以设置门的方式赋值idt_table,MIPS直接给全局变量exception_handlers[]成员赋值的方式。arm的方式比较另类。其方式是将从__vectors_start开始,直到__vectors_end之间的一段代码给复制到vectors_base地址上,这个vectors_base其实就是0x0000000或者0xffff0000。

------------------------------------------------arch/arm/kernel/trap.c
void __init early_trap_init(void *vectors_base)
{
     /* 异常向量表 exception vectors的基址 */
unsigned long vectors = (unsigned long)vectors_base;
     extern char __vectors_start[], __vectors_end[];

    vectors_page = vectors_base;

    /*
     * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
     * into the vector page, mapped at 0xffff0000, and ensure these
     * are visible to the instruction stream.
     */
    memcpy((void *)vectors, __vectors_start, 
__vectors_end - __vectors_start);
  . . .
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

异常向量表内容是针对ARM的7种异常要采取的不同的处理代码,但是这个异常向量表总size是非常小的,其中每一种异常只有4字节的代码。因此实际上向量表中针对每一种异常的每一个表项都是一句跳转指令或者是使用ldr指令向PC寄存器写入新值。

------------------------------------------arch/arm/kernel/entry-armv.S
    .globl  __vectors_start
 __vectors_start:
  ARM(  swi SYS_ERROR0  )
  THUMB(    svc #0      )
  THUMB(    nop         )
  W(b)    vector_und + stubs_offset        /* 未定义指令 */
  W(ldr)  pc, .LCvswi + stubs_offset /* 软件中断SWI,系统调用 */
  W(b)    vector_pabt + stubs_offset       /* 指令预取中止 */
  W(b)    vector_dabt + stubs_offset       /* 数据访问中止 */
  W(b)    vector_addrexcptn + stubs_offset /* 保留 */
  W(b)    vector_irq + stubs_offset        /* 外部中断模式 */
  W(b)    vector_fiq + stubs_offset        /* 快速中断模式 */

  .globl    __vectors_end
 __vectors_end:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

初始化大蓝图

下面以海思的Hi3535为例展示arm体系中断初始化的主要流程。
技术分享图片

以上是关于LINUX-内核-中断分析-中断向量表-arm的主要内容,如果未能解决你的问题,请参考以下文章

SylixOS 中断流程

SylixOS 中断流程

ARM中断向量表与响应流程

ARM中的异常中断是如何实现进入中断程序的,比如如何进入...

Linux中断 - ARM中断处理过程

linux源码分析