
本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作。具体整个处理过程分成三个步骤来描述:
1、第二章描述了中断处理的准备过程
2、第三章描述了当发生中的时候,ARM硬件的行为
3、第四章描述了ARM的中断进入过程
4、第五章描述了ARM的中断退出过程
本文涉及的代码来自3.14内核。另外,本文注意描述ARM指令集的内容,有些source code为了简短一些,删除了THUMB相关的代码,除此之外,有些debug相关的内容也会删除。
二、中断处理的准备过程
1、中断模式的stack准备
ARM处理器有多种processor mode,例如user mode(用户空间的AP所处于的模式)、supervisor mode(即SVC mode,大部分的内核态代码都处于这种mode)、IRQ mode(发生中断后,处理器会切入到该mode)等。对于linux kernel,其中断处理处理过程中,ARM 处理器大部分都是处于SVC mode。但是,实际上产生中断的时候,ARM处理器实际上是进入IRQ mode,因此在进入真正的IRQ异常处理之前会有一小段IRQ mode的操作,之后会进入SVC mode进行真正的IRQ异常处理。由于IRQ mode只是一个过度,因此IRQ mode的栈很小,只有12个字节,具体如下:
struct stack {
u32 irq[3];
u32 abt[3];
u32 und[3];
} ____cacheline_aligned;
static struct stack stacks[NR_CPUS];
除了irq mode,linux kernel在处理abt mode(当发生data abort exception或者prefetch abort exception的时候进入的模式)和und mode(处理器遇到一个未定义的指令的时候进入的异常模式)的时候也是采用了相同的策略。也就是经过一个简短的abt或者und mode之后,stack切换到svc mode的栈上,这个栈就是发生异常那个时间点current thread的内核栈。anyway,在irq mode和svc mode之间总是需要一个stack保存数据,这就是中断模式的stack,系统初始化的时候,cpu_init函数中会进行中断模式stack的设定:
void notrace cpu_init(void)
{
unsigned int cpu = smp_processor_id();------获取CPU ID
struct stack *stk = &stacks[cpu];---------获取该CPU对于的irq abt和und的stack指针
……
#ifdef CONFIG_THUMB2_KERNEL
#define PLC "r"------Thumb-2下,msr指令不允许使用立即数,只能使用寄存器。
#else
#define PLC "I"
#endif
__asm__ (
"msr cpsr_c, %1\n\t"------让CPU进入IRQ mode
"add r14, %0, %2\n\t"------r14寄存器保存stk->irq
"mov sp, r14\n\t"--------设定IRQ mode的stack为stk->irq
"msr cpsr_c, %3\n\t"
"add r14, %0, %4\n\t"
"mov sp, r14\n\t"--------设定abt mode的stack为stk->abt
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-76601-1.html
反向营销