Chinaunix首页 | 论坛 | 博客
  • 博客访问: 647741
  • 博文数量: 156
  • 博客积分: 4833
  • 博客等级: 上校
  • 技术积分: 1554
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-21 19:36
文章分类

全部博文(156)

文章存档

2016年(2)

2013年(1)

2012年(13)

2011年(30)

2010年(46)

2009年(29)

2008年(23)

2007年(12)

分类: BSD

2012-03-31 15:25:51

Call tree for interrupt:

 (exception.S)VECTOR(Mip***ception, unknown)->machExceptionTable->MipsUserIntr/MipsKernIntr->cpu_intr


Linux:

trap_init():loop call->set_vi_handler()->set_vi_srs_handler->msc_bind_eic_interrupt

set_vi_srs_handler:

   b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING);   

   vec_start = except_vec_vi 

   memcpy(b, vec_start, handler_len);


BUILD_ROLLBACK_PROLOGUE except_vec_vi
NESTED(except_vec_vi, 0, sp)
    SAVE_SOME
    SAVE_AT
    .set    push
    .set    noreorder
FEXPORT(except_vec_vi_lui)
    lui    v0, 0        /* Patched */
    j    except_vec_vi_handler
FEXPORT(except_vec_vi_ori)
     ori    v0, 0        /* Patched */
    .set    pop
    END(except_vec_vi)
EXPORT(except_vec_vi_end)


具体的异常向量初始化代码参见arch/mips/kernel/traps.c。大概执行流程如下:
1、计算所有外部中断向量的size(个数xIntCtl[VS])
2、通过size计算ebase,并将结果写入EBASE寄存器
3、循环调用set_vi_handler初始化外部中断向量(根据VEIC或者VINT支持的外部中断个数决定循环次数)。handler地址如果是 NULL,则会指向do_default_vi。细节还由是否支持shadow寄存器决定。do_default_vi就是产生一个kernel panic。

set_vi_handler就是调用set_vi_srs_handler,其中srs参数为0,表示目前没有支持shadow寄存器。set_vi_srs_handler流程如下:
1、获得中断handler的地址,如果是NULL则使用do_default_vi
2、计算对应中断向量的基址(ebase+x200+nxIntCtl[VS])
3、计算中断vector的长度(except_vec_vi_end - vec_start)。vec_start等于except_vec_vi
4、copy从vec_start开始,handler长度的代码到该中断向量的基址。目前copy的是默认代码
5、计算handler中lui和ori指令的地址,修改这两条指令的内容,使得它们load真正的中断handler的地址到v0寄存器中
6、flush icache

注意,这里面有一个技巧,就是修改默认的lui和ori指令。默认的行为是load地址0到v0中,修改后就是load真正的中断handler到v0中。

  w = (u32 *)(b + lui_offset);
 *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
  w = (u32 *)(b + ori_offset);
 *w = (*w & 0xffff0000) | ((u32)handler & 0xffff);
  local_flush_icache_range((unsigned long)b,(unsigned long)(b+handler_len));

最终每一个中断vector都是这个样子:
保存部分上下文(包括切换堆栈)
load真正的中断handler到v0中
跳转到except_vec_vi_handler
在except_vec_vi_handler中,保存剩下的上下文,load ret_from_irq到ra中
jr v0跳转到真正的中断handler处理中断


阅读(1079) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~