【问题标题】:Which instructions are responsible for mapping the bus into memory?哪些指令负责将总线映射到内存?
【发布时间】:2016-12-26 23:26:16
【问题描述】:

然后一个 CPU 指令从内存中读取一些东西,在 CPU 和 MMU 中有一个特殊的电路,当指令执行时,地址被发送到 MMU,它通过 BUS 通知需要从内存中读取并将信息放入目标寄存器。我还了解到,一些通常对应于 RAM 的地址被映射到一些设备。所以我想有一种方法可以首先告诉我一些设备将映射到哪些地址。然后,我们欺骗处理器尝试从内存地址读取,然后通过某些电路,它最终读取设备。

我在哪里可以找到更好的解释?特别适用于处理 PCI 和更多知名设备的 x86 架构。

【问题讨论】:

  • 您需要澄清您的问题。对于标题中的问题,答案将包含所有三个:I/O 端口读取/写入、内存读取/写入、无(由 BIOS/芯片组/其他硬件连接或预配置)。你并没有真正“愚弄”CPU。物理内存地址解码可在 CPU 和内存/设备/总线之间路由数据。有些地址可能是硬连线的,而有些可能是可变的。

标签: memory linux-kernel cpu instructions


【解决方案1】:

没有负责将设备映射到内存的指令1

一个完整的答案过于宽泛,但我们可以举一两个例子。
首先,说服您自己可以通过简单地告诉设备要收听的地址来配置设备。在硬件层面,这只不过是一种比较。

  1. 某些设备具有固定地址。
    这些是旧设备,在系统首次发布时出现,并被其他竞争对手克隆,以及后续版本以实现向后兼容性。

  2. 可配置设备。
    这些设备有跳线/开关来选择要收听的地址范围。用户的任务是避免冲突并适当地配置软件。

  3. Plug and play 设备。
    最著名的 PnP 总线是 PCI,但 ISA 和 MCA 也是 PnP 的地方(ISA 是“某种”PnP)。
    这些设备与上述设备类似,但可在软件中进行配置,它们所需的资源(IRQ、DMA、MMIO)也是可枚举的,以让固件和操作系统分配它们而不会发生冲突。

现在您想知道如何实现选项 3。答案很简单:使用元地址空间

以 PCI 为例,地址 0cf8h0cfch2 用于选择设备,设备上的寄存器configuration space,并读取或写入该寄存器。
配置空间中的寄存器可用于变基设备。

假设寄存器10h保存设备监听的地址,那么这段伪代码将设备映射到88888888h

uint32_t* select = MAKE_POINTER(0xCF8);
uint32_t* data = MAKE_POINTER(0xCFC);

*select = MAKE_SELECT(0, 1, 31, 0x10);   //Bus 0, Device 1, Function 31, Register 0x10
*data = 0x88888888;                      //Set reg 0x10 to 0x88888888

如您所见,取消指针会生成对内存位置 0cf8h 和 0cfch 的写入,但这些位置不会被硬件路由到主内存,而是转到 Host-to-PCI 桥控制器将它们转换为感兴趣的设备将获取的 PCI 配置空间访问。

稍后,当访问 88888888h 时,这又不是路由到主内存3,而是路由到配置设备所在的 PCI 总线(通常是 subtractive decoding 的结果)正在听。


1 从某种意义上说,没有特制的 CPU 指令。一切都是执行某些指令的结果,因此从某种意义上说,某些“必须对被映射的设备负责”。对于这个答案的其余部分,我假设您想知道MMIO 的工作原理。

2 仅适用于 IO 地址空间中的 x86,但不要让我们分心。

3 硬件知道内存在哪里结束,如果软件将设备映射到实际存在内存的位置,则后者优先且不会访问该设备。

【讨论】:

    猜你喜欢
    • 2018-07-01
    • 2014-01-02
    • 2011-05-19
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多