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. 工作中遇到的比较奇怪的一些sql(一些子查询)

    在列中进行子查询 1.在一个表中有多个员工ID,比如一个下单员工,一个修改订单的员工,可以使用在列中进行子查询,具体如下: ( SELECT staff_name FROM sp_staff_basi ...

  2. [洛谷1156]垃圾陷阱(DP)

    [Luogu1156] f[i]表示高度为i时的存活时间 Code #include <cstdio> #include <algorithm> #define N 110 u ...

  3. 为 dll (类库) 解决方案添加测试项目

    解决方案中新建项目, 添加引用, "解决方案" -> "项目", 选中即可, 而非直接添加 dll, 这会导致编译出错

  4. 初见spark-03(高级算子)

    最近心情不是很好,但是需要调节自己,真的需要调节自己,还是要努力,这个世界有我喜欢的人,有我追求的人,也许真的是守的住寂寞,耐得住繁华吧. 不说别的了,今天我们来接受啊spark的高级算子的系列 1. ...

  5. Android 第三方库RxLifecycle使用

    1.简单介绍RxLifecycle 1.1.使用原因. 在使用rxjava的时候,如果没有及时解除订阅,在退出activity的时候,异步线程还在执行. 对activity还存在引用,此时就会产生内存 ...

  6. android MotionEvent

    getAction() 获取事件的类型,这是一个组合值,由pointer的index值和事件类型值组合而成的 getActionMasked() 获取事件的类型,不具有其他信息 参考: http:// ...

  7. bootstrap重新设计按钮样式

    1.将btn的样式换成以下的样式 2.思路: (1)将原来的btn样式设置color:#FFF,同时text-shadow设置,这样原来的btn样式就会变淡了,后面再加上新的样式就可以覆盖掉 注意:要 ...

  8. ICG-智能代码生成器.(权限控制.融入平台).(表单引擎).(最低兼容IE8)

    请下拉滚动条... 代码生成器.附带客户端代码 个人平台:www.10086bank.com 界面: 1--首先是server制作界面(BS结构).直接上图:   2--点击提交生成一下文件: 各个代 ...

  9. QBASIC教程

    Qbasic 程序设计入门 BASIC(Beginner’s All-purpose Symbolic Instruction Code 的缩写,意为初学者通用符号指令代码)语言是在1964年由美国的 ...

  10. 【LoadRunner】LR编写Dubbo协议脚本

    一.Dubbo服务简介 Dubbo是一个分布式服务架构,把核心业务抽取出来作为独立的服务,使前端应用能更快速和稳定的响应. Dubbo服务工作原理:服务提供方提供接口,并提供接口的实现,提供方注册服务 ...