CPU/DMA如何访问硬盘?

CPU/DMA如何访问硬盘?

考虑 x86 CPU / LINUX

我想了解 cpu 或 dma 如何访问硬盘?是否必须通过 IO 端口地址访问硬盘,还是必须映射到内存(MMIO)?

答案1

硬盘上的数据不属于物理地址 空间。1数据不是内存映射的。

例如,SATA 控制器具有 CPU 需要写入的 I/O 寄存器,以便对其进行编程,使n扇区从某个磁盘偏移量通过 DMA 传输到某个物理内存地址。

这些 I/O 寄存器中的部分或全部可能通过 MMIO(正常加载和存储到特殊地址)而不是in/out端口 IO 来访问。但这仍然只是将所需命令发送到 SATA 控制器的问题。(有关详细信息,请参阅https://wiki.osdev.org/AHCI) AHCI 是最广泛使用的内核<->硬件驱动程序接口,但也有其他接口(例如需要自己的驱动程序的花式 RAID 控制器)。

例如我的主板上的 AHCI SATA 控制器,根据lspci -v

00:17.0 SATA controller: Intel Corporation Q170/Q150/B150/H170/H110/Z170/CM236 Chipset SATA Controller [AHCI Mode] (rev 31) (prog-if 01 [AHCI 1.0])
        Subsystem: ASUSTeK Computer Inc. Q170/Q150/B150/H170/H110/Z170/CM236 Chipset SATA Controller [AHCI Mode]
        Flags: bus master, 66MHz, medium devsel, latency 0, IRQ 135
        Memory at f7248000 (32-bit, non-prefetchable) [size=8K]
        Memory at f724c000 (32-bit, non-prefetchable) [size=256]
        I/O ports at f090 [size=8]
        I/O ports at f080 [size=4]
        I/O ports at f060 [size=32]
        Memory at f724b000 (32-bit, non-prefetchable) [size=2K]
        Capabilities: <access denied>
        Kernel driver in use: ahci
        Kernel modules: ahci

这两个小的“内存”区域(2k 和 8k)几乎肯定是 MMIO 端口,但它在 I/O 地址空间中也有一些 I/O 端口。“不可预取”是一个提示;如果读取有副作用,则必须禁用预取。

注意flags: bus master。这意味着它可以 DMA 到主内存/从主内存。

但是我的 NVMe SSD仅有的有 MMIO 空间,没有遗留 I/O 端口。

03:00.0 Non-Volatile memory controller: Intel Corporation SSD 600P Series (rev 03) (prog-if 02 [NVM Express])
        Subsystem: Intel Corporation SSD 600P Series
        Flags: bus master, fast devsel, latency 0, IRQ 16, NUMA node 0
        Memory at f7000000 (64-bit, non-prefetchable) [size=16K]
        Capabilities: <access denied>
        Kernel driver in use: nvme

现代硬盘控制器不会让 CPU 使用“编程 I/O”一次复制 4 或 8 个字节的数据。这是经典 IDE / ATA 控制器的一个选项,但仅作为在主板或 PCI HD 控制器上发生不良事件(如锁定或数据损坏)时的一种后备方案,用于将hdparmLinux 驱动程序设置为在 SATA 前系统上使用 DMA 传输。

从技术上讲,PIO 显然仍是 AHCI SATA 控制器的一个选项。但它从来都不是默认选项;与硬件损坏成为现实的糟糕旧时代不同,现代操作系统可以放心地期待 DMA 能够正常工作。


脚注 1:除非你的“硬盘”实际上是非易失性 DIMM在内存插槽中,例如英特尔 Optane DC PM或由电池供电的 DRAM)。将最近存储的数据从写回式 CPU 缓存推送到非易失性内存映射存储是clflushopt或等指令的一个用例clwb

相关内容