分类: LINUX
2012-03-24 11:13:56
一、硬件完成的工作
1、set epc
2、set EXL 表示进入内核模式和禁止中断
3、set cause寄存器;有的异常也需设置BadVaddr寄存器
4、跳到异常入口执行
二、软件工作
1、区分不同的异常,Cause寄存器的ExcCode域
2、准备空间保存寄存器状态,由SAVE_ALL宏完成
说明几点:
1)、获得空间方法如下:
若是用户态 --> 内核态,则 k0 = sp, sp = *kernelsp - PT_SIZE,store k0, PT_R29(sp),保存其它寄存器。
若是内核态 --> 内核态,直接 k0 = sp, sp = sp - PT_SIZE,store k0, PT_R29(sp),然后保存其它寄存器。
获得空间大小是PT_SIZE,寄存器按照特定的方式保存,形成一个 struct pt_regs 结构,传递给子函数。
2)、在SAVE_ALL宏中,保存了epc,和status,cause寄存器,这样就可以异常嵌套
3、调用子函数(sp作为参数),做任何你想做的事。
4、从子函数返回到ret_from_exception宏,ret_from_exception宏调用RESTORE_ALL宏完成寄存器状态的回复,最后恢复sp寄存器,即恢复到sp+PT_SIZE处。
5、eret,同时完成清除SR(EXL)位,把控制权交给epc指向的指令。
三、疑问探究
C语言中主函数中调用子函数,栈的处理过程:
1、进入子函数的时候,编译器完成sp - size
2、子函数执行过程中,定义的变量会放到栈上,如果用到s0-s7寄存器,编译器会把s0-s7的值保存到栈上
3、子函数返回时后,编译器先恢复s0-s7寄存器,再将sp + 适当的size到进入子函数时sp处。