IOMMU

在没有IOMMU的情况下,设备(指32bit或64bit设备,老的16bit的不提)的DMA操作可以访问整个物理地址空间,所以理论上设备可以向操作系统的代码段、数据段等内存区域做DMA,从而破坏整个系统。当然,通常来说不会有这样的设备。IOMMU的出现,可以实现地址空间上的隔离,使设备只能访问规定的内存区域。下面简要说一下intel的IOMMU怎么做到这点的:
目前PC架构最多有256PCI总线,于是IOMMU用一个称为root entry的数据结构描述PCI总线,总共256个root entry构成一张表。每条PCI总线最多允许256个设备,IOMMU用context entry描述一个PCI设备(或者是PCI桥),256个context entry构成一张表。所以就有了如图的关系。我们知道,PCI设备用 {BUSEV:FUNC}(当然,还有个segment,不过似乎PC架构都只有一个segment,这个暂时忽略)描述一个设备。所以对于一个特定设备,用bus号做索引root entry表,用dev号索引context entry表可以找到描述该设备的的context entry。context entry中有一个指针指向一章I/O页表,当设备发起DMA操作时,IOMMU会根据该页表把设备的DMA地址转换成该设备可以访问内存区域的地址。
所以只要为设备建一张I/O页表,就可以使设备只能访问规定的内存区域了。当然,也可以把该页表当成跳板,让只能寻址32bit地址空间的设备访问到64bit地址空间中去。

大概就是这么回事了,似乎写的有点乱,具体问题看spec。

rootentry.jpg (25.55 KB, 下载次数: 100)

 

rootentry.jpg

最近学习了一下PCIE,牵扯不少名词,网络上不少blog和文章,对虚拟地址、物理地址、翻译过程理不清头绪,在这里尝试总结一下问题,并给出自己的理解(大部分是基于推导猜测),希望了解这块的大侠们纠正,有些问题自己也不懂,希望能够得到指点。谢谢!

1. BIOS或者内核在初始化PCIE的时候,BAR里写入的基地址到底是虚拟存储器域地址,还是物理存储器域地址,还是pcie总线域地址?
答:PCIE总线域地址,内核自己记录每个设备的主存物理地址--PCIE总线域地址映射。

2. 那好,那么初始化好之后,该设备驱动加载时,据说要做ioremap,这是怎么回事?
答:保护模式下,谁都绕不过MMU和页表(内核自身也绕不过么?),必须使用虚拟地址,包括内核自身(比如Linux下高1GB和Windows下高2GB或1GB)。驱动必须把内核初始化好的这些BAR物理基地址ioremap()为内核虚拟空间的虚拟地址。之后读写IO端口也必须使用虚拟地址。

3. 那好,ioremap之后,映射关系被保存在了哪里,是页表里么?
答:是的,由于内核虚拟空间被每个用户进程公用,所有进程页表的内核空间映射都是共享的,就被保存在这里,也要经过MMU,所以陷入内核不需要更新CR3寄存器。

4. 那好,驱动发出某个虚拟地址读写设备某寄存器,经过MMU翻译之后,北桥怎么知道这地址是发给该物理设备的?PCIE设备DMA的时候不是必须发出PCIE总线物理地址么,如果它发出的驱动告诉它的主存虚拟地址,怎么解?
答:内核初始化PCIE的时候,会对北桥编程,将所有外设的地址范围保存在北桥的缓存里,所以北桥知道,并且知道哪些地址是应该交给PCIE控制器,也就是PCIE主桥处理的。至于第二个问题,不清楚。。

5. 那好,PCIE主桥收到对应地址的访问之后,做了什么?
答:主桥直接在PCIE地址总线上放置收到的地址信号,次级桥或者bus0总线上的EP终端设备都会解析这个地址,如果发现是自己BAR+Limit地址范围之内的,就会认领这个信号,从而启动数据传输周期。

6. 那么PCIE主桥屁事不干就管转发信号?
答:这个不清楚,之前看到的是主桥负责把主机物理地址翻译长PCIE总线地址,按照上述过程,根本不用翻译,每个PCIE设备都知道自己负责响应哪块地址段,因为各自都知道各自的BAR基地址和limit,看不出哪里需要翻译。而且至今也不理解所谓“PCIE总线地址”原生是个什么概念,是不是那意思是说每个PCIE设备在没被初始化之前都认为自己的BAR基地址是从0开始。。不清楚所谓“主桥地址翻译”在什么时候翻译了谁。。

7. 那好,PCIE设备从主机端内存DMA数据进来,是走PCIE数据总线么?
答:是的,PCIE串行+并行方式传输数据。

8. 那好,PCIE设备上的DMA控制器是和北桥上的DMA控制器在电路级连通么?
答:不清楚,猜测是连接到PCIE主桥,经过翻译之后,再访问内存控制器。

9. 那好,PCIE设备要启动DMA,它怎么知道去哪个地址DMA?
答:驱动在初始化该设备的时候,会把主存里的数据缓存、指令队列等基地址写到设备的专用寄存器里,并保持恒久不变。设备通过访问该基地址得到指令以及SGL内存段描述表,从而知道去哪里DMA。

10. 那好,驱动通知给设备的这些地址,是硬件物理地址还是虚拟地址?
答:一定是虚拟地址,因为驱动写入这些寄存器里的地址虽然是地址,但是是作为数据形式写入的,MMU不会感知到“数据”里面保存的是地址。

11. 那好,设备通过DMA控制器把要访问的虚拟地址发送给北桥DMA控制器,北桥DMA控制器是要通过MMU翻译成物理地址么?
答:理论上应该是这样,但是据说有个叫做IOMMU的东西,专门负责DMA时候的地址翻译。但是这里我也不明白,IOMMU会把虚拟地址翻译成物理地址么?为何不用MMU,单独搞一个IOMMU?

12. 那好,PCIE设备是不是只能访问主机端主存在BAR里定义的地址段?
答:之前看过一些文章说不管是CPU访问外设地址还是外设访问主存地址,都是限制在BAR里的地址段的,都不能越界访问。但是现实中好像根本不是这么回事。外设DMA主存的时候可以访问任意地址空间,有4GB可用,那么一定是虚拟空间了,我之前也理解外设访问主存也必须限制在BAR规定的地址段内,可能被深深误导了。但是既然SGL里通告的是虚拟地址,那么为何DMA不是用MMU来映射回物理地址呢?非要再搞个IOMMU为何呢?

13. 那好,请告诉我既然有“PCIE域总线地址”,那么PCIE插槽针脚上,地址线连接在哪里?
答:PCIE总线使用数据针脚复用地址和数据信号,分周期,先地址,后数据。但是,也请明白的告诉我,传送64位地址的话,一个时钟周期传完,起码要64根导线,PCIE插槽上如果是4个Lane的,没有64线吧,那是不是要分多个周期传送了。

14. 好吧。那么所谓“PCI设备在向主存DMA的时候使用的也是PCIE总线域地址而不是主存地址”,能否解释一下这句话?死活想不通,PCIE设备怎么能使用PCIE总线域地址向主存DMA?这不相当于刻舟求剑么?驱动告诉它去哪DMA,它就去应该去哪DMA,完全不懂。
答:不要问了,我已经疯了。

15. 哦。那请告诉我书上说“BAR内存放的是PCIE总线域的地址而不是存储器域的地址”,我也要疯了,内核初始化PCIE的时候,不是把其分配的存储器域的基地址写入到BAR内么?怎么就不是存储器域的地址了呢?难道“正统”做法应该是写入PCIE总线域地址,然后再由PCIE主桥进行翻译?
答:哎?尼玛,你可能还真说对了。的确“正统”的做法,就是为每个PCIE设备分配各自的PCIE域的总线基地址并保证不冲突,然后为每个PCIE域的基地址映射存储器域的基地址,然后记录在PCIE初始化那个树结构里,并且把这个地址翻译表保存在北桥。。。

16. 哦?尼玛太好了。那么请解释一下书上说的“PCIE设备在DMA的时候也只能使用PCIE总线地址,而且不能访问未被映射的地址空间”。
答:晕了。这完全颠覆了我的认知。PCIE设备应该是可以完全DMA主存的虚拟地址空间,但是如果BAR里如果只分配了1MB地址,按照“书”上说的,它和寻址4GB虚拟空间? “书”中的描述为何不能啰嗦和通俗一些呢?愁死了。

首先需要明白CPU域的物理地址空间和PCI域的地址空间的区别。而PCI域的地址空间又分成配置空间,内存地址空间,IO地址空间。

一般容易混淆的是CPU域的物理地址和PCI域的内存地址空间的地址,因为x86上它们数值上相等,因此很多时候就认为两者等同,其实是不同的。

比如32位的CPU域物理地址空间可能只有4G,但是PCI域的内存地址空间可以达到2^64大小。。。远远大于CPU域物理地址空间。

从CPU域物理地址空间到PCIE域的内存地址空间的映射,即将PCI设备的bar + size这么一段pcie域的内存地址空间映射到CPU域上对应数值的物理地址空间。

而从PCIE域的内存地址空间到CPU域物理地址空间的映射,则是iommu的工作。如果没有,那么同样是直接映射。

CPU发起访问是,使用的是自己的物理地址,通过pcie root complex转换成PCI域的内存地址空间的地址。而一旦在PCIE总线上,存在的寻址全部使用PCIE域的地址。

同样设备发起访问时,使用的是PCI域的地址,不会使用CPU域的物理地址。当有iommu时,就可以做到PCIE设备访问的是连续的PCI域的地址,但是通过iommu将它翻译为了不连续的CPU域物理地址。

 

通常X86系统中会存在四大地址空间:进程地址空间、内核地址空间、物理地址空和PCI地址空间。这几大地址空间有些是硬件领域的相关内容,例如PCI地址空间,PCI Hole;有些是软件研发需要了解的。这几大地址空间有什么不同?他们之间是如何联系在一起的呢?

下图是进程地址空间、内核地址空间以及物理地址空间之间的联系,下面对几大地址空间的联系进行阐述。

 

 

650) this.width=650;" onsubmit onchange onunload onselect onreset> 

 

进程地址空间大家比较熟悉,很多人都知道通过虚拟内存机制,在32位平台上每个进程都可以获得4GB大小的地址空间。在32位Linux系统中,高1GB空间是每个进程共享的内核地址空间,0~3GB的空间是每个进程独享的地址空间。进程地址空间通过页表与物理地址空间建立联系,为了减少这种映射带来的开销损失,X86处理器硬件提供了TLB页表Cache。由于访存具有很高的时空局部性,因此TLB Cache的命中率很高,为虚拟内存机制的工程应用奠定了基础。从硬件上讲,进程虚拟地址映射最重要的模块是MMU,只有拥有MMU的处理器才可以支持虚拟地址机制。从软件上来讲,虚拟地址最重要的是页表管理。操作系统需要为虚拟内存建立页表,当TLB Cache Miss的时候,处理器会产生中断,然后进行页表映射,并且加载页表。在进程的用户空间,很多时候也希望直接对PCI的设备内存空间直接进行操作,例如很多应用程序想直接操作显卡内存,获得性能上的优势。为了达到这种目的,需要将处理器域PCI设备内存地址映射至进程地址空间。在Linux中提供了mmap函数实现IO地址与虚拟地址之间的映射。这种映射本质上与物理内存的映射是一样的,同样需要建立页表。

 

OS内核地址空间占据了3~4GB,共1GB大小的地址空间。其中,绝大部分地址(3G~Vmalloc_end)都是通过线性映射的方式进行映射,起始的一段物理内存空间被直接映射至内核空间。因此,内核空间的这种线性映射的地址也称为逻辑地址,这种地址无需页表进行映射,物理地址和逻辑地址之间的转换可以通过简单的偏移运算即可完成。内核空间中也存在虚拟地址,这段地址空间为Vmalloc_end~4GB。内核空间通过Vmalloc函数为这段虚拟地址空间建立页表,与物理内存建立联系。另外,在实际的系统中,除了物理内存之外,PCI设备同样占据处理器物理地址空间,内核空间想要访问PCI设备内存时,需要通过ioremap函数将处理器域PCI设备内存地址映射到内核空间。这种映射与vmalloc的方式一样,同样需要建立页表。我们可以看到,实际上,在32位Linux中,虚拟地址空间不是很大,默认情况下只有几百兆的空间。那么,如果用户想映射一块非常大的PCI设备内存空间至内核,怎么办呢?我想如果用户有这方面的需求,那么只能通过调整vmalloc_end参数将虚拟地址空间扩大。另外,在ARM嵌入式系统中,由于系统的内存资源有限,32位Linux预留的内核空间地址足够,而且物理内存通常会小于1GB,因此,PCI物理地址空间往往会落在1GB以内。在这种情况下,PCI设备内存的映射可以采用内核空间逻辑地址映射的方式,直接通过偏移操作进行物理地址和IO虚拟地址的转换,而无需调用ioremap进行页表操作(ARM嵌入式系统中会定义_REG宏实现虚实地址转换)。

 

650) this.width=650;" onsubmit onchange onunload onselect onreset> 

CPU物理地址空间理解上比较容易,就是处理器访问内存的地址空间。但是,值得注意的是,处理器内存地址空间并非全部用于物理内存的访问(DIMM),其中有一部分用于访问PCI设备地址空间。因此,如果处理器地址总线宽度为32位,拥有4GB地址空间,那么,其中只有一部分地址是用于访问物理内存的。因此,32位的地址总线无法支持4GB大内存。为了解决这个问题,Intel和AMD处理器在推出64位处理器之前采用了PAE技术,即Intel处理器将地址总线扩展到36位;AMD处理器扩展到40位。在软件的处理上,对页表也进行了修改,实现32位虚拟地址与36/40位物理地址的映射。从上图我们可以看出,当系统中安装的物理内存比较少时,例如只安装了1GB内存,那么物理地址空间还会存在空闲地址,4GB的顶端地址空间会分配给PCI设备,并且PCI设备地址空间与物理内存空间没有交叉。前几年这样的系统大量存在。但是,伴随着物理内存的日益廉价,大内存的系统大量出现,例如很多系统都配备大于4GB的内存。这样的系统会存在一个问题:PCI设备地址和物理内存存在地址交叉,处理器无法访问被PCI地址空间覆盖的物理内存。这也就在物理内存空间形成了一个地址空洞,这个空洞通常被称为PCI Hole。为了解决这个问题,芯片组提供了一组寄存器将被PCI设备地址覆盖的那部分物理内存重新映射到其它地址空间,从而实现将这部分遗失的内存回收。这种映射是通过硬件实现的。目前,在64位处理器上依然存在PCI Hole的问题,主要考虑到兼容性的问题。未来如果把PCI设备地址空间直接放到64位地址空间的顶端,PCI Hole这个问题也就不存在了。

 

650) this.width=650;" onsubmit onchange onunload onselect onreset> 

很多人在开发PCI设备的时候很疑惑,什么是PCI地址空间?PCI地址和处理器地址是一回事吗?其实在X86系统中,PCI地址和处理器地址在数值方面是相同的,但是这两个地址仍然属于两个不同的地址域。上面讨论的物理地址所指的就是处理器域的物理地址,是站在处理器的角度来看待访问地址的。PCI地址不是站在处理器角度的地址,而是PCI总线域的地址,是站在PCI桥、PCI设备看到的地址。如上图所示,PCI总线域地址和处理器域地址是通过PCI主桥(Host或者Complex)进行映射转换的。位于处理器的软件如果想访问PCI设备,那么直接采用处理器域的PCI设备地址,当然位于内核的驱动程序需要采用ioremap之后的虚拟地址进行访问。位于设备端的DMA控制器需要进行数据传输时,需要采用PCI总线域的地址。有趣的是,X86处理器对这两个空间的地址进行等值映射,所以看到的值是相同的,但是PowerPC则进行了线性映射,两个值是不相同的。

 

在看这个书时我规规矩矩的从前往后看,其实有些内容在后面会有很多理解和答案;先看下下面的图示,会很好理解PCI总线的整个架构:

        

 

 

PCI总线和其他总线比较有几个突出优点:
        1、PCI总线空间和处理器空间隔离

        PCI总线上的设备都有自己的PCI地址(PCI总线地址),处理器空间地址和PCI总线地址通过HOST主桥(HOST主桥就是连接处理器和PCI总线的一个设备器件)进行隔离。HOST主桥中有很多寄存器,这就可以使得处理器工作的频率和总线工作频率可以不一样,通过寄存器缓存数据。当处理器要访问PCI设备时,需要通过HOST主桥进行地址转换,把处理器地址转换成PCI总线地址,然后才能访问PCI设备;同理,PCI设备中的数据要往外走,也要通过HOST主桥进行地址转换。说到底,HOST主桥就是一个桥梁。

 

        2、可扩展性

        所谓可扩展性就是说在PCI总线上可以挂个PCI桥(PCI桥就是连接PCI总线和PCI总线的),然后PCI桥会推出一条PCI总线,该总线上又可以挂一个PCI桥,然后又可以推出一条PCI总线.......;但是一颗PCI总线树(PCI总线树以HOST主桥为树根PCI总线连接的所有设备)上的设备上限为256,其中包括HOST主桥和PCI桥;再提一个概念,上游总线和下游总线:上游总线是PCI桥靠近HOST主桥(或者说处理器)的一段总线,下游总线就是另外一端总线了;

        PCI桥的作用可以隔离PCI设备,不影响各条总线的带宽,总线x1上通讯和总线x2上是否通讯无关;同一条总线上的设备可以自由通讯,同HOST主桥下(PCI域)中设备可以通讯,而不需要处理器操作。当PCI桥出现故障时,如:PCI桥x1出现故障,那么PCI设备11和PCI设备12可以通讯,但是数据不能出去,当然也不影响其他总线上的通讯;

        如果HOST主桥支持Peer-to-Peer数据传输方式,那么设备可以跨PCI桥直接通讯,比如:PCI设备01和PCI设备12;

 

         3、动态配置机制

        PCI设备的地址可以由系统软件动态分配,解决了地址冲突。每一个PCI设备都有一个独立的配置空间,在配置空间中有该设备在总线上的地址系列的基地址,这个基地址也是有系统软件动态分配的。PCI桥的配置空间中有其PCI子树使用的地址范围;

 

        4、共享总线机制

        PCI总线上有多个设备,但他们需要通讯时,都必须向PCI总线仲裁器提出申请,当得到允许后才能在总线中发送数据;

 

        5、中断机制

        PCI总线上的设备可以使用四根中断请求信号INTA  INTB  INTC INTD向处理器发出中断请求;其中INTA是单功能设备,其他的是多功能设备;

 

PCI总线知识重点
        1、HOST主桥
         HOST主桥是用来隔离处理器的存储器域与PCI总线域的特殊桥片,管理PCI总线域。在其所管理的PCI设备中所有设备的配置空间都由HOST主桥通过配置读写总线周期访问的。
         HOST主桥可以通过设置Inbound寄存器来让不同的PCI总线域中的设备进行通讯;

        2、接口控制信号
        a、FRAME#信号(#表示低电压有效),该信号表示一个PCI总线事务的开始和结束,当设备获得PCI总线仲裁允许,得到使用权后,将置该信号为低电压。
        b、IRDY#信号,该信号由PCI主设备驱动(主设备可以主动发送读写命令,而从设备只能被动接受),其实就是PCI源设备驱动信号,表示主设备(源设备)已经把数据准备好了。如果总线为写事务,则表示在AD[31:0]上的数据有效;如果是读,则表示目标设备(从设备)已经准备好缓存了,主设备可以把数据发送到AD[31:0]上了;(这是个人的理解,和书上有点出入)
        c、TRDY#信号,该信号由目标设备驱动,该信号有效,表示目标设备已经将数据准备好了。如果总线是写事务,则表示目标设备已经准备好了缓存,可以把数据写入目标设备中;如果总线是读事务,表示设备需要的数据在AD[31:0]上有效了。
        d、stop#信号,表示目标设备请求主设备停止当前PCI总线的事务。目标设备可以要主设备对当前PCI总线事务进行重试(Retry,目标数据没有准备好),断连(Disconnect,目标设备不能接受较长的Burst操作),夭折(Target Abort,数据传输出错);
        e、IDSEL信号,PCI总线在进行配置读写总线事务时,使用该信号选择PCI目标设备;
        f、LOCK#信号,主设备可以使用该信号,将目标设备的某个资源锁定,以防止其他设备访问;
        看下面的PCI总线事务时序图:

 


        
        下面的时序图解释(书上的描述):        
        当一个 PCI 主设备需要使用 PCI 总线时,需要首先发送 REQ#信号,通过总线仲裁获得总线使用权,即 GNT#信号有效后,使用以下步骤完成一个完整 PCI 总线事务,对目标设备进行存储器或者 I/O 地址空间的读写访问。
        (1) 当 PCI 主设备获得总线使用权之后, 将在 CLK1 的上升沿置 FRAME#信号有效, 启动 PCI总线事务。当 PCI 总线事务结束后,FRAME#信号将被置为无效。
        (2) PCI 总线周期的第一个时钟周期(CLK1 的上升沿到 CLK2 的上升沿之间)为地址周期。在地址周期中,PCI 主设备将访问的目的地址和总线命令分别驱动到 AD[31:0]和 C/BE#信号上。如果当前总线命令是配置读写,那么 IDSEL 信号线也被置为有效,IDSEL 信号与 PCI 总线的AD[31:11]相连。
        (3) 当 IRDY#、TRDY#和 DEVSEL#信号都有效后,总线事务将使用数据周期,进行数据传递。当 IRDY#和 TRDY#信号没有同时有效时,PCI 总线不能进行数据传递,PCI 总线使用这两个信号进行传送控制。
        (4) PCI 总线支持突发周期,因此在地址周期之后可以有多个数据周期,可以传送多组数据。而目标设备并不知道突发周期的长度,如果目标设备不能继续接收数据时,可以 disconnect 当前总线事务。值得注意的是,只有存储器读写总线事务可以使用突发周期。一个完整的 PCI 总线事务远比上述过程复杂的多,因为 PCI 总线还支持许多传送方式,如双地址周期、fast back-to-back(快速背靠背)、插入等待状态、重试和断连、总线上的错误处理等一系列总线事务。

        3、仲裁信号
        当主设备(从设备被动操作,不需要仲裁信号)需要发起读写总线事务时(就是要占用总线使用权),必须先向仲裁器发起请求,当得到允许PCI总线使用权时,才可以开始通讯;而仲裁就是通过仲裁信号来处理的,仲裁信号有两个信号组成,REQ#和GNT#组成。每个仲裁器都要和主设备直接相连,所以仲裁器的信号接口数量将会限制PCI主设备的数量。解决办法是利用PCI桥推出新的PCI总线,因为在新的总线上也要有仲裁器。下面看下主设备和仲裁器的连接:

 

        


        请求过程:PCI 主设备使用 PCI 总线进行数据传递时,需要首先置 REQ#信号有效,向 PCI 总线仲裁器发出总线申请,当 PCI 总线仲裁器允许 PCI 主设备获得 PCI 总线的使用权后,将置 GNT#信号为有效,并将其发送给指定的 PCI 主设备。而 PCI 主设备在获得总线使用权之后,将可以置FRAME#信号有效,与 PCI 从设备进行数据通信。
  
        4、Posted和Non-Posted传送方式
        Posted总线事务是指PCI主设备向PCI目标设备发送数据时,数据到达PCI桥后,上游总线就可以结束该事务,该事务就由PCI桥和下游总线去处理。这可以提高效率和解决PCI总线拥挤的问题;
       Non-Posted总线事务是指PCI主设备向PCI目标设备发送数据时,数据必须到达目的设备后才能结束总线事务(此时上游总线不能提前结束);
       很显然这两种传送数据方式中Posted方式会高效些,但是PCI总线中规定:只有在存储器写请求时,才可以使用Posted总线事务(PMW = Posted Memory Write);其他的存储器读请求和I/O读写请求、配置读写请求只能使用Non-Posted总线事务;

        5、HOST处理器访问PCI设备
        这涉及到地址域问题,到第二章可以更方便的理解。HOST处理器对PCI设备的数据访问主要包括两个方面内容:一、处理器对PCI设备的存储器和I/O读写请求;二、处理器对PCI设备进行配置读写;
        处理器对PCI设备的I/O读写请求:如果有独立的I/O地址空间,则把PCI的I/O地址映射到存储域的I/O地址空间,然后处理器就可以通过  out/in  指令来访问PCI的数据;如果没有独立的I/O地址空间,则在HOST主桥初始化时,将PCI设备使用的I/O地址空间映射为处理器的存储器地址空间;然后处理器就可以直接访问这些映射出去的地址,当然访问这些地址时,会通过HOST主桥把这些请求转交到PCI总线上。
        处理器对PCI设备的存储器读写请求:将PCI设备使用的BAR空间映射到“存储器域”的存储器地址空间。然后处理器就可以通过存储器读写指令访问存储器地址空间(HOST主桥会转化为PCI总线事务;)

        6、PCI设备读写主存储器
        PCI设备与存储器直接进行数据交换的过程也被称为DMA。PCI总线进行DMA操作时,需要得到数据的大小和目的地址(PCI总线域的物理地址,HOST主桥会负责地址转换);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值