使用端口映射I/O时是否使用虚拟内存?

Ste*_*eve 6 c linux x86 device-driver virtual-memory

如果我有一个内存映射的I/O设备,并且我想写入位于0x16D340x16D34地址的该设备的寄存器,该地址实际上是一个虚拟地址,CPU将首先将其转换为物理地址,然后写入数据到物理地址.

但对于端口映射I/O设备(例如:串行端口),所以如果我想要写一个寄存器位于地址串口0x3F8,是0x3F8地址的物理地址或虚拟地址?


编辑:我在x86架构上.

pmd*_*mdj 5

x86/x86-64 上的端口映射 I/O(大多数其他现代架构甚至不支持它)发生在完全独立的地址空间中。这个地址空间不受内存映射的影响,所以没有虚拟端口地址,只有物理端口地址。必须使用特殊inout指令来执行端口 I/O,简单的内存访问(例如使用mov)无法访问这个单独的地址空间。可以基于权限级别进行访问保护;大多数现代操作系统默认阻止用户空间进程访问 I/O 端口。

例如,您可以查看英特尔的“英特尔® 64 位和 IA-32 架构开发人员手册:第 1 卷” (撰写本文时第 18章)的“输入/输出”一章以了解详细信息。

请注意,在 x86 的早期,每个设备(包括 ISA 附加卡)中的端口地址都是硬连线的。如果幸运的话,该卡有一组跳线,用于为设备选择一组有限的可能端口范围中的一个,以避免设备之间的范围冲突。后来,引入了即插即用以在系统启动期间动态进行选择。PCI 进一步完善了这一点,以便操作系统和/或固件几乎可以将 I/O BAR 映射到 0x0000-0xffff 地址空间内的任何位置。由于其许多固有限制,现在在设计新硬件时强烈建议不要使用端口映射 I/O。

  • 当地址在总线上时,x86 CPU 是否仍然包含一个引脚来选择内存或 I/O?这就是我记得事情的方式,但对我来说大学是多年前的事了(来自 [Memory-Mapped I/O](https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/IO/mapped. html)): *"IN 和 OUT 以及从内存加载和存储之间的唯一区别是 CPU 上的单个输出引脚。如果地址总线上的地址是内存地址,则该引脚将输出,例如,0 , 如果地址是 I/O 地址,则输出 1"*. (2认同)
  • @jww 我对此表示怀疑,今天的 CPU 内置了内存控制器,因此有很多引脚直接连接到内存模块,无需在那里进行 I/O 寻址。它们还有直接的 PCI Express 通道。PCIe 使用很少的引脚,消息(包括地址和有效载荷数据)仅在一对电线(每个方向)上串行传输以使用差分信号。也许对于一些传统的外围设备,但无论如何它们都可能在南桥中。 (2认同)