arm中断异常时cpsr显示都是svc模式?
有个疑问,在中断处理中,打印cpsr发现mode=0x13 处于svc mode。
data abort处理中,打印cpsr发现mode=0x13
看来kernel只用了user mode和svc mode。
1. 如果是这样的,那么怎样实现只用两种mode的呢?
2. 如果是这样的,那么中断异常处理中(从usr mode到svc mode), sp是从usr sp自动切换到svc sp的,硬件自动处理吗,从文档上没有看到相关部分。
blake326 发表于 2013-07-11 09:11 static/image/common/back.gif
有个疑问,
在中断处理中,打印cpsr发现mode=0x13 处于svc mode。
data abort处理中,打印cpsr发现mode=0 ...
个人认为,有内核态,用户态就够用了。
对于异常和中断,应该有不同。通常中断由硬件处理,异常就不一定。异常/系统调用只是提供从用户态到内核态的方法,可以软件具体实现。 中断异常时是切换到了svc模式下去处理的
在irq模式下,只是将lr r0 spsr入栈,irq模式的栈size只有3个word,刚好够放这三个寄存器
然后将irq模式的栈基地址填到r0中,然后切换到svc模式
在svc模式下通过r0就可以取出lr r0 spsr,然后将lr和r0和r1-sp都压入svc模式的栈(此时是借用的被中断的线程的栈),将spsr写入svc模式的spsr
然后就进行中断处理
处理完之后,就可以直接从svc模式返回到发生中断之前的模式 回复 2# daniel_11
嵌套中断的要求: 回复 3# arm-linux-gcc
》》》》》》》》》》》
然后将irq模式的栈基地址填到r0中,然后切换到svc模式
》》》》》》》》》》
你的意思是发生中断后,会进入irq模式,然后保存了r0,lr,spsr之后,kernel就立刻切换到了svc模式?那么这个切换的动作在哪里的,svc_entry? 我看代码没有找到这个动作。
回复 4# smalloc
那么你的意思是在中断处理中,arm处于irq mode吗?
但是我打出来的都是arm处于svc mode,不过我的板子用了vlx虚拟机,可能有影响。 本帖最后由 arm-linux-gcc 于 2013-07-19 18:55 编辑
回复 6# blake326
从irq到svc的切换过程如下:
.macro vector_stub, name, mode, correction=0
.align 5
vector_\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, @ save spsr
@
@ Prepare for SVC32 mode.IRQs remain disabled.
@
mrs r0, cpsr
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0
以上3句是将spsr中的模式位改为svc,注意这里只是修改了irq的spsr,还未切换状态
@
@ the branch table must immediately follow this code
@
and lr, lr, #0x0f 取出spsr中的,这里不用取M4,因为M4是表示26位还是32位寻址的,如果只想知道模式的话,取就够了
THUMB( adr r0, 1f )
THUMB( ldr lr, )
mov r0, sp 将irq模式的栈基地址填到r0,以后在svc_entry中可以通过r0去读取irq的栈
ARM( ldr lr, ) 直接将乘以4再加上pc就可以计算出入口(因为一个entry占4个字节),结果为__irq_usr或__irq_svc,具体是usr还是svc要看发生中断之前是什么模式
movs pc, lr @ branch to handler in SVC mode 跳进入口(__irq_usr或__irq_svc),同时做模式切换(mov带了s,就会给pc赋值的同时将用spsr去填cpsr)
ENDPROC(vector_\name)
vector_stub irq, IRQ_MODE, 4 宏vector_\name展开,展开之后的结果,使得上述 ARM(ldr lr,)处的pc值就是下面的.long __irq_usr处的地址
.long __irq_usr @0(USR_26 / USR_32) 为0
.long __irq_invalid @1(FIQ_26 / FIQ_32)
.long __irq_invalid @2(IRQ_26 / IRQ_32)
.long __irq_svc @3(SVC_26 / SVC_32) 为3
.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
其中一些是占位符,这里刚好16个,对应了的所有可能取值,所以entry的地址就可以用很快的算出来,之所以弄16个entry,是因为在各种模式的取值中并不是连续的
你在svc_entry是看不到模式切换的,因为在进入svc_entry之前就已经做了,你可以去直接看irq的栈,可以查看以下数据结构
arch/arm/kernel/setup.c,他们分别是irq abt und模式的栈
struct stack {
u32 irq;
u32 abt;
u32 und;
} ____cacheline_aligned;
写的挺乱的,不知道说清楚没,向来不善于写这类东西
本帖最后由 arm-linux-gcc 于 2013-07-19 18:59 编辑
另贴一个CPSR的模式位以便对比看
M4 M3 M2 M1 M0
0 0 0 0 0 User26 模式
0 0 0 0 1 FIQ26 模式
0 0 0 1 0 IRQ26 模式
0 0 0 1 1 SVC26 模式
1 0 0 0 0 User 模式
1 0 0 0 1 FIQ 模式
1 0 0 1 0 IRQ 模式
1 0 0 1 1 SVC 模式
1 0 1 1 1 ABT 模式
1 1 0 1 1 UND 模式
回复 7# arm-linux-gcc
》》》》》》
movs pc, lr @ branch to handler in SVC mode
谢谢。这段代码我也看过几遍,原来是在这句切到svc mode的。没有注意到 movs指令。 为何irq模式的栈只有3个word,irq的sp是在哪赋值的?多谢
回复 3# arm-linux-gcc
页:
[1]
2