MIPS 74K内核Interrupt Compatibility Mode处理方式

来源:互联网 发布:广数螺纹编程 编辑:程序博客网 时间:2024/05/17 04:03

     这是一个默认的中断处理模式,CPU收到一启动异常的时候,内核进入这种模式。在这种模式中,中断是非向量的,中断会被分派到异常向量偏移0x180的位置处(Cause IV=0),或者0x200的位置(Cause IV = 1).当以下的任何一个条件成立时,这种模式有效:

    Cause IV=0

    Status BEV=1

    IntCtl VS =0(当VI模式不存在或者禁止时)

compatibility mode的中断处理程序例子:
/*
* 解设:
* - CauseIV = 1 (如果为0,当中断到达这里之前,这个中断不会被这个处理程序处理)
* - GPRs k0 和k1 寄存器可以被使用(因为这这种模式里没有提供shadow 寄存器)
* - 优先级设置为:IP7..IP0 (HW5..HW0, SW1..SW0)
*
* 位置: Offset 0x200 */


IVexception:
    mfc0 k0, C0_Cause /* Read Cause register for IP bits */
    mfc0 k1, C0_Status /* and Status register for IM bits */
    andi k0, k0, M_CauseIM /* Keep only IP bits from Cause */
    and k0, k0, k1 /* and mask with IM bits */
    beq k0, zero, Dismiss /* no bits set - spurious interrupt */
    clz k0, k0 /* Find first bit set, IP7..IP0; k0 = 16..23 */
    xori k0, k0, 0x17 /* 16..23 => 7..0 */
    sll k0, k0, VS /* Shift to emulate software IntCtlVS */
    la k1, VectorBase /* Get base of 8 interrupt vectors */
    addu k0, k0, k1 /* Compute target from base and offset */
    jr k0 /* Jump to specific exception routine */
    nop


/*每一个中断处理程序都会处理一个特定的中断,类似与VI或者EIC这些中断模式,

由于每一种中断都会有一个自己的中断信号,他们有自己的中断标志进行识别,

如果多个中断使用同一个中断信号,每一个中断处理程序都需要判断实际中断源,

通过优先级高低来判断。*/


SimpleInterrupt:
/*这里需要清除中断,有一些寄存器需要保存或者恢复,之后使用eret指令返回被中断的代码中*/
eret /* Return to interrupted code */


NestedException:

/*对于嵌套中断,通常需要保存EPC和状态寄存器,保存GPRs,通过IM位禁止当前中断来避免进入中断死循环,

设置处理器进入kernel模式,重新允许中断,下面是简单的例子代码*/


    mfc0 k0, C0_EPC /* Get restart address */
    sw k0, EPCSave /* Save in memory */
    mfc0 k0, C0_Status /* Get Status value */
    sw k0, StatusSave /* Save in memory */
    li k1, ~IMbitsToClear /* Get IM bits to clear for this interrupt */
    /* this must include at least the IM bit */
    /* for the current interrupt, and may include */
    /* others */
    and k0, k0, k1 /* Clear bits in copy of Status */
    ins k0, zero, S_StatusEXL, (W_StatusKSU+W_StatusERL+W_StatusEXL)
    /* Clear KSU, ERL, EXL bits in k0 */   
    mtc0 k0, C0_Status /* Modify mask, switch to kernel mode, */


/* re-enable interrupts */
/*
* Process interrupt here, including clearing device interrupt.
* In some environments this may be done with a thread running in
* kernel or user mode. Such an environment is well beyond the scope of
* this example.
*/

/*这里进行中断处理*/

/*完成处理之后,重新允许中断*/
/*
* To complete interrupt processing, the saved values must be restored
* and the original interrupted code restarted.
*/
    di /* Disable interrupts - may not be required */
    lw k0, StatusSave /* Get saved Status (including EXL set) */
    l k1, EPCSave /* and EPC */
    mtc0 k0, C0_Status /* Restore the original value */
    mtc0 k1, C0_EPC /* and EPC */
    /* Restore GPRs and software state */
    eret /* Dismiss the interrupt */