【问题标题】:Does CR3 change when an interrupt is fired on x86 machines?在 x86 机器上触发中断时 CR3 会改变吗?
【发布时间】:2015-09-16 02:35:57
【问题描述】:

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

【问题讨论】:

  • wiki.osdev.org/Context_Switching 没有提及任何相关内容。你有理由怀疑它正在改变吗?也许在可以单步执行的 VM 中尝试您的代码。
  • 你的意思是硬件会改变它还是操作系统通常会这样做?
  • 我同意——用一些示例代码测试它可能是最好(最简单)的检查方法。如果您不知道该怎么做,那将是另一个问题:)

标签: assembly x86 paging intel interrupt


【解决方案1】:

当发生中断或异常时,处理器会保存以下状态(请参阅英特尔 64 和 IA-32 架构软件开发人员手册第 3 卷(3A、3B 和 3C):系统编程指南,6.12。 1.) :

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

    EFLAGS, CS, EIP
    
  • 另一方面,如果 DPL 低于 CPL,则 除了上述寄存器SSESP 寄存器被推入另一个堆栈(在TSS)。

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

这意味着中断处理程序的代码必须在可能发生中断的每个虚拟地址空间中都可以访问。正因为如此,并且因为这样的处理程序通常从内核调用附加代码,所以大多数内核将它们自己的大部分代码和数据映射到每个进程的地址空间,从而减少了每个进程的可用内存空间。通常这个映射建立在可寻址内存空间的“上端”,大约 3GB。

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


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

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

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

[上面提到的Intel手册,7.2.3]

【讨论】:

  • 好答案,但要吹毛求疵:我相信 64 位 CPU 确实支持任务切换,只是不支持 64 位模式。
  • 首先感谢本专栏中的答案。 OSdev 站点中没有此信息。
【解决方案2】:

可能。您可能有一个专门用于中断服务的任务。它可能具有与其中断的任务不同的 CR3 值(在任务状态段 (AKA TSS) 中有一个用于 CR3 的字段)。因此,您最终可能会在每次中断(即每次任务切换时)切换 CR3 两次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2016-03-07
    相关资源
    最近更新 更多