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. Matplotlib 图表的基本参数设置

    1.图名,图例,轴标签,轴边界,轴刻度,轴刻度标签 # 图名,图例,轴标签,轴边界,轴刻度,轴刻度标签等 df = pd.DataFrame(np.random.rand(10,2),columns= ...

  2. VUE前端无法启动

    cd 到client中,使用npm run dev ,一直卡着也不报错,启动不了项目 可以直接使用 ,需要进入root目录进行 cnpm install npm -g

  3. 移动端的拖拽排序在react中实现 了解一下

    最近做一个拖拽排序的功能找了好几个有一个步骤简单,结合redux最好不过了,话不多说上代码 第一步: npm install react-draggable-tags --save 第二步 sort. ...

  4. Android 微信支付步骤

    以前自己写过微信支付,今天让我用h5调用微信支付,结果还浪费了点时间,虽然时间不长. 1.导入jar包 .微信提供的jar包 2.写你的微信支付的代码,其实如果参数都有了就一段代码: public v ...

  5. shell编程——参数传递

    1.Linux Shell参数引用 $0 这个程式的执行名字$n 这个程式的第n个参数值,n=1..9$* 这个程式的所有参数$# 这个程式的参数个数$$ 这个程式的PID$! 执行上一个背景指令的P ...

  6. 【Hazard of Overfitting】林轩田机器学习基石

    首先明确了什么是Overfitting 随后,用开车的例子给出了Overfitting的出现原因 出现原因有三个: (1)dvc太高,模型过于复杂(开车开太快) (2)data中噪声太大(路面太颠簸) ...

  7. 【Max Points on a Line 】cpp

    题目: Given n points on a 2D plane, find the maximum number of points that lie on the same straight li ...

  8. yum源是什么

    我们安装软件的时候需要下载软件,将很多软件放在一起就是源.软件安装包的来源. 所以yum源就是软件安装包来源. 如果我们是在线的,他会在网上给你下载安装包,如果是离线的没有网络.那么就只能配置本地的y ...

  9. python基础实践(五)

    # -*- coding:utf-8 -*-# Author:sweeping-monk# -*-操作列表-*-Traverse_the_list = ['guanfu','xiaole','fang ...

  10. (原、整)Unreal源码 CoreUbject- Uobject

    (原.整) Unreal源码 CoreUbject- Uobject 类别                    [随笔分类]Unreal源码搬山 @author:白袍小道 随缘那啥 这里还是属于UE ...