为什么x86分页没有特权环的概念?

2024-05-06

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

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

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

从可移植性的角度来看,环 1 和环 2 的存在是 x86 架构的一个怪癖,便携式操作系统不应该使用它们,因为其他架构只有 2 个特权级别。

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

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


我想到的一个猜测是,英特尔打算在 Ring 1 代码运行时,is主管,“主管”环3代码。环 1 未运行under ring 0.

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

我真的对这个东西了解不多,但是https://wiki.osdev.org/Task_State_Segment https://wiki.osdev.org/Task_State_Segment显示 TSS 包含 CR3 字段,因此使用硬件任务切换我猜测通过调用门进行调用可以直接触发 CR3 更改。 (所以调用目标not已经必须被映射,否则环 1 / 2 代码可能会修改它。或者它可以与页表本身和 GDT 一起映射为只读,以通过修改它来阻止环 1 代码接管环 0。)

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

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

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

Separate from my previous guess (about ring 1 supervising ring 3), perhaps Intel expected OSes to use segmentation to separate ring 1 / 2 from ring 0 memory in the same page table if desired1. As you say, they probably weren't trying to create something that portable microkernel OSes could just use as a bonus.

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

不过,我认为这意味着非平面模型,因为 x86 分段使地址从 0.. 限制开始 https://wiki.osdev.org/Segment_Limits,不是例如允许访问从低到高的一系列虚拟地址,而不改变指针的含义。

脚注1:

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

一些特权指令需要环 0,因此环 1 可以阻止意外发生。 IO权限级别可以单独设置,以允许cli and in/out在环 > 0 中,但其他指令如invlpg https://www.felixcloutier.com/x86/invlpg, lgdt https://www.felixcloutier.com/x86/lgdt:lidt, and mov cr, reg https://www.felixcloutier.com/x86/mov-1需要实际的环 0。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么x86分页没有特权环的概念? 的相关文章

  • 测试 xmm/ymm 寄存器是否为零的更快方法?

    It s fortunate that PTEST does not affect the carry flag but only sets the rather awkward ZF also affects both CF and ZF
  • 如何在 Restful Web 服务中指定一系列数据或多个实体

    要访问 Restful Web 服务中的 User 实例 URL 的结构如下面的curl 请求所示 curl v X GET s BASE URL User customer id json 如果我想指定所有用户实体或对一系列用户实体进行分
  • 32 位应用程序在 64 位操作系统上运行得更快还是更慢? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • CREATE TABLE 和 CREATE ANY TABLE 权限之间的区别

    我不明白这两种特权之间的区别 我找到了这两个解释 但这对我没有帮助 CREATE TABLE gt Enables a user to create a table owned by that user CREATE ANY TABLE g
  • mfence 和 asm 易失性 ("" : : : "内存") 的区别

    据我了解 mfence是硬件内存屏障 而asm volatile memory 是编译器障碍 但是 可以asm volatile memory 用来代替 mfence 我感到困惑的原因是这个链接 http gcc gnu org ml gc
  • 气体:内存引用太多

    编译时指令如下 movl 4 ebp 8 ebp I got 内存引用过多 它出什么问题了 括号之前的数字是字节偏移量 这会导致发生内存引用 并且不能有两个movl 您需要先将值暂时移至寄存器 movl 4 ebp ecx movl ecx
  • C 标准库函数与系统调用。哪个是“open()”?

    I know fopen 在C标准库中 所以我绝对可以调用fopen C 程序中的函数 我感到困惑的是为什么我可以打电话给open 功能也一样 open 应该是系统调用 所以它不是标准库中的C函数 因为我能够成功地调用open 函数 我调用
  • 如何使用 LOCK ASM 前缀来读取值?

    我知道如何使用 LOCK 来线程安全地递增一个值 lock inc J 但是如何以线程安全的方式读取 J 或任何值 LOCK 前缀不能与 mov 一起使用 如果我执行以下操作 xor eax eax lock add eax J mov J
  • x86 汇编乘法和除法指令操作数,16 位及更高

    我对 x86 汇编中的乘法和除法运算如何工作感到相当困惑 例如 下面的代码看起来并不太困难 因为处理的是 8 位 8 位乘法 User Input num1 20 num2 15 mov ax num1 moves the 8 bits i
  • 如何在 x86 汇编中编写自修改代码

    我正在考虑为我最近开发的一个业余爱好虚拟机编写一个 JIT 编译器 我了解一些汇编语言 我主要是一名 C 程序员 我可以阅读大多数汇编语言并参考我不理解的操作码 并编写一些简单的程序 但是我很难理解这几个示例我在网上找到的自我修改代码 这是
  • 给寄存器赋值并加减

    我对此完全迷失了 我需要使用寄存器来计算以下表达式的编程 varA varA varB varC varD 其中 varA varB 等是变量 将整数值分配给上述变量的 EAX EBX ECX 和 EDX 寄存器 这意味着 您可以对输入进行
  • 使用`esp*scale 时寻址内存时出错

    内存寻址一般形式 发现了here https stuff mit edu afs athena project rhel doc OldFiles 3 rhel as en 3 i386 memory html is base index
  • crt0 是否加载 msvcrt.dll?

    我想弄清楚标准 C 函数是什么样的printf 在 Windows 环境下加载到内存中 我知道crt0 obj准备堆栈 调用int main int argc char argv 然后使用 main 返回的退出代码退出进程 我还听说 C 标
  • 调用/返回/jmp等后x86代码执行?

    我希望这个问题不会太愚蠢 因为它看起来似乎很明显 当我对缓冲区溢出进行一些研究时 我偶然发现了一个简单的问题 调用 返回 跳转后转到新指令地址后 CPU是否会执行该地址处的OP代码 然后将一个字节移动到下一个地址并执行下一个OP代码 依此类
  • 为什么我们需要不同的指针数据类型?

    基本上指针是一个用于存储内存地址的变量 它总是十六进制 内存地址 那么为什么我们需要不同的数据类型来存储地址 例如 int a 我们可以用这个 a 来存储浮点地址吗 并非所有指针 必须具有 相同的大小 如果您有一个需要对齐到 10 MB 的
  • 如果我有一个 8 位值,那么使用 8 位寄存器而不是 16、32 或 64 位寄存器有什么优势吗?

    我读到的 x86 asm 介绍性文献似乎在所有实际场景中都坚持使用 32 位寄存器 eax ebx 等 除了证明 64 位寄存器也存在之外 如果确实提到 16 位寄存器 那也是作为历史注释来解释为什么 32 位寄存器的名称前面有一个 e 编
  • 是否可以调用驻留在 exe 中的非导出函数?

    我想调用驻留在第 3 方 exe 中的函数并获取其结果 好像有should是一种方法 只要我知道函数地址 调用约定等 但我不知道如何 有谁知道我会怎么做 我意识到任何解决方案都是非标准的黑客 但有must成为一种方式 我的非恶意用例 我正在
  • Visual Studio:如何正确构建和指定 x64 和 x86 的配置和平台

    使用 Visual Studio 2012 Professional 和 Ultimate 以及所有最新更新 如何正确指定配置和平台以正确构建 x86 和 x64 当您第一次创建 Winforms 应用程序时 Visual Studio 会
  • 在汇编中,指令指定数据类型吗?

    我是汇编语言编程 x86 的初学者 以下说法是否正确 在汇编中 BYTE WORD DWORD 等数据类型分别表示 8 位 16 位和 32 位模式 而不仅仅是整数 它们本身没有意义 它们只是位模式 使用它们的指令赋予了它们意义 汇编 代码
  • 将 1 字节立即值添加到 2 字节内存位置

    The add说明文档来 自这一页 http x86 renejeschke de html file module x86 id 5 html说如下 请注意我突出显示的两条说明 我在 NASM 中尝试了以下代码 符合第一个突出显示的指令

随机推荐