关于组装:x86 IO-mapped IO ports protection and DOS Extenders

x86 IO-mapped IO ports protection and DOS Extenders

我正在使用 DOS Extender 为 FreeDOS 开发一个保护模式应用程序。我的应用程序执行密集的 I/O。

由于所有的 DOS 扩展程序都在 Ring3(即 CPL=3)中运行它们的应用程序并且它们自己在 Ring 0(即 CPL=0)中运行,我想到了一些关于 I/O 保护的问题。

从 x86 文档中,我得到以下信息:

IOPL 敏感指令:IN、INS、OUT、OUTS、CLI 和 STI。

如果 CPL <= IOPL,则不产生异常并执行 IOPL 敏感指令。

如果 CPL > IOPL,并且指令是这些指令之一(IN、OUT、INS 或 OUTS),则处理器检查当前任务的 IO 权限位图(在其 TSS 中)以确定当前应用程序是否被允许访问寻址的 IO 端口。如果位图指示允许任务访问指示的 IO 端口,则不产生异常并执行 IO 指令。否则,将生成 GP 异常。

如果 CPL > IOPL,并且指令是 CLI 或 STI,处理器会生成 GP 异常。

这意味着如果我们的应用程序。在 Ring3 上运行,然后要执行 IN,OUT,INS,OUTS 指令,我们必须有 CPL <= IOPL(在我们的例子中这转换为 IOPL=3),或者如果 CPL > IOPL(这转换为 IOPL <= 2 ,即 IOPL = 0,因为通常不使用 Ring1 和 Ring2。)I/O 权限位图必须由 DOS Extender 设置(在启动我们的应用程序时),这样我们的应用程序。允许访问任何 I/O 端口。

但在后一种情况下,我们仍然不能使用 Ring3 应用程序中的 CLI 和 STI 指令,因为 CPL > IOPL。

所以,事实证明,只有当 CPL <= IOPL 时,才能执行以下指令: 输入、输入、输出、输出、CLI 和 STI。 在我们的例子中,这转换为 3 <= IOPL,即 IOPL = 3.

现在我的问题是,所有 dos 扩展程序是否在它们启动的任务/应用程序的 TSS 中设置 IOPL = 3?

如果他们不这样做,那么他们必须在 Ring0 (CPL=0) 中运行任务/应用程序,否则应用程序无法执行 IOPL 敏感指令。

文档还声明:

程序或任务只能通过 POPF 和 IRET 指令改变其 IOPL;
然而,这样的改变是有特权的。
除非以特权级别 0 即 CPL=0 运行,否则任何程序都不能更改当前的 IOPL。较低特权的过程尝试更改 IOPL 不会导致异常; IOPL 保持不变。

这意味着:如果在Ring 3代码中遇到POPF或IRET指令,则IOPL字段不会被修改/恢复,CPU不会产生异常。

这没关系,因为我们不想修改 IOPL 字段,让它由 DOS Extender 处理。
但这是否意味着其他标志(EFLAGS reg.的bit0到bit11)将被恢复?

我的应用程序。可能还需要执行 POPF 指令和 IRET。

该文档还指出:

只有当 CPL <= IOPL 时,程序才可以使用 POPF 指令更改 IF 标志的设置。较低特权的过程尝试更改 IF 标志不会导致异常; IF 标志保持不变。

这意味着:如果在 Ring3 代码中遇到 POF 指令,则仅当 CPL <= IOPL 即 3 <= IOPL 或 IOPL = 3 时修改 IF 标志。同样我们需要 IOPL 为 3。:)

我正在寻找一个通用的答案——即不是 DOS Extender 特定的。这是因为,似乎虽然它们在实现上有所不同,但基本原则仍然是相同的 b/w DOS 扩展器——例如他们在 Ring3 中运行应用程序。


我不明白为什么 DOS 扩展程序需要在 Ring 3 中运行您的应用程序代码。我认为 DPMI 规范要求这样做,但如果您的应用程序是唯一运行的应用程序,您实际上不必坚持它。这篇论坛帖子提到了一些据称在 Ring 0 中运行的扩展器:

All known Ring0 hosts (DOS32/A, WDOSX, CWSDPR0) don't swap - it this
just coincidence or is there a fundamendal"problem" preventing Ring0
hosts from swapping?

来自 CWSDPMI 页面:

CWSDPR0.EXE is an alternate version which runs at ring 0 with virtual memory disabled. It may be used if access to ring-0 features are desired.

来自 DOS/32 页面:

  • protected mode applications run at CPL 0

如果这些都不起作用,还有其他选择:

  • 设置你自己的保护模式——这并不难

  • 采用现有的 DOS 扩展器并对其进行修改以在 Ring 0 中运行。HX-DOS 源可用,以及其他一些源。


  • 可能由您决定谁来负责。如果这是系统上唯一的应用程序,则可以授予它所有权限。如果有其他应用程序需要系统保护,允许一个应用程序做任何它想做的事,可能不是那么好。

    在受保护模式的操作系统中,如 Windows 和 Linux,您需要编写设备驱动程序并将其安装在内核中以访问硬件。

    我相信 POPF 指令将恢复您使用早期 PUSHF 指令保存的所有标志。只是如果您首先尝试摆弄堆栈上的位,保护规则就会启动。

    如果不设置 I/O 权限位,另一个选项是拦截保护中断并根据具体情况决定是否允许应用程序读取或写入端口。在这种情况下,扩展程序可以代表应用程序执行操作,然后恢复它。不过有点棘手……