中断处理中的save_all、restore_all和iret
A.指令iret
指令iret(interrupt return)中断返回,其作用是从中断中恢复中断前的状态,具体作用有如下三点:
1.恢复IP(instruction pointer)
2.恢复CS(code segment)
3.恢复中断前的PSW(program status word),即恢复中断前的标志寄存器的状态。以上操作按顺进行。
B.保存现场的宏SAVE_ALL
在中断发生前夕,要把所有相关寄存器的内容都保存在堆栈中,这是通过SAVE_ALL宏完成的:
#define SAVE_ALL cld; pushl %es; pushl %ds; pushl %eax; pushl %ebp; pushl %edi; pushl %esi; pushl %edx; pushl %ecx; pushl %ebx; movl $(__KERNEL_DS),%edx; movl %edx,%ds; movl %edx,%es; |
该宏执行以后,堆栈内容如图3.6所示。把这个宏与图3.5 结合起来就很容易理解图3.6,在此对该宏再给予解释:
· CPU在进入中断处理程序时自动将用户栈指针(如果更换堆栈)、EFLAGS寄存器及返回地址一同压入堆栈。
· 段寄存器DS和ES原来的内容入栈,然后装入内核数据段描述符__KERNEL_DS(定义为0x18),内核段的DPL为0。
C.恢复现场的宏RESTORE_ALL
当从中断返回时,恢复相关寄存器的内容,这是通过RESTORE_ALL宏完成的:
#define RESTORE_ALL popl %ebx; popl %ecx; popl %edx; popl %esi; popl %edi; popl %ebp; popl %eax; 1: popl %ds; 2: popl %es; addl $4,%esp; 3: iret; |
可以看出,RESTORE_ALL与SAVE_ALL遥相呼应。当执行到iret指令时,内核栈又恢复到刚进入中断门时的状态,并使CPU从中断返回。