AMD GPU 内核驱动架构分析(一)

这篇具有很好参考价值的文章主要介绍了AMD GPU 内核驱动架构分析(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

和CPU相比,GPU中包含了大量的并行计算单元,适合处理像素,矩阵,坐标等大量同类型的数据,因此,很多LINUX上的应用程序为了能够利用GPU的加速功能,都试图和GPU直接打交道,因此,系统中可能有多个组件或者程序同时使用GPU,比如桌面系统中OpenGL的实现MESA。这样会带来一个问题,就是多个进程并发访问GPU,如果控制不好,势必会造成系统工作不稳定,为了解决这样的问题,LINUX内核开发者在内核中设计了DRM模块,所有访问GPU的操作都通过DRM统一管理,由DRM来统一协调对GPU的访问,所以,在Linux系统中,各类GPU驱动,包括NVIDIA,AMD等大厂的GPU驱动都是集成在DRM框架中的.以AMD GPU驱动为例,AMD GPU的内核驱动结构上是一个复杂的软件堆栈,负责管理和控制AMD图形硬件,以便应用程序可以与GPU进行通信并利用其图形处理能力,这些能力都是通过DRM提供的,DRM屏蔽了不同显卡厂家的硬件差异,以统一一致的接口向上层提供服务。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

以下是AMD GPU内核驱动的主要组成部分:

硬件抽象层(HAL)

  • HAL是位于底层的部分,负责与GPU硬件之间的通信。它提供了一个抽象的接口,使上层的驱动和应用程序可以访问GPU的功能和寄存器,而不需要了解具体的硬件细节。

图形命令处理器(GCP)

  • GCP负责接收、解析和执行应用程序发送的图形命令。它将应用程序的图形请求翻译成GPU硬件可以理解的指令,以执行绘图操作和渲染任务。

AMDGPU内核驱动

  • 这是AMD GPU驱动的核心部分,运行在操作系统的内核空间。它与硬件通信,管理GPU资源(如显存和显卡寄存器),执行调度和任务分配,以确保多个任务在GPU上正确运行。

GPU用户空间驱动

  • GPU用户空间驱动是运行在操作系统的用户空间的组件,它与AMDGPU内核驱动协同工作,提供对GPU的高级控制。它包括OpenGL和Vulkan驱动程序,以及OpenCL运行时库,允许应用程序与GPU进行图形和通用计算任务的交互。

AMDGPU-PRO

  • AMDGPU-PRO是AMD的专业级GPU驱动,主要用于支持专业应用程序和工作负载,如CAD、3D建模和科学计算。它提供了更丰富的特性和支持,包括对专业图形API和库的更好的兼容性。

AMD ROCm

  • AMD ROCm(Radeon Open Compute)是一个开源的GPU计算平台,旨在支持GPU加速的深度学习和高性能计算工作负载。它包括ROCm内核驱动和ROCm用户空间工具,为GPU计算提供了强大的支持。

总之,AMD GPU的内核驱动结构是一个多层次的系统,由硬件抽象层、内核驱动、用户空间驱动和专业级组件组成,以便应用程序可以有效地利用AMD GPU的图形和计算能力。这些组件共同协作,确保GPU能够执行各种图形和计算任务。

图中的箭头表示源模块会调用箭头指向的目标模块中的函数或者符号,这种调用通常和LINUXN内核中的框架驱动注册相对应,即由架构中低层次的模块向框架中高层次的模块注册操作句炳,所以实际的架构层次应该是上下颠倒的,也就是说,从架构上看,应该是DRM在上,而AMDGPU在最底层,只有扇入口,没有扇出口。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

虽然不清楚N卡的官方驱动的实现细节,但作为对比,从模块拓扑来看,和AMD GPU应用架构很类似:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

NVIDIA NOUVEAU开源驱动同样集成于DRM框架中,模块之间的依赖比AMD更加简洁一些,不过这可能意味着驱动的实现更加复杂。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

单纯从核显的角度作对照,可能拿INTEL的核显作为对比最为合适,毕竟两者面对的是同一个市场,INTEL的核显I915驱动拓扑如下:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

再看一个,下图是VIRTUALBOX中基于虚拟GPU的DRM框架,vmwgfx.ko是虚拟GPU的KMD.对比三张拓扑,可以看到DRM和GPU之间的关系大同小异,都是KMD将自身注册进入DRM驱动框架内部,UMD通过DRM框架调用KMD的实现(模块关联图架构上是从底层到上层的,如果从调用层次上看,应该把图上下颠倒)

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

同样作为虚拟机,vmware是直接基于vmwgfx提供KMD的角色:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

小结:

显卡是DRM设备的后端:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

所以,进一步抽象GPU和DRM框架的架构,建立它们之间的联系,似乎是这样的:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

DRM以字符设备IOCTL命令的形式向用户态提供功能,IOCTL的实现有两种,一种是DRM通用的CMD,另一种是GPU specific实现,GPU Specific的CMD范围在(0x40-0xA9).

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

以锐龙R5600G核显VEGA7为例,其支持DX12,Vulkan,OpenCL,OpenGL等多种用户态编程接口,这些接口在GPU软件栈中的作用基本上相当于Posix在CPU侧的作用,是构成GPU生态系统(渲染,计算,多媒体)的基石,非常重要。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMDKFD驱动配置编译架构分析

amdkfd目录最终会和amdgpu目录的源码一同编译,生成amdgpu.ko,AMD GPU驱动,主要是指amdgpu.ko.

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

和AMDGPU相关的配置:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMDGPU驱动初始化

AMDGPU由多个硬件处理单元组成(IP核block),任何一条GPU的渲染命令,其最终都是发送到GPU的硬件单元上,硬件单元可以处理一些通用的渲染
命令,也可能处理一些专有渲染命令,因此一条GPU渲染命令需要指明它发往的硬件单元。实际上,mesa驱动针对GPU的每个硬件单元都抽象了具体的结构,当硬件单元驱动想给自己对应的硬件发送GPU命令时,就需要设置硬件的类型。就是这里的ring_type。为什么叫ring_type呢,因为
每个硬件处理单元和CPU之间时通过ring buffer传递渲染命令的,每个硬件单元上都有一个或者多个ring buffer,所以ring_type就是GPU硬件单元的类型。从DMESG LOG信息可以看到,AMDGPU初始化时,初始化了compute, gfx, sdma, jpeg_dec, vcn_enc,vcn_dec,kiq等ring.

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

注册的调用顺序为:

amdgpu_pci_probe->amdgpu_driver_load_kms->amdgpu_device_init->amdgpu_device_ip_early_init->amdgpu_discovery_set_ip_blocks->amdgpu_discovery_set_ih_ip_blocks->amdgpu_device_ip_block_add.

最终由amdgpu_device_ip_block_add完成设备的注册。然后会在如下调用堆栈中完成RING调度线程的初始化。

...->amdgpu_device_init->amdgpu_device_ip_init->amdgpu_ring_init->amdgpu_device_init_schedulers->drm_sched_init->kthread_run(drm_sched_main,...

AMDGPU驱动会为每个RING创建一个内核线程,专门负责对这个RING上的COMMAND PACKET进行调度。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMDGPU对应的DRM驱动结构体drm_driver为amdgpu_kms_driver对象,定义在文件amdgpu_drv.c中,在启用AMDGPU系统上,这个结构体即是DRM框架的后端。

2791 static const struct drm_driver amdgpu_kms_driver = {
2792         .driver_features =      
2793         ¦   DRIVER_ATOMIC |     
2794         ¦   DRIVER_GEM |        
2795         ¦   DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
2796         ¦   DRIVER_SYNCOBJ_TIMELINE,
2797         .open = amdgpu_driver_open_kms,
2798         .postclose = amdgpu_driver_postclose_kms,
2799         .lastclose = amdgpu_driver_lastclose_kms,
2800         .ioctls = amdgpu_ioctls_kms,
2801         .num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms),
2802         .dumb_create = amdgpu_mode_dumb_create,
2803         .dumb_map_offset = amdgpu_mode_dumb_mmap,
2804         .fops = &amdgpu_driver_kms_fops,
2805         .release = &amdgpu_driver_release_kms,
2806                                 
2807         .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
2808         .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
2809         .gem_prime_import = amdgpu_gem_prime_import,
2810         .gem_prime_mmap = drm_gem_prime_mmap,
2811                                 
2812         .name = DRIVER_NAME,    
2813         .desc = DRIVER_DESC,    
2814         .date = DRIVER_DATE,    
2815         .major = KMS_DRIVER_MAJOR,
2816         .minor = KMS_DRIVER_MINOR,
2817         .patchlevel = KMS_DRIVER_PATCHLEVEL,
2818 }; 

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

DRM Driver initialization  process are launched by AMD GPU PCIE Driver probe procedure.

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMDKFD驱动

AMD的amdkfd 可以理解为在 DRM 子系统中提供了 CPU 与 GPU 沟通的快速通道,使得两者可以平等的访问内存资源而无需额外拷贝。AMDKFD驱动在内核中通过CONFIG_HSA_AMD配置项使能/关闭,关闭后整个KFD的注册全部为空函数,系统自然也就不会创建/dev/kfd设备节点。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

KFD和GPU的渲染,多媒体功能都隐藏在内核DRM框架后面,两个是并行独立的模块,KFD的存在目的是为了给HPC计算场景提供一个快速访问GPU的通道,对于DRM渲染功能来说,并不是必不可少的,所以当关闭CONFIG_HSA_AMD后,并不影响正常的DRM渲染功能。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

具体分析可以参考这篇对HSA架构的分析:

AMD HSA 异构计算架构和AMD-KFD内核驱动&NVIDIA内核驱动_papaofdoudou的博客-CSDN博客

AMDGPU固件

amdgpu固件分布在/lib/firmware/amdgpu,/lib/firmware/amd两个目录, GPU驱动加载时通过内核API request_firmware装载进GPU。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMDGPU驱动初始化流程

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

GPU工作context

1.pasid是 per file的,不是per进程的.

2.每个struct file下可以创建多个context,共享同一个PASID(drm设备open时分配的).

3.pasid在不同的struct file是不同的,便于细粒度控制不同的打开上下文。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

释放PASID堆栈,发生在文件关闭的时候:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

前面截图中,线程分配了CTXID 1,2,3,4,退出时只释放了1,2,3。 4实际上是在这里释放的:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

gpu_sched原理

gpu 的调度策略如下图所示:

1.每个context定义一个三维的entity表,作为某个指定IP Block的某个RING(比如GFX支持四个RING,而且VCN支持2个RING)下某个JOB的容器。

2.驱动初始化时,为每个ring创建一个调度线程和四个优先级调度队列,全系统唯一。

3.entity是JOB的容器,JOB中包含具体的由GPU执行的某个操作的渲染指令或者解码指令,而entity代表了用户的操作ring buffer,它和某个RING上的某个优先级队列管理结构对应。

4.不同上下文的entity如果分配在同一个IP BLOCK的同一个RING上的同优先级,则通过优先级队列中struct drm_sched_rq->rb_tree_root红黑数管理,管理值为最久等待时间oldest_job_waiting,通过JOB提交时调用ktime_get获得。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

调度策略

entity是job的容器,drm_sched_main 调度线程在选择可以运行的entity的时候,涉及到一个调度策略问题,在6.X内核之前,从sched_rq中选择可以运行JOB的entity使用的是优先级+roundrobin调度策略,首先安按照sched_rq 3/2/1/0 的优先级顺序选择一个最高优先级的sched running queue,之后,在当前选择的sched_rq里面根据round robin选择一个可以运行的entity投入运行。这种方式下,sched_rq是通过list_head链表管理之下的所有entity的。

下图表示和调度相关的几个关键数据结构之间的关系:

1.struct amdgpu_ring和struct drm_gpu_scheduler是一对一的关系,每个GPU ring对应一个内核调度对象,对应一个数据结构。

2.每个RING(调度对象)包含四个struct drm_sched_rq对象。

3.每个struct drm_sched_rq对象包含了多个entity对象,每个entity对应用户空间某个命令队列。

4.每个entity对象连接起多个struct drm_sched_job对象,代表应用的某笔渲染命令。

5.entity对象会反向指向其所在的struct drm_sched_rq对象,同时通过struct drm_gpu_scheduler        **sched_list指针数组间接引用了其可以运行于其上的调度器对象,意味着某个entity可以选择投入到多个相同性质的ring中的任意一个去执行,比如有多个渲染ring,计算ring,则相应队列可以选择任何一个ring执行,为复杂均衡提供了一种可能。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

而6.X内核之后,调度策略增加了一种模式,就是FIFO,这种方式是通过红黑树对entity进行管理,上图中绘制的就是这种方式。 为了兼容老的RR方式,AMDGPU模块定义了drm_sched_policy变量进行控制,在FIFO这种方式下,红黑树使用JOB投入时间作为键值进树。直到调度器将时间窗口内的JOB全部取完后,spcs queue未空,下面的FIRST逻辑再次运行时,彩才会切换entity在红黑数中的位置。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

简而言之,调度器在选择entity的时候,会判断drm_sched_policy的配置,根据调度策略的不同选择使用FIFO还是round robin策略。

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMDGPU对FIFO调度的支持是在6.0内核开始的,commit id为:08fb97de03aa2205c6791301bd83a095abc1949c, comment里面详细解释了针对的问题和修改思路,可以参考:

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

AMD GPU 内核驱动架构分析(一),GPU,AMD,GPU

清华linux-stable镜像仓库:  

https://mirrors.tuna.tsinghua.edu.cn/git/linux-stable.git 

参考资料

https://www.x.org/docs/AMD/old/R5xx_Acceleration_v1.5.pdf

https://blog.csdn.net/tugouxp/article/details/131619250?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22131619250%22%2C%22source%22%3A%22tugouxp%22%7D

dma-fence简析以及使用demo_papaofdoudou的博客-CSDN博客

AMD GPU虚拟化_amd显卡虚拟化_shuaifeng.zhang的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-707075.html


结束

到了这里,关于AMD GPU 内核驱动架构分析(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux内核源码分析 1:Linux内核体系架构和学习路线

    好久没有动笔写文章了,这段时间经历了蛮多事情的。这段时间自己写了一两个基于不同指令集的 Linux 内核, x86 和 RISC-V 。期间也去做了一些嵌入式相关的工作,研究了一下 ARM 指令集架构。 虽然今年九月份我就要申请了,具体申请 AI 方向还是机器人、嵌入式、操作系统、

    2024年02月07日
    浏览(42)
  • 【Linux驱动】Linux--USB免驱摄像头驱动分析(基于5.4内核)

    【Linux应用】Linux–V4L2摄像头应用编程 【Linux】Linux–V4L2视频驱动框架 【Linux驱动】Linux–虚拟摄像头vivid驱动分析(基于5.4内核) 本文基于Linux 5.4内核,虚拟摄像头驱动文件在 driversmediausbuvc 目录下,本文深入分析了5.4内核下UVC驱动的实现及调用过程。读完本文可以对UVC驱

    2024年02月10日
    浏览(32)
  • linux-2.6.22.6内核i2c驱动框架源码分析

    i2c是常见的通信协议,协议比较简单,只有数据和时钟两条线(SDA和SCL),i2c的通信分为主机和从机,主机一般占主导地位,从机可以有多个。 i2c通信的数据格式为(SDA上的数据):开始的7位里面指定了设备地址(因为有多个从机),第8位是读或写信号,表示此次传输是读还

    2024年02月11日
    浏览(41)
  • Linux内核源码分析 (B.2)虚拟地址空间布局架构

    Linux内核只是操作系统当中的一部分,对下管理系统所有硬件设备,对上通过系统调用向 Library Routine 或其他应用程序提供API接口。 内存管理可以通过以下三个维度进行介绍: 用户空间 相当于应用程序使用 malloc() 申请内存,通过 free() 释放内存。 malloc() / free() 是 glibc 库的内

    2024年02月09日
    浏览(51)
  • AMD GPU虚拟化

    在GPU虚拟化场景下Linux内核层一般需要二套driver,一套是是常规的VF driver(比如amdgpu.ko、amdkfd.ko), 另一套是PF driver(比如gim.ko)用来sriov的初始化(SR-IOV extended capability),vfid的配置等。其中PF driver运行于Host侧,而VF driver运行于虚拟化VM侧,gim.ko和amdkfd.ko/amdgpu.ko之间可以通过Mailbox和

    2024年02月06日
    浏览(33)
  • AMD GPU内存管理(1):概览

    参考内核代码:Linux-6.1/driver/gpu/drm/amd HMM 待更新...... dumb buffer create/map         在AMDGPU的Graphics业务中,用到了GEM(Graphics Execution Manager),它是用于内核内部管理图形缓冲区,用户空间进程可以通过GEM来创建、处理和销毁GPU中视频内容的内存对象。如下是AMD GPU注册得drm_driver回

    2023年04月17日
    浏览(21)
  • 【SA8295P 源码分析】66 - Android 侧内核层 TouchScreen Panel(TP)触摸屏驱动源码分析

    【源码分析】 因为一些原因,本文需要移除, 对于已经购买的兄弟,不用担心,不是跑路, 我会继续持续提供技术支持, 有什么模块想学习的,或者有什么问题有疑问的, 请私聊我,我们 +VX 沟通技术问题,一起学习,一起进步 接下来,我一一私聊已经购买的兄弟添加V

    2024年02月11日
    浏览(42)
  • AMD GPU安装运行stable diffusion

    本文操作环境为Windows10/11+AMD AI绘画是一种利用人工智能技术进行绘画的方法。它可以通过机器学习算法来学习艺术家的风格,并生成类似于艺术家的作品。最近,AI绘画技术得到了很大的发展,许多公司和研究机构都在进行相关的研究和开发。例如,OpenAI最近推出了一个名为

    2024年02月05日
    浏览(39)
  • AMD GPU内存管理(2):GEM/TTM

    参考内核代码:Linux-6.1/driver/gpu/drm/amd 一、背景 在AMD的Linux GPU驱动中,只有计算相关的业务(amdkfd)直接使用TTM来allocate/free内存,当然在dma-buf来进行进程间通信内存共享时也用到了GEM。而在图形相关业务中既使用了GEM也使用了TTM。下面对GEM和TTM的核心结构和函数进行剖析。 二

    2024年02月10日
    浏览(28)
  • 【AMD GPU】使用A卡进行ai模型训练

    rocm都更新这么多版本了怎么还没有windows的 ~~##RX580用户看过来 rocm4.0版本后就不支持RX580了,垃圾AMD linux:Ubuntu20.04.1 CPU:R9-5900hx GPU:RX6800M 12G python:3.10.6 2022-10-24 23:21:50一键部署工具发布 顺序:1-8-2-3-4-5-7-6 加个源:deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu jammy main 下载链接ht

    2024年02月03日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包