uclinux-2008r1-rc8(bf561)的中断处理(4):_evt_ivhw
来源:互联网 发布:汪涵人设崩 知乎 编辑:程序博客网 时间:2024/04/30 21:39
这部分代码在arch/blackfin/mach-common/interrupt.S中,用于处理Hardware Error Interrupt,VDSP文档对此错误的解释是:
The Hardware Error Interrupt is generated by:
Bus parity errors
Internal error conditions within the core, such as Performance Monitor overflow
Peripheral errors
Bus timeout errors
看看uclinux的处理:
/* interrupt routine for ivhw - 5 */
ENTRY(_evt_ivhw)
SAVE_ALL_SYS
//# We are going to dump something out, so make sure we print IPEND properly
p2.l = lo(IPEND);
p2.h = hi(IPEND);
r0 = [p2];
[sp + PT_IPEND] = r0;
/* set the EXCAUSE to HWERR for trap_c */
r0 = [sp + PT_SEQSTAT];
R1.L = LO(VEC_HWERR);
R1.H = HI(VEC_HWERR);
R0 = R0 | R1;
[sp + PT_SEQSTAT] = R0;
r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
SP += -12;
call _trap_c;
SP += 12;
call _ret_from_exception;
.Lcommon_restore_all_sys:
RESTORE_ALL_SYS
rti;
ENDPROC(_evt_ivhw)
在这里,SAVE_ALL_SYS将系统的大部分寄存器的值都压到栈中,且入栈的顺序是和pt_regs这个结构体的成员一一对应的,因此最后可以将此结构体的指针传给函数trap_c。
PT_IPEND和PT_SEQSTAT分别定义了保存IPEND和SEQSTAT这两个寄存器值的成员相应于pt_regs这个结构体的偏移量,因而使用[sp + PT_IPEND]这样的方式可以取得相应寄存器的值。
VEC_HWERR则是定义好的一个常数:
/* The hardware reserves (63) for future use - we use it to tell our
* normal exception handling code we have a hardware error
*/
#define VEC_HWERR (63)
因为出错的原因保存在SEQSTAT寄存器的低5位中,因此通过取或的方式将pt_regs->seqstat的值设置为EXCAUSE,而不是原来的32位整数。
然后调用trap_c进行处理,此函数将决定输出错误信息后返回原位置执行,或者中止执行。
最后调用了_ret_from_exception函数,这个函数的实现在arch/blackfin/mach-common/entry.S中,我们来看看它的实现:
ENTRY(_ret_from_exception)
p2.l = lo(IPEND);
p2.h = hi(IPEND);
csync;
r0 = [p2];
[sp + PT_IPEND] = r0;
_ret_from_exception_1:
r2 = LO(~0x37) (Z);
r0 = r2 & r0;
cc = r0 == 0;
if !cc jump _ret_from_exception_4; /* if not return to user mode, get out */
/* Make sure any pending system call or deferred exception
* return in ILAT for this process to get executed, otherwise
* in case context switch happens, system call of
* first process (i.e in ILAT) will be carried
* forward to the switched process
*/
p2.l = lo(ILAT);
p2.h = hi(ILAT);
r0 = [p2];
r1 = (EVT_IVG14 | EVT_IVG15) (z);
r0 = r0 & r1;
cc = r0 == 0;
if !cc jump _ret_from_exception_5;
/* Set the stack for the current process */
r7 = sp;
r4.l = lo(ALIGN_PAGE_MASK);
r4.h = hi(ALIGN_PAGE_MASK);
r7 = r7 & r4; /* thread_info->flags */
p5 = r7;
r7 = [p5 + TI_FLAGS];
r4.l = lo(_TIF_WORK_MASK);
r4.h = hi(_TIF_WORK_MASK);
r7 = r7 & r4;
cc = r7 == 0;
if cc jump _ret_from_exception_4;
p0.l = lo(EVT15);
p0.h = hi(EVT15);
p1.l = _schedule_and_signal;
p1.h = _schedule_and_signal;
[p0] = p1;
csync;
raise 15; /* raise evt14 to do signal or reschedule */
_ret_from_exception_4:
r0 = syscfg;
bitclr(r0, 0);
syscfg = r0;
_ret_from_exception_5:
rts;
ENDPROC(_ret_from_exception)
在此入口的开始,直接取IPEND寄存器的值判断0x37指定的掩码位置的状态,如果为1则直接跳转到_ret_from_exception_4,查一下IPEND这几位的意义:
The IPEND register keeps track of all currently nested interrupts (see Figure 4-12). Each bit in IPEND indicates that the corresponding interrupt is currently active or nested at some level. It may be read in Supervisor mode, but not written. The IPEND[4] bit is used by the Event Controller to temporarily disable interrupts on entry and exit to an interrupt service routine.
When an event is processed, the corresponding bit in IPEND is set. The least significant bit in IPEND that is currently set indicates the interrupt that is currently being serviced. At any given time, IPEND holds the current status of all nested events.
0:EMU中断
1:RST中断
2:NMI
4:Global Interrupt Disable
5:IVHW
当发生上述状况时,内核直接跳转到_ret_from_exception_4。
_ret_from_exception_4:
r0 = syscfg;
bitclr(r0, 0);
syscfg = r0;
_ret_from_exception_5:
rts;
在这里syscfg的最低位表示Supervisor Single Step,如果置1,则每执行一条指令将中断一次,似乎是用于程序调试的,但是不是很明白。
- uclinux-2008r1-rc8(bf561)的中断处理(4):_evt_ivhw
- uclinux-2008r1-rc8(bf561)的中断处理(2):evt_nmi
- uclinux-2008r1-rc8(bf561)的中断处理(3):trap
- uclinux-2008r1-rc8(bf561)的中断处理:全文
- 重读uclinux-2008r1-rc8(bf561)内核的中断处理(4):特定处理函数
- 重读uclinux-2008r1-rc8(bf561)内核的中断处理(3):中断处理流程
- uclinux-2008r1-rc8(bf561)的中断处理(1):中断入口设置
- uclinux-2008r1-rc8(bf561)的中断处理(8):中断描述
- 重读uclinux-2008r1-rc8(bf561)内核的中断处理(2):中断配置
- uclinux-2008r1-rc8(bf561)的中断处理(5):evt_timer
- uclinux-2008r1-rc8(bf561)的中断处理(6):__common_int_entry
- uclinux-2008r1-rc8(bf561)的中断处理(7):evt_evt7-13
- uclinux-2008r1-rc8(bf561)的中断处理(9):irq_chip
- uclinux-2008r1-rc8(bf561)的中断处理(10):ivg_table
- uclinux-2008r1-rc8(bf561)的中断处理(11):do_irq
- 再读uclinux-2008r1-rc8(bf561)内核的中断处理(1):数据结构
- uclinux-2008R1-RC8(bf561)到VDSP5的移植(40):中断优先级
- uclinux-2008r1-rc8(bf561)内核的console(1):数据结构
- 在Oracle中使用序列创建唯一流水号
- 黑客开发出思科路由器后门
- 关于在VISIO中进行数据库建模时如何显示字段类型,以及注释的
- 我爱你中国,我爱你中华民族
- 自己写的操作 RMS类
- uclinux-2008r1-rc8(bf561)的中断处理(4):_evt_ivhw
- 2008年17款远程控制软件大比拼
- C#(.NET)生成高质量(清晰)缩略图
- 最新 Jazz 入门文档
- 用sendredirect还是forward?页面跳转续~
- 计算二值图像的重心
- C#中ref和out的使用小结
- DB2 V9.5 备份还原增强特性,第1部分
- 在Oracle中实现各种日期处理