47

我正在研究英特尔保护模式。我发现调用门、中断门、陷阱门几乎是一样的。事实上,除了 Call Gate 有参数 counter 的字段,而且这 3 个门有不同的 type 字段外,它们在所有其他字段上都是相同的。

至于它们的功能,它们都是用来将代码控制转移到某个代码段内的某个程序中。

我想知道,因为这 3 个门都包含跨权限边界调用所需的信息。为什么我们需要 3 种?1还不够好吗?

感谢您的时间和回复。

更新 1

一个相关问题:何时使用中断门或陷阱门?

更新 2

今天我想到了这个想法:

不同的目的,不同的门,并以不同的 CPU 行为细节进行。比如IF标志处理。

4

3 回答 3

67

门(调用、中断、任务或陷阱)用于跨段转移执行控制。根据目的地的类型和使用的指令,权限级别检查的执行方式不同。

调用门使用 CALL 和 JMP 指令。呼叫门将控制权从较低特权代码转移到较高特权代码。门 DPL 用于确定哪些特权级别可以访问门。调用门已经(或可能已经)逐渐放弃,取而代之的是更快的 SYSENTER/SYSEXIT 机制。

任务门用于硬件多任务支持。硬件任务切换可以自愿发生(CALL/JMP 到任务门描述符),也可以在 NT 标志设置时通过中断或 IRET 发生。它与中断或陷阱门的工作方式相同。据我所知,没有使用任务门,因为内核通常需要在任务切换时完成额外的工作。

中断和陷阱门与任务门一起被称为中断描述符表。它们的工作方式与调用门相同,只是将参数从一个特权堆栈传输到另一个特权堆栈。一个区别是中断门清除 EFLAGS 中的 IF 位,而陷阱门不会。这使它们成为服务硬件中断的理想选择。陷阱广泛用于硬件辅助虚拟化。

有关详细信息,请参阅您感兴趣的处理器的英特尔架构手册。

更新

要回答评论:

区分中断和陷阱的原因有很多。一是范围的不同:中断门指向内核空间(毕竟,管理硬件的是内核),而陷阱是在用户空间中调用的。响应硬件事件调用中断处理程序,而响应 CPU 指令执行陷阱。

举一个简单(但不切实际)的例子来更好地理解为什么中断和陷阱门对待 EFLAGS 的方式不同,考虑一下如果我们在单处理器系统上为硬件事件编写中断处理程序并且在我们无法清除 IF 位时会发生什么正在服务一个。当我们忙于为第一个中断提供服务时,可能会出现第二个中断。然后我们的中断处理程序将在 IH 执行期间的某个随机点被处理器调用。这可能会导致数据损坏、死锁或其他不良魔法。实际上,中断禁用是确保将一系列内核语句视为关键部分的机制之一。

不过,上面的示例假设了可屏蔽中断。无论如何,您不想忽略 NMI。

今天,这在很大程度上也无关紧要。今天,快速和慢速中断处理程序之间几乎没有区别(搜索“快速和慢速处理程序”),中断处理程序可以以嵌套方式执行,SMP 处理器强制将本地中断禁用与自旋锁结合起来,等等。

现在,陷阱门确实用于服务软件中断、异常等。处理器中的页面错误或除以零异常可能是通过陷阱门处理的。使用陷阱门控制程序执行的最简单示例是 INT 3 指令,它用于在调试器中实现断点。在进行虚拟化时,虚拟机管理程序在环 0 中运行,而客户内核通常在环 1 中运行 - 特权代码会因一般异常错误而失败。Witchel 和 Rosenblum 开发了二进制翻译,这基本上是重写指令来模拟它们的效果。发现关键指令并用陷阱代替。然后当陷阱执行时,控制权交给 VMM/管理程序,它负责模拟环 0 中的关键指令。

借助硬件辅助虚拟化,陷阱和模拟技术的使用受到了一定的限制(因为它相当昂贵,尤其是当它是动态的时),但二进制转换的实践仍然被广泛使用

有关更多信息,我建议您查看:

  • Linux 设备驱动程序,第三版(在线提供)
  • 对于二进制翻译,QEMU是一个很好的开始。
  • 关于陷阱和模拟,请查看软件/硬件技术之间的比较。

希望这可以帮助!

于 2010-08-06T15:40:40.763 回答
27

建筑与设计

从保护的角度来看,x86 架构是基于分层环的,根据该环,处理器交付的所有执行空间被划分为四个分层保护域,每个保护域都分配了自己的权限级别。这种设计假设大部分时间代码将在最低特权域中执行,有时会请求来自更高特权安全域的服务,这些服务将抢占特权较低的活动到堆栈上,然后以这样的方式恢复它:对于特权较低的代码,整个抢占将是不可见的。

分级保护域的设计表明,控制不能在不同的安全域之间任意传递。

门是 x86 架构的一项功能,用于将控制权从特权较低的代码段转移到特权较高的代码段,但反之则不然。此外,在较低特权段中的控制将被传递的点可以是任意的,但在更高特权段中的控制将被传递的点是严格指定的。只有通过IRET指令才允许向后控制传递到特权较少的段。在这方面,英特尔软件开发人员手册声称:

较低权限段中的代码模块只能通过称为门的严格控制和保护的接口访问在较高权限段上运行的模块。尝试在不通过保护门且没有足够访问权限的情况下访问更高特权段会导致生成一般保护异常 ( #GP)。

换句话说,门是具有所需访问权限和目标地址的特权域入口点。这样,所有门都是相似的,并且用于几乎相同的目的,并且所有门描述符都包含 DPL 字段,处理器用于控制访问权限。但请注意,仅当调用源是软件、或指令时,处理器才会检查门的 DPL CALLJMPINT在调用源是硬件时绕过此检查。

门的类型

尽管所有门都相似,但它们还是有一些区别,因为最初英特尔工程师认为不同的门将用于不同的目的。

任务门

任务门只能存储在 IDT 和 GDT 中并由INT指令调用。这是一种非常特殊的门,与其他门有很大不同。

最初,英特尔工程师认为他们将通过提供基于 CPU 的任务切换功能来彻底改变多任务处理。他们引入了TSS(Task State Segment),它保存了任务的寄存器状态,可用于硬件任务切换。触发硬件任务切换有两种方式:使用TSS本身和使用Task Gate。要进行硬件任务切换,您可以使用CALLJMP指令。如果我理解正确的话,引入任务门的主要原因是能够触发硬件任务切换以响应中断的到来,因为JMPTSS 选择器无法触发硬件任务切换。

实际上,没有人使用它,也没有人使用硬件上下文切换。实际上,从性能的角度来看,此功能并不是最佳的,使用起来也不方便。例如,考虑到 TSS 只能存储在 GDT 中,并且 GDT 的长度不能超过 8192,从硬件的角度来看,我们不能有超过 8k 的任务。

陷阱门

陷阱门只能存储在 IDT 中并由INT指令调用。它可以被认为是一种基本类型的门。它只是将控制权传递给在更高特权段中的陷阱门描述符中指定的特定地址,仅此而已。主动用于不同目的的陷阱门,可能包括:

  • 系统调用实现(例如用于此目的的 Linux 使用INT 0x80和 Windows 使用)INT 0x2E
  • 异常处理实现(我们没有任何理由在异常情况下禁用中断)。
  • 带有 APIC 的机器上的中断处理实现(我们可以更好地控制内核堆栈)。

中断门

中断门只能存储在 IDT 中并由INT指令调用。它与陷阱门相同,但除此之外,中断门调用还通过自动清除 EFLAGS 寄存器中的 IF 标志来禁止将来接受中断。

中断门积极用于中断处理实现,尤其是在基于 PIC 的机器上。原因是需要控制堆栈深度。PIC 没有中断源优先级功能。因此,默认情况下,PIC 仅禁用已在处理器中处理的中断。但是另一个中断仍然可以在中间到达并抢占中断处理。因此,内核堆栈上可以同时有 15 个中断处理程序。结果,内核开发人员要么被迫显着增加内核堆栈大小,从而导致内存损失,要么准备好面对零星的内核堆栈溢出。中断门可以保证同时只有一个处理程序在内核堆栈上。

呼叫门

调用门可以存储在 GDL 和 LDT 中,并由CALL指令JMP调用。类似于陷阱门,但另外可以将多个参数从用户模式任务堆栈传递到内核模式任务堆栈。传递的参数数量在调用门描述符中指定。

呼叫门从未流行过。有几个原因:

  • 它们可以用陷阱门(奥卡姆剃刀)代替。
  • 他们不是很便携。其他处理器没有这样的特性,这意味着在移植操作系统时支持系统调用的调用门是一种负担,因为必须重写这些调用。
  • 它们不太灵活,因为可以在堆栈之间传递的参数数量是有限的。
  • 从性能的角度来看,它们并不是最佳的。

在 1990 年代末,Intel 和 AMD 为系统调用引入了额外的指令:SYSENTER/ SYSEXIT(Intel)和SYSCALL/ SYSRET(AMD)。与调用门相比,新指令提供了性能优势并已被采用。

概括

我不同意迈克尔·福卡拉基斯的观点。抱歉,除了影响IF标志外,中断和陷阱之间没有任何区别。

  • 理论上,每种类型的门都可以用作指向具有任何级别权限的段的接口。在实践中,在现代操作系统中仅使用中断和陷阱门,在 IDT 中用于系统调用、中断和异常处理,因此它们都用作内核入口点。

  • 任何类型的门(包括中断、陷阱和任务)都可以通过使用INT指令在软件中调用。唯一可以禁止用户模式代码访问特定门的功能是 DPL。例如,当操作系统构建 IDT 时,无论特定门的类型如何,将用于硬件事件处理的门的内核设置 DPL 为 0,并且根据此权限,仅允许从内核空间访问此门(最多运行特权域),但是当它为系统调用设置门时,它将 DPL 设置为 3 以允许从任何代码访问该门。结果,用户模式任务能够使用 DPL = 3 的门进行系统调用,但会在尝试调用键盘中断处理程序时捕获一般保护错误。

  • IDT 中的任何类型的门都可以由硬件调用。人们仅在他们想要实现某些同步的情况下才使用中断门来处理此硬件事件。例如确保内核堆栈溢出是不可能的。例如,我在基于 APIC 的系统上成功地使用陷阱门处理硬件中断。

  • 类似地,IDT 中任何类型的门都可以在软件中调用。对系统调用和异常使用陷阱门的原因很简单。没有任何理由禁用中断。中断禁用是一件坏事,因为它会增加中断处理延迟并增加中断丢失的可能性。因此,没有任何严重的理由,没有人不会禁用它们。

  • 中断处理程序通常以严格的可重入风格编写。这样,中断处理程序通常不共享数据,并且可以透明地相互抢占。即使我们需要在中断处理程序中相互排除对数据的并发访问,我们也可以使用 cli 和 sti 指令仅保护对共享数据的访问。没有任何理由将整个中断处理程序视为关键部分。没有任何理由使用中断门,除了希望防止在基于 PIC 的系统上可能发生的内核堆栈溢出。

陷阱门是内核接口的默认解决方案。如果有一些严重的原因,可以使用中断门代替陷阱门。

于 2012-12-23T09:03:22.827 回答
9

中断门很特殊,因为 IF 标志会自动清除。调用门很特殊,因为它不是通过中断向量激活的。任务门很特别,因为它会自动保存处理器状态。四种不同的行为,有四个名称很方便。

于 2010-08-06T17:23:59.260 回答