在x86机器上触发中断时,CR3是否会更改?

Bil*_*her 4 paging x86 assembly intel interrupt

在x86机器上,触发中断时,CR3是否会更改(不仅仅是EIP的值)?

Dan*_*our 5

发生中断或异常时,处理器将保存以下状态(请参阅《Intel 64和IA-32体系结构软件开发人员手册》第3卷(3A,3B和3C):《系统编程指南》 6.12.1。):

  • 如果DPL(目标特权级别)等于CPL(当前特权级别),则在将控制权交给中断处理程序之前,以下寄存器以及可能的错误代码将被推送到当前堆栈:

    EFLAGS, CS, EIP
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果在另一方面,DPL比CPL下,则附加到上述寄存器SSESP寄存器被压入到另一个栈(在TSS指定)。

由于处理器必须使操作系统能够恢复被中断进程的状态,因此处理器无法自行更改上述寄存器以外的任何内容。因此,CR3改变。

这意味着必须在可能发生中断的每个虚拟地址空间中访问中断处理程序的代码。因此,并且由于这样的处理程序通常从内核调用其他代码,因此大多数内核将自己的代码和数据的很大一部分映射到每个进程的地址空间中,从而减少了每个进程的可用内存空间。通常,此映射建立在可寻址内存空间的“高端”(大约3GB)上。

在我很早以前写的一个爱好内核中,我采取了尝试使进程的地址空间保持尽可能大的方法,因此,我只映射了中断处理程序以及一些代码和所需的数据,以更改为专用的内核地址。实际将中断处理到进程的地址空间之前的空间。事实证明,这相当困难,只有一个可疑的好处,这就是为什么我认为大多数系统都不采用这种方法。


如果在中断描述符表中有一个任务门描述符,则在触发该中断时,将发生硬件任务切换,将处理器的状态保存到当前TSS中,并从任务门引用的TSS中加载状态。这包括加载CR3寄存器的值,从而更改虚拟地址空间(请参见上述手册的7.3。)。

但是,实际上很难做到这一点,因为顾名思义,硬件任务切换高度依赖于硬件,因此仅在x86 CPU上受支持。由于很少使用该功能,因此即使相应的64位CPU也不再支持该功能:

在64位模式下,不支持任务切换[..]

[上述英特尔手册,第7.2.3节]