4

我正在使用 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 时才能执行以下指令:IN、INS、OUT、OUTS、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 中运行应用程序。

4

2 回答 2

3

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

所有已知的 Ring0 主机(DOS32/A、WDOSX、CWSDPR0)都不会交换——这只是巧合,还是存在阻止 Ring0 主机交换的根本“问题”?

CWSDPMI页面:

CWSDPR0.EXE 是在禁用虚拟内存的环 0 上运行的替代版本。如果需要访问 ring-0 功能,则可以使用它。

DOS/32 页面

  • 保护模式应用程序以 CPL 0 运行

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

  1. 做你自己的保护模式设置 - 这并不难

  2. 使用现有的 DOS 扩展器并对其进行修改以在 Ring 0 中运行。HX-DOS 源可用,以及其他几个


于 2012-07-23T11:37:47.773 回答
1

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

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

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

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

于 2012-07-22T12:26:31.147 回答