在PCIe总线中,一个地址转换关系由8B组成,这也是地址转换请求TLP的Length字段至少为0b10的原因。当TA收到地址转换请求TLP后,将查找ATPT,然后通过存储器读完成TLP,将转换关系发送给PCIe设备。采用这种方式时,PCIe设备将首先向TA发送地址转换请求TLP,并从ATPT中获得地址转换关系后,使用TA等于0b10的存储器读写TLP,即使用Translated Address与主存储器进行数据交换,从而有效避免了上文所述的安全隐患。......
2023-10-20
在Linux系统中,支持一系列API实现存储器地址到PCI总线地址的转换,这些API的详细定义见./Documentation/DMA-API.txt文件。本节仅以pci_map_single函数为例说明这种地址转换的工作原理。pci_map_single函数在./include/asm-generic/pci-dma-compat.h文件中,如源代码12-10所示。
源代码12-10pci_map_single函数
该函数共有4个输入参数,其中hwdev参数与PCI设备的pci_dev对应,ptr参数对应存储器域的虚拟地址,size字段对应数据区域的大小。而direction参数与数据区域的使用方法对应,PCI_DMA_NONE用于调试,较少使用;PCI_DMA_TODEVICE表示这段数据的传递方向是从存储器到PCI设备;PCI_DMA_FROMDEVICE表示这段数据的传递方向是从PCI设备到存储器;PCI_DMA_BIDIRECTIONAL表示方向未知。该函数的返回值为dma_addr,即PCI总线域的物理地址。
pci_map_single函数的主要作用是通过ptr参数,获得与之对应的dma_addr,即进行存储器域虚拟地址到PCI总线域物理地址的转换。值得注意的是存储器域物理地址与PCI总线域物理地址的区别。
在Linux系统中,使用virt_to_phys函数将存储器域的虚拟地址转换为存储器域的物理地址,但是通过该函数仅能获得存储器域的物理地址,因此该地址不能填写到PCI设备中进行DMA操作。值得注意的是,进行DMA操作的地址是由PCI设备使用的,而且这个地址只能是PCI总线域的物理地址,尽管在许多处理器中,virt_to_phys函数和pci_map_single函数的返回值相同。
不同的处理器使用不同的方式实现pci_map_single函数。起初在x86处理器中,存储器域物理地址到PCI总线域物理地址的转换非常简单,是直接相等的关系。但是x86处理器为了支持虚拟化技术,使用了VT-d/IOMMU[99]技术,使得该函数的实现略微复杂。
同样是基于x86架构,AMD处理器使用的IOMMU技术与Intel有所区别,AMD的x86处理器使用./arch/x86/kernel/amd_iommu.c文件中的map_single函数,进行存储器域地址空间到PCI总线域地址空间的转换;而Intel的x86处理器使用./drivers/pci/intel-iommu.c文件中的intel_map_single函数实现存储器地址空间到PCI域地址空间的转换。IOMMU技术略微有些复杂,在第13.1节中将专门描述这部分内容。(www.chuimin.cn)
在PowerPC处理器中,存在一组Inbound寄存器,通过该组寄存器可以将PCI总线地址转换为PowePC处理器规定的存储器地址,详见第2.2节。这组Inbound寄存器也可以看作一种IOMMU,只是该IOMMU机制仅支持段式映射而不支持页式映射。
Linux PowerPC使用dma_direct_map_page函数实现这个地址转换,该函数的定义详见./arch/powerpc/kernel/dma.c。在Linux PowerPC中,PCI总线域的物理地址也与存储器域的物理地址相等。
Linux PowerPC还需要设置Inbound寄存器组,这段代码在./arch/power/sysdev/fsl_pci.c文件的setup_pci_atmu函数中,如源代码12-11所示。目前这段代码对Inbound寄存器组的Entry 2进行设置,允许PCIe设备访问0~0x7FFF-FFFF(2GB)这段存储器域物理地址空间,而且PCI总线地址与存储器地址一一对应而且相等。
源代码12-11 setup_pci_atmu函数
这段代码源于Linux 2.6.30,在这个版本中,PCIe设备不能访问PowerPC处理器2GB之上的物理内存。而在Linux 2.6.31.6中,该函数被大规模修改,以支持超过2GB的存储器系统,本节对Linux内核的这些改动不做进一步描述,对此有兴趣的读者可以参考Linux2.6.31.6内核中setup_pci_atmu函数的最新实现。
有些支持IOMMU机制的PowerPC处理器,如IBM的PowerPC处理器系列,可以使用dma_iommu_map_page或者ibme bus_map_page函数实现pci_map_single函数,而cell处理器使用dma_fixed_map_page函数实现该功能。pci_map_single函数函数在IBM的PowerPC处理器上已经移植完毕,但是Freescale除了P4080处理器之外,还没有支持IOMMU的处理器。目前对P4080处理器的支持并没有加入到Linux PowerPC中。
有关PCI Express体系结构导读的文章
在PCIe总线中,一个地址转换关系由8B组成,这也是地址转换请求TLP的Length字段至少为0b10的原因。当TA收到地址转换请求TLP后,将查找ATPT,然后通过存储器读完成TLP,将转换关系发送给PCIe设备。采用这种方式时,PCIe设备将首先向TA发送地址转换请求TLP,并从ATPT中获得地址转换关系后,使用TA等于0b10的存储器读写TLP,即使用Translated Address与主存储器进行数据交换,从而有效避免了上文所述的安全隐患。......
2023-10-20
假设在一个32位处理器中,存储器域的0xF000-0000~0xF7FF-FFFF这段物理地址空间与PCI总线的地址空间存在映射关系。图3-1 存储器域与PCI总线域的映射关系当PCI设备使用DMA机制访问存储器域地址空间时,处理器系统同样需要将存储器域的地址空间反向映射到PCI总线地址空间。本章采用图3-1的映射关系,虽然增加了映射复杂度,却便于读者深入理解存储器域到PCI总线域之间的映射关系。......
2023-10-20
图2-4 MPC8548处理器存储器域到PCI域的转换在介绍MPC8548处理器如何使用Outbound寄存器组进行存储器域地址空间到PCI总线域地址空间的转换之前,本节将首先介绍Outbound寄存器组中的相应寄存器。该位是Outbound窗口的使能位,为1表示当前Outbound寄存器组描述的存储器地址空间到PCI总线地址空间的映射关系有效;为0表示无效。检查LAWBAR和LAWAR寄存器,判断当前36位的物理地址是否属于PCI总线空间。......
2023-10-20
下面将以图1-1中的处理器系统为例,简要介绍PCI总线支持的总线事务及其传送方式。由表1-2可知,PCI总线支持多种总线事务。PCI总线的配置读写总线事务与HOST主桥与PCI桥相关,因此读者需要了解HOST主桥和PCI桥的详细实现机制之后,才能深入理解这部分内容。PCI总线支持以下几类存储器读写总线事务。HOST处理器使用PCI总线的存储器读写总线事务和I/O读写总线事务访问PCI设备的BAR空间。PCI设备对主存储器进行读写,即DMA读写操作。......
2023-10-20
51单片机数据存储器用于存放运算中间结果、数据暂存和数据缓冲、标志位等。CPU在复位后默认选择表3-3中第0组工作寄存器。图3-9 片内RAM地址分配图表3-3 工作寄存器地址列表高128B地址空间,80H~FFH为特殊功能寄存器空间。图3-10 特殊功能寄存器地址分配图表3-4 特殊功能寄存器说明表3-4中论述的特殊功能寄存器需要在程序中处理,实际应用中与硬件操作相结合,需要开发人员按功能需求进行控制。......
2023-11-04
本节讲述PCIe总线定义的各类TLP,并详细介绍这些TLP的格式。在PCIe总线中,存储器读写,I/O读写和配置读写请求TLP由以下几类报文组成。存储器读请求TLP和读完成TLP当PCIe主设备,RC或者EP,访问目标设备的存储器空间时,使用Non-Posted总线事务向目标设备发出存储器读请求TLP,目标设备收到这个存储器读请求TLP后,使用存储器读完成TLP,主动向主设备传递数据。PCIe主设备仅使用存储器写请求TLP即可完成DMA写操作,主设备不需要目标设备的回应报文。......
2023-10-20
TOLUD~4GB这段PCI总线地址空间主要映射和ICH相连的PCI设备地址空间,此外还包括EPBAR指向的空间,以及MCHBAR和DMIBAR指向的空间等。FSB Interrupts存储器空间与MSI中断机制相关,PCIe设备向这段存储器空间进行写操作时,MCH将这个写操作转换为FSB总线的Interrupt Message总线事务。DMI Interface负向译码空间被分为若干段,用来映射ICH使用的PCI总线地址空间。这些PCI设备的BAR空间被映射到这段空间。由以上说明可以发现与MCH连接的PCIe设备的访问延时小于与ICH连接中的PCIe设备。......
2023-10-20
存储器读写请求TLP的格式如图6-8所示。在存储器读写和I/O读写请求的第3和第4个双字中,存放TLP的32或者64位地址。存储器、I/O和原子操作读写请求使用的TLP头较为类似。此时与这个存储器读请求TLP对应的读完成TLP中不包含有效数据。......
2023-10-20
相关推荐