CPU上处理的中断可以分成“硬件中断”和“软件中断”两类,比如网卡产生的中断称为硬件中断,而如果是软件使用诸如"int 0x10"(X86平台上)这样的指令产生中断称为软件中断,硬件中断是异步的,其发生的时机是不可知的,但是软件中断是同步的,CPU是“确切”知道其发生的时机的。

  同样的,在GPU看来,中断也可以分成“硬件中断”和“软件中断”两类,比如热插拔事件或者vblank事件都会产生“硬件中断”,这些事件在GPU看来是异步的,GPU不知道这些事情何时发生。GPU也可以使用类似CPU的int指令那样产生中断,考虑这样一种情形:驱动向硬件发送了绘图命令后必须等到硬件执行完了这些命令后才能进行后续的操作,否则硬件的上一次命令没有执行完就继续执行下一次命令会导致错误。前面介绍scratch寄存器的时候提及过可以在命令末尾添加一条写scratch寄存器的命令,发送命令之后驱动使用轮询的方式轮询scratch寄存器,当然这种场合使用轮询肯定是不合适的,实际上显卡可以采用软中断机制,在完成绘图命令后执行一个类似“int xx”的命令产生中断,这里GPU是“确切”知道中断发生的时机的----即在绘图命令完成的时候。

  前面提到的fence就是这种“软件中断”的具体应用。

  在上一篇blog中看到,fence是按照下面的步骤使用的:

  radeon_fence_create->radeon_fence_emit->radeon_fence_wait

  radeon驱动中的fence机制用于同步GPU和CPU,Fence机制的实现依赖GPU产生的软中断和scratch寄存器。CP完成一个绘图操作后执行产生中断的命令,向CPU发送一次中断信号,这里的“产生中断的命令”其实就是写CP_INT_STAT寄存器。

  在radeon驱动代码中,完成向ring buffer中填充绘图命令后,会调用radeon_fence_emit函数(参考GPU命令包章节的代码),在r600显卡上最终调用r600_fence_ring_emit函数,该函数中有如下代码:

2327 void r600_fence_ring_emit(struct radeon_device *rdev,

2328               struct radeon_fence *fence)

......

2347         /* Emit fence sequence & fire IRQ */

2348         radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));

2349         radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg -

PACKET3_SET_CONFIG_REG_OFFSET) >> 2));

2350         radeon_ring_write(rdev, fence->seq);

2351         /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */

2352         radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));

2353         radeon_ring_write(rdev, RB_INT_STAT);

  这里让GPU执行的命令(2352-2353行代码)类似在操作系统中让CPU执行的“int xx” 指令,这两句代码的意思是写CP_INT_STATUS寄存器,但是注意到寄存器CP_INT_STATUS 是一个中断状态寄存器,驱动通过MMIO的方式是无法写这个寄存器的,但是如果CP写这个寄存器就会产生“软件中断”(当前观察到的现象是这样的,是否正确)。

  通常硬件会有一些寄存器用于表示中断相关信息,在硬件产生中断的时候将相关信息写入寄存器中,驱动读取这些寄存器就能知道和中断相关的具体信息。Radeon GPU中除了有这类寄存器表明中断类型外,scratch寄存器可以派上用场。

  在内核radeon驱动中,每一个fence都被分配了唯一的ID号(seq),在radeon_fence_emit中有如下代码:

71 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence )

......

80     fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);

  2340-2350行代码fence->seq的值被写入一个scratch寄存器,所以当绘图命令完成中断产生之前scratch寄存器就会是被置为这个唯一的ID号,读取scratch寄存器就能够知道是哪一次绘图命令产生的中断。

  Fence中断处理函数是radeon_fence_poll_locked。首先读取fence编号,知道是那一次fence操作产生的中断,当产生中断的fence编号是最后一个编号时,需要将最后一个fence编号赋值为当前编号,同时更新fence定时器。如果不是最后一个fence编号产生的中断,就需要判断定时器,然后唤醒fence中断队列。

PS.  这篇文章里只描述了软件中断的硬件机制,linux内核drm驱动关于显卡中断的代码也有一套比较复杂的框架,需要深入分析才能理解其全貌。

【原创】Linux环境下的图形系统和AMD R600显卡编程(7)——AMD显卡的软件中断的更多相关文章

  1. 【原创】Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

    Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区 ...

  2. Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

    转:https://www.cnblogs.com/shoemaker/p/linux_graphics01.html Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过 ...

  3. 【原创】Linux环境下的图形系统和AMD R600显卡编程(2)——Framebuffer、DRM、EXA和Mesa简介【转】

    转自:http://www.cnblogs.com/shoemaker/p/linux_graphics02.html 1. Framebuffer Framebuffer驱动提供基本的显示,fram ...

  4. 【原创】Linux环境下的图形系统和AMD R600显卡编程(5)——AMD显卡显命令处理机制

    通常通过读写设备寄存器对设备进行编程,在X86系统上,有专门的IO指令进行编程,在其他诸如MIPS.SPARC这类系统上,通过将设备的寄存器映射到内存地址空间直接使用读写内存的方式对设备进行编程. R ...

  5. 【原创】Linux环境下的图形系统和AMD R600显卡编程(3)——AMD显卡简介

    早期的显卡仅用于显示,后来显卡中加入了2D加速部件,这些部件用于做拷屏,画点,画线等操作.随着游戏.三维模拟以及科学计算可视化等需要,对3D的需求逐渐增加,早期图形绘制工作由CPU来完成,要达到真实感 ...

  6. 【原创】Linux环境下的图形系统和AMD R600显卡编程(9)——R600显卡的3D引擎和图形流水线

    1. R600 3D引擎 R600核心是AMD一款非常重要的GPU核心,这个核心引入了统一处理器架构,其寄存器和指令集同以前的GPU 都完全不同,对其编程也有比较大的区别. 图1显示了R600 GPU ...

  7. Linux环境下的图形系统和AMD R600显卡编程(2)——Framebuffer、DRM、EXA和Mesa简介

    转:https://www.cnblogs.com/shoemaker/p/linux_graphics02.html 1. Framebuffer Framebuffer驱动提供基本的显示,fram ...

  8. 【原创】Linux环境下的图形系统和AMD R600显卡编程(6)——AMD显卡GPU命令格式

    前面一篇blog里面描述了命令环缓冲区机制,在命令环机制下,驱动写入PM4(不知道为何会取这样一个名字)包格式的命令对显卡进行配置.这一篇blog将详细介绍命令包的格式. 当前定义了4中命令包,分别是 ...

  9. 【原创】Linux环境下的图形系统和AMD R600显卡编程(10)——R600显卡的3D引擎编程

    3D图形处理流水线需要流经多个硬件单元才能得到最后的渲染结果,流水线上的所有的硬件单元必须被正确编程,才能得到正确的结果. 总体上看,从图形处理流水线的源头开始,需要准备好vertex和index,在 ...

随机推荐

  1. C++ 基础 引用

    1.引用的本质 int b = 10; int &a = b; 等效于: int * const a = &b; 由于 a 是 const声明,所以一旦定义无法修改,所以要在定义时就要 ...

  2. C语言进阶——变量属性05

    C语言变量属性: C语言的变量可以有自己的属性 在定义变量的时候加上“属性”关键字 “属性”关键字指明变量的特有意义 语法:property type value_name; auto关键字: aut ...

  3. C++机试笔记

  4. Maven学习 (二) Eclipse 上安装 Maven3插件

    eclipse 安装插件的方式最常见的有两种: 1. 一种是在线安装,这貌似是用的最多的,就是:Help  -->  Install New Software,然后输入 HTTP 地址来安装,但 ...

  5. 当Hadoop 启动节点Datanode失败解决

    Hadoop 启动节点Datanode失败解决 [日期:2014-11-01] 来源:Linux社区  作者:shuideyidi [字体:大 中 小] 当我动态添加一个Hadoop从节点的之后,出现 ...

  6. Redmine部署到Windows Azure

    有幸,今天可以尝试将Redmine部署到Windows Azure中,记下点滴,方便大家查阅 步骤一:Windows Azure中安装Ubuntu VM 遇到的问题,创建VM时会提示云服务.云存储订阅 ...

  7. 《Cracking the Coding Interview》——第12章:测试——题目6

    2014-04-25 00:53 题目:你要如何测试一个分布式银行系统的ATM机? 解法:ATM是Automatic Teller Machine,取钱的.我想了半天,没找到什么很清晰的思路,也许是因 ...

  8. 【Pascal's Triangle】cpp

    题目: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,R ...

  9. 性能测试之siege

    一.siege介绍 Siege是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数 ...

  10. NGUI-Tweens

    Tweens(补间动画) 补间动画有很多种: 这里以Tween Height为例: 项目层次: btn为一个按钮,group为一组图片精灵,预览图如下: 第一步:先为每个item附加一个Tween H ...