阅读:5233回复:9
请教64位操作系统如何兼容32位PCI设备?
各位好:
请教大家一个问题,我们现在在做一个PCI设备,该设备会使用DMA方式从主存取数据,我们的设备是32位的,不能确定在64位环境(64位OS和64位CPU)能不能正常运行,有这么几个问题要请教大家: 1、设备是32位的,也就是说它的寻址空间是4G,而在64位环境下,驱动程序是如何保证分配的物理地址是在4G范围内,如果驱动不能保证分配的空间不在4G范围内,那么设备在取数据时肯定会出错。 2、主板BIOS在给PCI设备分配地址空间时,是如何分配的,64位环境如何给32位设备分配空间,32位设备又是如何对其进行地址译码的? 3、归根结底,也就是64位操作系统是如何兼容32位设备的? 多谢多谢! |
|
沙发#
发布于:2007-12-31 09:16
这个问题并不是在64位下面存在的
32位下面也有这个问题的..因为在32位下面也能使用超过4g的物理内存 1.首先pci本身就只是一个32位的总线结构.64位是通过一个叫做double address cycle(DAC)来实现的,所以即使在64位的环境下面.pci仍然是32位的操作模式.pci跟cpu是多少位是没有关系的 2.按照现在已经有的bios和efi的实现来看.ia32下面几乎从来不给pci设备分配高于4G的bar.即使bar是64位的memory的.总是尽量把memory mapped io分配在4g以下.而4g以上的空间分配给物理内存. 3.至于用于dma的内存.这个是操作系统和设备驱动程序一起来完成的.由设备驱动程序告诉操作系统这个设备是否支持64位的dma 然后操作系统根据设备提供的信息来分配物理内存...如果设备不支持64位的dma.那么操作系统保证分配出来的dma内存是在4g以下的 一般的流程是.上层传递一个虚拟地址的缓冲区地址给驱动程序.驱动程序调用操作系统的某个(某些)api把这个虚拟地址转换成sg list 然后把这个sg list提交给物理设备...操作系统就会在上面"把虚拟地址转换成sg list"这一步作手脚,确保最后返回的sg list里面记录的物理地址是满足设备要求的 |
|
板凳#
发布于:2007-12-31 17:39
没错,32位/PAE下也会有这样的问题。
其实问题不在于配置空间的地址,Windows也许可以保证把32位设备的配置空间映射到4GB以下。但比如有着样的操作:在64位或32位PAE且物理内存大于4GB的场景下,驱动程序需要分配一块内存,然后把这块内存的物理地址告诉硬件(把物理地址写入硬件的寄存器)。这种情况下能否保证这块内存一定位于4GB以下?也就是硬件的寄存器是否只需要32位就够了? 引用第1楼tiamo于2007-12-31 09:16发表的 : |
|
地板#
发布于:2008-01-01 08:29
拿windows来说
如果一个设备需要作dma 则首先需要调用一个叫IoGetDmaAdapter的函数 注意这个函数的第二个参数---PDEVICE_DESCRIPTION DeviceDescription 这个结构里面有两个成员来控制dma缓存区的分配策略 Dma32BitAddresses和Dma64BitAddresses 驱动程序通过设置这两个成员来告诉windows如何分配物理内存 如果Dma64BitAddresses为FALSE 那么在IA32平台下.windows保证返回给设备程序的那个将要写到硬件寄存器的物理内存的地址是在4G以下的.. 至于硬件的设计上面.能完成64位的dma的时候绝对不去作32位的dma 因为这样有性能损失.. 如果用户提交的缓冲区的物理地址大于4G.但是设备没办法作64位的dma 那么windows需要在4G以下的空间分配额外的跟用户缓冲区一样大的一块物理内存. 然后把用户缓冲区里面的内容复制到新分配的物理内存里面. 然后再把新分配的物理内存地址返回给驱动程序 然后设备作dma dma完了以后.windows还需要作一次同样的copy动作.然后释放掉4G以下的那块物理内存 当然通常copy动作只是作一次.不会前后都作的. 从host到device作dma的时候.copy动作发生在dma之前 从device到host作dma的时候copy动作发生在dma之后 如果设备本身支持64位dma.那么windows就只是需要把用户缓冲区的物理地址直接返回给驱动就行了 而不需要额外的分配内存作copy动作 当然..以上讨论都是基于设备支持Scatter Gather的前提下的 另外...配置空间?怎么映射? pcie的配置空间是会被映射到memory的.一共256MB 但是这个映射过程是bios来决定..windows并不会参与映射过程 要是pci的配置空间的话...是通过cf8,cfc来访问的. |
|
地下室#
发布于:2008-01-01 21:12
明白了!
如果所分配不是DMA的内存呢,是否有问题? 引用第3楼tiamo于2008-01-01 08:29发表的 : |
|
5楼#
发布于:2008-01-02 12:39
按照windows的要求
传递给物理设备的内存必须是用dma分配的... 不是经过dma分配的内存是不能直接提交给物理设备的. 除了上面这个32位64位的原因以外 还有别的原因 比如在IA64下面并不能保证cpu边看到的物理地址跟pci设备那边看到的物理地址是1比1对应的 |
|
6楼#
发布于:2008-01-02 17:40
多谢tiamo!
说得再具体些,比如对于一块网卡,在驱动里面可以控制接收时的缓冲区分配,那么应该不存在4GB的问题。但对于发送,为了避免数据的拷贝,对于从协议驱动中传下来的数据包,想在Miniport驱动中直接使用数据包的内存块,只需要重新分配一些描述符来描述这些内存块。这种情况下,上层传下来的数据包的内存块是否会存在4GB的问题呢?或者说这种不拷贝的机制能否实现,是否需要重新分配满足DMA要求的新内存块,再把上层传下来的数据包复制到新内存块中? 引用第5楼tiamo于2008-01-02 12:39发表的 : |
|
7楼#
发布于:2008-01-04 00:59
以ndis来说
dma需要作的工作有一步会在InitializeMiniport里面 要么调用NdisMInitializeScatterGatherDma...注意他的第二个参数 要么调用NdisMAllocateMapRegisters....注意他的第三个参数 如果驱动不支持64位..那么这个copy操作是不能避免的 通常的讲...copy操作是由操作系统来完成的...不需要驱动参与的好像 ndis的驱动我也没写过..也不太清楚具体是怎么来完成的 似乎是需要调用NdisMStartBufferPhysicalMapping函数把上层的虚拟地址转换成物理地址 然后把物理地址提交到硬件. 然后在硬件完成以后调用NdisMCompleteBufferPhysicalMapping释放掉上次的map? |
|
8楼#
发布于:2008-01-07 17:11
查了一下,Copy的确是需要的,Miniport驱动需要做Copy,上层传下来的内存块不可直接用
|
|
9楼#
发布于:2008-01-11 09:07
引用第6楼rangzh于2008-01-02 17:40发表的 : 这个方面应该跟32,64位没关系. 零拷贝机制是存在的,接收时可以真零拷贝,但发送时一定需要先分配新DMA内存,拷贝,再送硬件. |
|