Chinaunix首页 | 论坛 | 博客
  • 博客访问: 12513
  • 博文数量: 2
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 32
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-26 16:41
文章分类
文章存档

2014年(2)

我的朋友

分类: LINUX

2014-02-28 23:14:26

根据各种网上的资料,自己做个理解总结。

说起中断首先讲到的就是中断向量表:
arch/arm/kernel/entry-armv.S中的一个表,表内每一项都指示了相应类型中断的入口地址:
__vectors_start:
 ARM( swi SYS_ERROR0 )
 THUMB( svc #0 )
 THUMB( nop )
W(b) vector_und + stubs_offset---> 未定义指令异常
W(ldr) pc, .LCvswi + stubs_offset--->系统调用
W(b) vector_pabt + stubs_offset--->指令预取终止异常
W(b) vector_dabt + stubs_offset--->Data abort异常
W(b) vector_addrexcptn + stubs_offset--->Address exception地址异常,说是32位上不会发生的
W(b) vector_irq + stubs_offset--->普通中断
W(b) vector_fiq + stubs_offset--->外部快速中断

vector_und ,LCvswi , vector_dabt ,vector_addrexcptn vector_irq vector_fiq 的定义的话我们同样可以在arch/arm/kernel/entry-armv.S中找到,大概内容都差不多

如:
vector_fiq:
disable_fiq
subs pc, lr, #4
那就是啥都没做,disable一下就回去了。

如:
.globl __stubs_start
__stubs_start:

/*
 * Interrupt dispatcher
 */
vector_stub irq, IRQ_MODE, 4---》vector_stub 是一个宏,接受参数后将第一个字段和vector拼接,也就是说这里是vector_irq:....当然宏展开还有其他内容么

.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
这就是一个中断分派表了。中断来了之后,首先是去找__stubs_start,然后根据中断类型以及当时的工具模式找到对应的entry,看到这里只定义了__irq_usr 和__irq_svc。

我们拿
__irq_svc来说,就是这个中断来的时候当前CPU在执行内核太代码啦。
.align 5
__irq_svc:
svc_entry


#ifdef CONFIG_PREEMPT
get_thread_info tsk
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
str r8, [tsk, #TI_PREEMPT] @ restore preempt count
ldr r0, [tsk, #TI_FLAGS] @ get flags
teq r8, #0 @ if preempt count != 0
movne r0, #0 @ force flags to 0
tst r0, #_TIF_NEED_RESCHED
blne svc_preempt
#endif
ldr r4, [sp, #S_PSR] @ irqs are already disabled
#ifdef CONFIG_TRACE_IRQFLAGS
tst r4, #PSR_I_BIT
bleq trace_hardirqs_on
#endif
svc_exit r4 @ return from exception
 UNWIND(.fnend )
ENDPROC(__irq_svc)
前后反正就是中断进出过程中搞来搞去的一些事,高亮的才是核心
irq_handle其实他就是个宏,那么它只做什么的呢,我们看它的代码

.macro irq_handler
get_irqnr_preamble r5, lr
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrne lr, BSYM(1b)
bne asm_do_IRQ

#ifdef CONFIG_SMP
/*
* XXX
*
* this macro assumes that irqstat (r6) and base (r5) are
* preserved from get_irqnr_and_base above
*/
test_for_ipi r0, r6, r5, lr
movne r0, sp
adrne lr, BSYM(1b)
bne do_IPI

#ifdef CONFIG_LOCAL_TIMERS
test_for_ltirq r0, r6, r5, lr
movne r0, sp
adrne lr, BSYM(1b)
bne do_local_timer
#endif
#endif
.endm


红色大字大家就熟悉了吧,终于到C代码了。这样,我们就知道怎么的中断就搞到那几个中断处理函数上来了。


这个表我们讲完了。现在有个疑问,这个表是放什么地方的呢?

我们不管内核把他放在了zImage的什么地方了,(只要能找到代码在什么地方就好了)因为那没有意义,还是要看最终在什么地方,这就要看这个函数了:
setup_arch()-》early_trap_init

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);
....
}
这里三句memcpy起到了关键作用,分别把中断中出现过的几个部件放到了想要的位置,这个位置的起始点就是vectors,这个值是在这个函数一开始的地方赋值的

unsigned long vectors = CONFIG_VECTORS_BASE;

说明了一点,这个地址是可以配的,根据soc的情况不同可能不同,但大量的文件都把这个值设为0xffff0000,这个原因么,不知道。
阅读(1485) | 评论(0) | 转发(1) |
0

上一篇:没有了

下一篇:一个arm学习的很系统知识的网站

给主人留下些什么吧!~~