如果PCI设备访问的地址在某个CPU的Cache行中命中时,可能会出现三种情况。

第一种情况是命中的Cache行其状态为E,即Cache行中的数据与存储器中的数据一致;而第二种情况是命中的Cache行其状态为S。其中E位为1表示该数据在SMP处理器系统中,有且仅有一个CPU的Cache中具有数据副本;而S位为1表示在SMP处理器系统中,该数据至少在两个以上CPU的Cache中具有数据副本。

当Cache行状态为E时,这种情况比较容易处理。因为PCI设备(通过HOST主桥)写入存储器的信息比Cache行中的数据新,而且PCI设备在进行DMA写操作之前,存储器与Cache中数据一致,此时CPU仅需要在Snoop Phase使无效(Invalidate)这个Cache行,然后FSB总线事务将数据写入存储器即可。当然如果FSB总线事务可以将数据直接写入Cache,并将Cache行的状态更改为M,也可提高DMA写的效率,这种方式的实现难度较大,第3.3.5节将介绍这种优化方式。

Cache行状态为S时的处理情况与状态为E时的处理情况大同小异,PCI设备在进行写操作时也将数据直接写入主存储器,并使无效状态为S的Cache行。

第三种情况是命中的Cache行其状态为M(Modified),即Cache行中的数据与存储器的数据不一致,Cache行中保存最新的数据拷贝,主存储器中的部分数据无效。对于SMP系统,此时有且仅有一个CPU中的Cache行的状态为M,因为MESI协议规定存储器中的数据不能在多个CPU的Cache行中的状态为M。

我们假定一个处理器的Cache行长度为32B,即256b。当这个Cache行的状态为M时,表示这个Cache行的某个字节、双字、几个双字、或者整个Cache行中的数据比主存储器中含有的数据新。

假设HOST主桥访问的地址,在Snoop Phase,通过CPU进行总线监听后,发现其对应的Cache行状态为M。此时HOST主桥进行存储器写操作时,处理情况较为复杂,此时这些状态为M的数据需要回写到主存储器。

我们考虑如图3?8所示的实例。假定处理器的Cache使用回写(Write-Back)策略进行更新。在这个实例中,HOST主桥对存储器的某个地址进行写操作,而所有CPU通过FSB总线进行总线监听时发现,HOST主桥使用的这个目的地址在某个CPU的Cache行命中,此时这个CPU将置HITM#信号为0,并置HIT#信号为1,表示当前Cache行中含有的数据比存储器中含有的数据更新。


我们假设此时在Cache行中,阴影部分的数据比存储器中的数据新,而其他数据与存储器保持一致,即在这个Cache行中第0~3个双字的数据是当前处理器系统中最新的数据,而第4~7个双字中的数据与存储器保持一致。

如果PCI设备向存储器写的数据区域可以完全覆盖这些阴影部分,如对第0~5个双字进行写操作时,这种情况不难处理。此时CPU只需在总线监听阶段,将这个Cache行使无效,然后将数据写入存储器即可。因为完成这个存储器写操作之后,PCI设备写入的数据是最新的,而且这个最新的数据将完全覆盖在Cache行中阴影部分的数据,所以CPU只需要简单地将这个Cache行使无效即可。

然而PCI设备(HOST主桥)无法预先知道这些Cache行中的数据哪些是有效的,哪些是无效的,而仅知道命中了一个“被修改过”的Cache行,从而PCI设备(HOST主桥)无法保证能够对Cache行中有效数据进行覆盖。因此PCI设备对存储器进行写操作时,不能简单地使无效(Invalid)状态位为M的Cache行。

我们仍然以图3?8为例,考虑一个PCI设备将4个双字(第4~7个双字)的数据写入到一个存储器中,这4个双字所访问的数据在某个CPU的Cache行中命中,而且该Cache行的状态为M,而且这个Cache行的前4个双字曾被处理器修改过。

此时CPU对FSB总线监听时,不能简单将当前Cache行使无效,因为这个使无效操作将丢失阴影部分的有效数据。这个阴影部分中的有效数据并没有被PCI设备重新写入,因此在整个处理器系统中,这个阴影部分仍然包含最新的数据。将最新的数据丢弃显然是一种错误做法,将会导致处理器系统的崩溃。

为此HOST主桥需要专门处理这种情况,不同的HOST主桥采用了不同的方法处理这种情况,但无外乎以下三种方法。

(1)      CPU进行总线监听后发现,HOST主桥访问的数据命中了一个状态位为M的Cache行,此时存储器控制器将通知HOST主桥重试或者延时处理,并暂时停止HOST主桥发起的这次存储器写操作。随后CPU将状态位为M的Cache行与存储器进行同步后,再使无效这个Cache行。之后HOST主桥在合适的时机,重新发起被HOST主桥要求重试的总线事务,此时CPU再次进行总线监听时不会再次出现Cache命中的情况,因此HOST主桥可以直接将数据写入存储器。许多HOST主桥使用这种方法处理PCI设备的存储器写总线事务。

(2)      首先HOST主桥将接收PCI设备进行DMA写的数据,并将这些数据放入存储器控制器的一个缓冲区中,同时结束PCI设备的存储器写总线事务。之后CPU进行总线监听,如果CPU发现HOST主桥访问的数据命中了一个状态位为M的Cache行时,则这个Cache行放入存储器控制器的另一个缓冲区后,使无效这个Cache行。最后存储器控制器将这两个缓冲区的数据合并然后统一写入到存储器中。

(3)      HOST主桥并不结束当前PCI总线周期,而直接进行总线监听,如果CPU进行总线监听发现HOST主桥访问的数据命中了一个状态位为M的Cache行时,则将这个Cache行整体写入存储器控制器的缓冲区后使无效这个Cache行,之后HOST主桥开始从PCI设备接收数据,并将这些数据直接写入这个缓冲区中。最后HOST主桥结束PCI设备的存储器写总线周期,同时存储器控制器将这个缓冲区内的数据写入存储器。

以上这几种情况是PCI设备进行存储器写时,HOST主桥可能的处理情况,其中第1种方法最常用。而x86处理器使用的implicit writeback方式,与第2种方法基本类似。第3种方法与第2种方法并没有本质不同。

但是如果PCI设备对一个或者多个完整Cache行的存储器区域进行写操作时,上述过程显得多余。对完整Cache行进行写操作,可以保证将Cache行对应的存储器区域完全覆盖,此时Cache行中的数据在PCI设备完成这样的操作后,在处理器系统中将不再是最新的。PCI设备进行这样的存储器写操作时,可以直接将数据写入存储器,同时直接使无效状态为M的Cache行。

PCI总线使用存储器写并无效(Memory Write and Invalidate)总线事务,支持这种对一个完整Cache行进行的存储器写总线事务。PCI设备使用这种总线事务时,必须要事先知道当前处理器系统中CPU使用的Cache行大小,使用这种总线事务时,一次总线事务传递数据的大小必须以Cache行为单位对界。为此PCI设备必须使用配置寄存器Cache Line Size保存当前Cache行的大小,Cache Line Size寄存器在PCI配置空间的位置见图2?9。

存储器读(Memory Read)、存储器多行读(Memory Read Multiple)和存储器单行读(Memory Read Line)总线事务也是PCI总线中的重要总线事务,这些总线事务不仅和Cache有关,还和PCI总线的预读机制有关,本篇在第3.4.5节中重点介绍这些总线事务。

3.3.4 PCI设备进行DMA写时发生Cache命中的更多相关文章

  1. 3.3.5 DMA写时发生Cache命中的优化

    在许多高性能处理器中,还提出了一些新的概念,以加速外设到存储器的DMA写过程.如Freescale的I/O Stashing和Intel的IOAT技术. 如图3?8所示,当设备进行存储器写时,如果可以 ...

  2. 3.3.2 PCI设备对不可Cache的存储器空间进行DMA读写

    在x86处理器和PowerPC处理器中,PCI设备对"不可Cache的存储器空间"进行DMA读写的过程并不相同.其中PowerPC处理器对"不可Cache的存储器空间&q ...

  3. 3.2 PCI设备的数据传递

    PCI设备的数据传递使用地址译码方式,当一个存储器读写总线事务到达PCI总线时,在这条总线上的所有PCI设备将进行地址译码,如果当前总线事务使用的地址在某个PCI设备的BAR空间中时,该PCI设备将使 ...

  4. 3.1 PCI设备BAR空间的初始化

    在PCI Agent设备进行数据传送之前,系统软件需要初始化PCI Agent设备的BAR0~5寄存器和PCI桥的Base.Limit寄存器.系统软件使用DFS算法对PCI总线进行遍历时,完成这些寄存 ...

  5. 008 PCI设备BAR空间的初始化

    一.PCI设备BAR空间的初始化 在PCI Agent设备进行数据传送之前,系统软件需要初始化PCI Agent设备的BAR0~5寄存器和PCI桥的Base.Limit寄存器.系统软件使用DFS算法对 ...

  6. 3.3.3 PCI设备对可Cache的存储器空间进行DMA读写

    PCI设备向"可Cache的存储器空间"进行读操作的过程相对简单.对于x86处理器或者PowerPC处理器,如果访问的数据在Cache中命中,CPU会通知FSB总线,PCI设备所访 ...

  7. 2.3 PCI桥与PCI设备的配置空间

    PCI设备都有独立的配置空间,HOST主桥通过配置读写总线事务访问这段空间.PCI总线规定了三种类型的PCI配置空间,分别是PCI Agent设备使用的配置空间,PCI桥使用的配置空间和Cardbus ...

  8. 利用WinDriver开发PCI设备驱动程序

    摘要 WinDriver是Jungo公司出版的一个设备驱动程序开发组件,它可以大大加速PCI设备驱动程序的开发.作者在实际的项目中采用了WinDriver来开发设备驱动程序,取得了相当好的运行效果.从 ...

  9. PCI 设备详解一

    2016-10-09 其实之前是简单学习过PCI设备的相关知识,但是总感觉 自己的理解很函数,很多东西说不清楚,正好今天接着写这篇文章自己重新梳理一下,文章想要分为三部分,首先介绍PCI设备硬件相关的 ...

随机推荐

  1. Tomcat8远程访问manager,host-manager被拒绝403

    Tomcat部署在服务器之后在服务器本地访问manager和host-manager成功(即127.0.0.1:8080或者localhost:8080),但使用测试主机访问tomcat的manage ...

  2. FC经典游戏还原之:松鼠大作战2

    版权声明:本文原创发布于博客园"优梦创客"的博客空间(id:raymondking123) 原帖地址:http://www.cnblogs.com/raymondking123/p ...

  3. Django之反向生成url

    首先新建一个项目test_url,项目包含一个名为app01的应用 在urls.py文件中生成如下内容 from django.conf.urls import url from django.sho ...

  4. CentOS下内存使用率查看

    freetotal        used        free      shared     buffers      cachedMem:        1815340     1628680 ...

  5. GreenDao 兼容升级,保留旧数据的---全方面解决方案

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  6. BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster [广义后缀自动机]

    JZPGYZ - Sevenk Love Oimaster     Oimaster and sevenk love each other.       But recently,sevenk hea ...

  7. 【转】Android UI 五种布局

    在一个Android应用中,Layout是开发中的一个很重要环节,Layout是组成UI不可缺少的一部分. ## Android UI 核心类 在Android应用构建UI的方法有以下几种: 单纯使用 ...

  8. Go基础之--反射

    反射:可以在运行时动态获取变量的相关信息 反射需要导入reflect 反射中重要函数的演示 反射有几下几个重要的函数:reflect.TypeOf :获取变量的类型,返回reflect.Type类型r ...

  9. Lua利用cjson读写json

    前言 本文结合本人的实际使用经验和代码示例,介绍如何在Lua中对json进行encode和decode.我这里采用的是Lua CJson库,是一个高性能的JSON解析器和编码器,其性能比纯Lua库要高 ...

  10. git 添加远程仓

    1.新建远程项目 2.提交代码 $ makdir ~/hello-world    //创建一个项目hello-world    $ cd ~/hello-world       //打开这个项目   ...