在IA-32e模式下,一旦发生中断和异常,将导致处理器进入64位模式,清楚这一点很重要。换句话说,在IA-32e模式下,中断和异常的处理程序必须是64位代码。
在IA-32e模式下,中断描述符表IDT内必须包含64位的中断门和陷阱门,但不包括任务门,因为IA-32e模式不支持硬件任务切换。在IA-32e模式下,要引用中断描述符表内的中断门和陷阱门,需要用中断号乘以16,而不是像传统模式下那样乘以8。
在IA-32e模式下,对中断和异常的处理是在64位模式下进行的,所以处理器在保护现场时的每个压栈操作都是按8字节进行。
和传统模式一样,在IA-32e模式下,因中断和异常而转入中断处理程序时,如果特权级发生变化,则需要切换栈。
在传统模式下,只有在特权级发生变化时,处理器才会压入段寄存器SS和栈指针寄存器,但是在IA-32e模式下,是无条件压入SS和RSP的。
在传统模式下,任务状态段TSS主要用于任务切换。当然,如果因中断或者系统调用而发生了特权级之间的转移,还要切换栈。新栈的段选择子和栈指针是从当前任务的任务状态段TSS中获取的。
如图2-34所示,这是传统模式下的任务状态段TSS,当中断和异常发生时,如果特权级发生了改变,则从当前任务的TSS中选择一个适当的栈段选择子与栈指针,TSS中的其他内容用于硬件任务切换。
在IA-32e模式下,不再支持硬件任务切换,但TSS依然有用,依然要用于中断和异常的处理及系统调用。同时,TSS的布局发生了变化,大部分内容被废弃。
如图2-35所示,在IA-32e模式下,原先的三个特权级栈指针被保留,但扩展到64位,分别是RSP0、RSP1和RSP2,取消了三个栈段选择子。这是因为在IA-32e模式下,中断和异常处理程序必须是64位的,在64位模式下,不再使用栈段寄存器SS,栈基地址始终为0。
如果发生了栈的切换,需要根据目标特权级从RSP0、RSP1和RSP2选择一个栈指针。但是还可以用另外一种机制来选择栈指针,这种新的机制叫作中断栈表(Interrupt Stack Table,IST)。引入中断栈表的基本想法是,为一些特殊的中断,比如不可屏蔽中断NMI、双重错异常等提供可以信任的栈。
在TSS中,一共定义了7个可以使用的中断栈表指针,分别是IST1到IST7。如果中断栈表机制是开启的,则因中断和异常而发生栈切换时,可以从中选择一个作为栈指针。
图2-34 保护模式下的任务状态段TSS
图2-35 IA-32e模式下的任务状态段TSS