【问题标题】:Why does x86 paging have no concept of privilege rings?为什么 x86 分页没有特权环的概念?
【发布时间】:2021-05-09 05:13:52
【问题描述】:

早在 1982 年,当英特尔发布 80286 时,他们在分段方案(环 0-3)中添加了 4 个特权级别,由全局描述符表 (GDT) 和本地描述符表 (LDT) 中的 2 位指定。

在 80386 处理器中,Intel 添加了分页,但令人惊讶的是,它只有 2 个权限级别(主管和用户),由页目录条目 (PDE) 和页表条目 (PTE) 中的单个位指定。

这意味着仅使用分页的操作系统(如大多数现代操作系统)无法从环 1 和 2 的存在中受益,这可能非常有用,例如,对于驱动程序。 (例如,Win9x 经常崩溃,因为它正在将有缺陷的未经检查的驱动程序加载到 ring 0)。

从可移植性的观点来看,ring 1 和 ring 2 的存在是 x86 架构的一个怪癖,可移植操作系统不应该使用它们,因为其他架构只有 2 个权限级别。

但我确信英特尔工程师在 1985 年设计 386 时并没有考虑到其他平台的可移植性。

那么,为什么 Intel 不允许分页具有 4 个特权级别,例如分段?

【问题讨论】:

  • 分页允许4级权限
  • @user123 PDE和PTE只有1位来指定权限。
  • 操作系统使用 2 个级别,因为它们认为支持 4 个级别没有用处。
  • @user123 是的,我是站在 CPU 设计者的角度,而不是操作系统设计者的角度。
  • @user123 保护模式在 90 年代之前没有得到太多使用,当时 386 已经 5 岁了。所以不,当英特尔设计 386 时,他们不可能知道没有人会使用 4 个权限级别。

标签: x86 operating-system cpu-architecture paging privileges


【解决方案1】:

在 386 保护模式和 286 中有四个权限级别(称为环):环 0 具有最高权限(操作系统),环 1 和 2 未广泛使用,环 3 具有最低权限(用户应用程序)。 Ring 0-2 称为“Supervisor”,而 Ring 3 称为“User”。

当前特权级别 (CPL) 由您正在执行的指令的地址决定,根据代码段的描述符特权级别 (DPL)。有关当前权限级别的更多信息,请参阅CPL vs. DPL vs. RPL.

您所指的位如下。它是映射 4MB 页面(或引用页表的 32 位 PDE)的 32 位页面目录条目 (PDE) 中的位 2。该位称为“用户/主管”(U/S)。该位的值为“0”表示不允许用户模式访问由该条目控制的 4MB 区域。正如您所写,这并不意味着只有“2 个特权级别(主管和用户)”。 “主管”级别仍然由三个环组成。这包括,连同用户响铃,总共四个响铃。

请参阅 Intel 64 和 IA-32 架构软件开发人员手册第 3A 卷:系统编程指南,第 1 部分的第 4.6 节:

对线性地址的每次访问要么是主管模式访问,要么是 用户模式访问。对于所有指令提取和大多数数据 访问,这个区别是由当前权限决定的 级别(CPL):当 CPL

因此,CPL 可以是 0、1、2 和 3,有效地具有所有 4 个环。

请从上述手册中找到有关美国国旗的更多信息:

一些操作隐式地访问线性的系统数据结构 地址 [...] 称为隐式主管模式访问,无论 CPL。在 CPL

附:我的回答没有解决为什么环 1 和环 0 之间的内存保护与环 3 和环 0/1/2 之间的内存保护不同的问题,因此如果页表条目,环 1 和环 2 将不可用无法将它们与环 0 区分开来。See the reply by Peter Cordes that addresses this issue.

【讨论】:

  • 问题是为什么 ring 1 和 ring 0 之间没有内存保护,就像 ring 3 和 ring 0/1/2 之间的方式一样。您没有回答这个问题,只是详细介绍了它“失踪”的事实。 (问题是假设如果页表条目无法将它们与环 0 区分开来,环 1 和环 2 不可用,而不是说它们根本不存在。)
  • @PeterCordes,谢谢,我刚才提到了这个。
【解决方案2】:

希望保护东西不受其他东西的影响。在分页存在之前(以及在 80x86 存在之前——“4 环”模型可以追溯到 Multics,如果不是更早的话),最简单的方法是使用“环”。

使用 4 个环,您可以进行“D 无法访问 C,他们无法访问 B,并且他们都无法访问 A”的安排。这对于相反的方向来说是相对糟糕的(“C 可以访问 D 中的所有内容,不管它是否需要”)并且对于粒度来说相对糟糕(例如,如果你想要“C 可以访问 D 的一部分但不是 D 的全部”) .

通过分页,您可以为每个事物分配自己的虚拟地址空间,并在任何地方映射任何内容以控制访问(因为您无法访问未映射到虚拟地址空间的任何内容)。您仍然可以通过将属于 D 的所有页面映射到 A、B 和C;并将所有属于C的页面映射到A和B;等等。但是,您也可以有任何其他安排 - 例如模拟 10 个环而不是 4 个环,或者让 C 访问 D 的一部分(但不是 D 的全部)和 B 的一部分(但不是 B 的全部),或者...

那么问题就变成了;如果仅分页就足以模拟任意数量的环(甚至更多),为什么我们仍然有 2 个环?

答案是分页只控制对内存中的事物(代码、数据)的访问,而不能/不能控制对不在内存中的事物(例如 CPU 的控制寄存器)的访问。仍然需要 2 个环来控制是否可以/不能访问不在内存中的内容(例如,mov cr0, eax 指令是否会导致一般保护错误)。

但是;有两件事使这一点变得不那么明显。在不同的虚拟地址空间之间切换会产生一些成本,人们试图将这种成本降至最低(例如,不给共享库提供自己单独的虚拟地址空间,不给各个设备驱动程序提供自己的虚拟地址空间等);并且因为分页被添加到预先存在的“4 环分段”设计中,旧的“4 环分段”仍然在使用中(例如 TSS、IO 权限系统等)。

【讨论】:

    【解决方案3】:

    我想到的一个猜测是,英特尔打算在 Ring 1 代码运行时,它主管,“监督”ring 3 代码。没有响铃 1 在响铃 0 下运行。

    如果 ring 1 代码想要调用 ring 0 代码,它可以通过调用门进行调用,并且 ring 0 代码可以将 CR3 更改为页表,其中包含页面中不存在的物理页面的映射表环 1 或 2 代码正在使用。

    我真的不太了解这些东西,但是https://wiki.osdev.org/Task_State_Segment 表明 TSS 包含一个 CR3 字段,所以使用硬件任务切换我猜通过调用门调用可以触发 CR3 更改直接地。 (所以调用目标确实不需要已经被映射,否则 ring 1 / 2 代码可能已经修改了它。或者它可以被映射为只读,连同页表本身和 GDT,通过修改来阻止环 1 代码接管环 0。)

    这意味着仅使用分页的操作系统 [...] 无法从环 1 和 2 的存在中受益

    这是你的错误:你不能“只使用分页”。即使在普通 x86 操作系统(具有平面内存模型)上进行来自用户空间的中断处理也需要设置 TSS 东西以在切换到内核模式时将 ESP 设置为内核堆栈指针,即使您不使用硬件任务也是如此-切换。

    x86 有“任务门”和“调用门”以及各种非常复杂的东西,我希望我不必完全理解,但我希望花一些时间阅读它可能会对386 的架构师认为操作系统可能想做的事情。

    与我之前的猜测不同(关于环 1 监督环 3),也许英特尔希望操作系统在需要时使用分段将环 1 / 2 与环 0 内存分开在同一页表中1。正如您所说,他们可能并没有尝试创建便携式微内核操作系统可以用作奖励的东西。

    内核可以决定虚拟地址空间的布局,因此它可以很好地分配其中的块供 ring 1 代码使用,并在调用它时适当地设置 CS/DS/ES/SS。

    不过,我认为这意味着非平面模型,因为 x86 分段会生成地址 go from 0..limit,而不是例如允许从低到高访问一系列虚拟地址,而不改变指针的含义。

    脚注 1

    ring 0 和 ring 1 之间是否需要完全的内存保护?操作系统可能将 ring 1 用于半可信代码。

    一些特权指令需要 ring 0,所以 ring 1 会阻止这种意外发生。 IO权限级别可以单独设置,允许cliin/out in ring > 0,但其他指令如invlpglgdtmov cr, reg需要实际的ring 0。

    【讨论】:

    • 顺便说一句,@MichaelPetch 或@IraBaxter,或者其他有玩玩具操作系统/引导加载程序经验的用户可能会给出比这更好的答案,或者填写一些我正在掩饰的细节。 Ira 写了一些关于 x86 保护模式以及它如何允许类似 Multics 的内存模型的文章:What is the "FS"/"GS" register intended for?
    • 我从未测试过,但我很确定一旦启用长模式,该限制就会被忽略,从而使分段无法用于内存保护。
    • @user123:是的,x86-64 长模式中性分段,对于 FS/GS 以外的分段,base=0 和 limit=-1 是固定的。这个问答是关于英特尔的 386 保护模式设计,而不是 AMD 几十年后的 AMD64 设计。
    • 是的,当然这只适用于更现代的 CPU。
    • @user123:您当然可以在“传统模式”下运行 x86-64 CPU;根本不启用长模式并运行 386 操作系统。所以即使是现代 CPU 也必须支持所有这些,只是不能在长模式下。
    猜你喜欢
    • 2016-11-30
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多