pStackTop参数由异常服务程序的第一部分传入,指向异常发生后的栈顶。在IA32架构里,发生异常时堆栈有4种状态,如图1所示。
图1 异常发生时堆栈状态
(a)是没有变换特权级和没有出错码的情形;(b)是没有变换特权级有出错码的情形;(c)是变换特权级和没有出错码的内层堆栈的情形。(d)是变换特权级和有出错码的内层堆栈情形。
对于本文而言,驱动是在内核层运行,发生异常时不会有特权级转换,所以(c),(d)两种情况不用考虑,而对于GP而言,是肯定有错误码产生的,所以只需要处理状态(b)格式的堆栈信息。把异常处理程序的入口地址写入堆栈中保存EIP的位置,然后清除错误码,再用IRETD或RETF指令返回就能转移到异常处理程序运行了。所以在第二段异常服务程序里修改返回地址是用:
pStackTop[1]=uResumeEntry;
而不是:
pStackTop[0]=uResumeEntry;
下一个需要注意的是堆栈指针的恢复。
对于如下状况,代码始终在同一个函数内运行,当然可以不考虑恢复堆栈指针:
int foo()
{
int a=1;
int b=2;
int *p=0;
BEGIN_EXCEPT_PROTECT()
{
*p=a+b;
}
EXCEPT_HANDLER()
{
printk(KERN_ERR”Invalid pointer!\n”);
}
END_EXCEPT_PROTECT()
return 0;
}
|