amdgpu kfd TTM create GTT

  • vm_alloc_memory_of_gpu
  • bo_do_create()
    • ttm_bo_placement_from_domain()
    • ttm_bo_init_reserved()

vm_alloc_memory_of_gpu

flags = ALLOC_MEM_FLAGS_GTT (0x2)

domain = alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
alloc_flags = 0;
byte_align = 1; 实际上在do_create时是按页面对齐
bo_type = ttm_bo_type_device (can mmap / Maybe at SYSTEM/VRAM)

bo_do_create()

已经有tbo(driver wrapper) , 所有bo位置属性在driver的bo中描述, 在ttm_bo_init_reserved时设置到tbo

//计算记账器中需要在系统内存存储多少空间
acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size, sizeof(struct amdgpu_bo));
page_size = ALIGN(byte_align, PAGE_SIZE) >>PAGE_SHIFT; //按照页面对齐的页面数目
bo->vm_bo // 标记当前mapping的vmbase , 在 vm_bo_base_init时被设置
bo->preferred_domains // 当前申请的bo 期望的位置
bo->allowed_domain //当前申请的bo 允许的位置, 申请时和preferred相同
bo->flags // 当前申请时的cached属性标记和bo资源标记(clear等)

ttm_bo_placement_from_domain()

// 根据alloc_memory时的domian, 标记 driver bo在相应domain的位置和cached属性
由于我们是GTT, 所以, 当前的place中flag存在 PL_TT, flags看之前alloc时的请求了, 目前假定用0, 所以是cached. 我们就有一个domain,所以 num是1 . 将创建的属性保存到abo中

ttm_bo_init_reserved()

实例化tbo中的mem信息

  1. ttm_mem_global_alloc // 根据之前计算好的tbo想彻底填充好页面信息所需要的cpu内存的数量, 申请内存, 这里我们给tbo的zone是kernel的, 所以我们再这个函数内部用kernel_zone申请, 看他的zone现在够不够用,不够的话, 需要swapout原来的(ttm_shrink), 这里, 如果刚才的type是ttm_bo_kernel. 那在lru的后端, 最后实在没办法才会swap?(priority = 1)
  2. tbo资源设置
 bo->bdev = bdev; // ttm_bo_devicebo->type = type;  //当前是ttm_bo_devicebo->num_pages = num_pages; // 多少个PAGE_SIZE的页面, 不是多少字节bo->mem.size = num_pages << PAGE_SHIFT; // 多少字节bo->mem.mem_type = TTM_PL_SYSTEM; //初始值,mem在cpu这边bo->mem.num_pages = bo->num_pages; //当前mem有多少页bo->mem.mm_node = NULL; // 当前mem没有分配gpu视角地址空间bo->mem.page_alignment = page_alignment; // 内存的页对齐大小bo->mem.bus.io_reserved_vm = false; //dma侧内存?bo->mem.bus.io_reserved_count = 0;bo->moving = NULL; //默认bo肯定没有移动bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); // 在cpu这边默认属性是SYSTEM. cachedbo->acc_size = acc_size; //记账器需要在cpu侧报错的tbo的资源大小bo->sg = sg; // 有没有dma_address
  1. drm_vma_offset_add // 如果cpu可见内存, 添加到vma, 保证在mmap时,可以到ttm_vm.c正常map给umd
  2. ttm_bo_validate() tbo区域验证和更新, 确保当前bo满足之前的期望值
    bo// 当前的bo
    placement// 期望的位置和属性
    ctx// ttm操作的资源锁, 给dma_resv用的

    1. 所以使用ttm_bo_mem_compat时, param1: 目标place, parem2: 当前区域, param3: 比较后返回的flag
    2. ttm_bo_move_buffer() // bo:tbo, placement:期望的位置和flag , ctx:dma_resv
      1. ttm_bo_mem_space() //通过placement决定我们的bo要往哪挪, 挪的空间也要在这准备好(get_node) mem_type = TTM_PL_SYSTEM, 此后new_mem就有了 mm_node 了
      2. ttm_bo_handle_move_mem(); bo:将要移动的bo, mem:将要移动的位置, false:不可evict, ctx: 当前操作的ctx
        1. 目标区或者原始区是pci, 或者两区域的cachde不匹配,那就得将原始区的映射释放并且将原始区内存加锁
        2. 目标区不是显存区域(TTM_MEMTYPE_FLAG_FIXED),有可能是GTT, 有可能是SYSTEM, 反正都是在系统内存那边,cpu都能访问
          1. tbo还没有页面存储结构, 需要创建ttm_tt(ps:也就是去系统内存搞点内存为了存后边系统内存的页面) ttm_tt_create 这个只是创建了存储页面的指针数组, 还没真正上页面, 此时创建好的ttm_tt->state = tt_unpopulated ;; ttm_tt_init_fields()
          2. 设置ttm_tt里面已经有页面的cached属性 ttm_tt_set_page_caching, 你会疑惑, 2.1 步骤不是刚创建ttm_tt? 但是有可能之前就已经有页面, 那需要把之前的页面设置cached属性, 但是2.1刚创建的, ttm->state是ttm_unpopulated, 还没页面,所以只是记录了页面属性,并没设置
          3. 新区域在非SYSTEM区(那就是GTT), ttm_tt_bind() 虚拟地址和物理地址的绑定 ,期间会发生populate和bind
            1. ttm_tt的mem进行地址绑定, 因为此时tbo->ttm处于一种需要移动状态, ttm_tt->state 一共是三种状态, bound. unbound, populated, 所以我们不确定当前ttm_tt是啥时候创建的 , 所以需要走一遍populated的过程才能进行bound.
            2. ttm_tt_populate() // 页面上新
            3. amdgpu_ttm_tt_populate()
              1. 如果是USERPTR的内存, 需要创建SG后备存储页面的结构
              2. 如果已经有页面,并且还是SG共享页面, 需要将页面保存到ttm->sg里面,并且还需要再次地址bind
              3. ttm_populate_and_map_pages() // 获取页面, map到设备侧

              1. ttm_pool_populate() //获取后端页面
                
                1. ttm_get_pages 真正获取page的地方了, 1.     根据page_flag和caechflag找打对应的pool1.     对于通用的GTT(非UC.WC) , 是使用的默认的PAGE. gfp是ZERO|MAYFAIL, 然后就是去内核高端区alloc_page了2.     对于UC,WC那种的cached, pool是有的, 需要在指定的pool里面申请资源2.   对一指定pool的情况, 如果有乱序页面, 需要进行页面重排swap, 而且对于dma区的申请时 , 可能申请到32M的连续page3.   系统内存页面获取完毕
                  
                2. 申请完页面需要告诉ttm后端的global记账器, 人家可是需要swapout/in的
              2. tt->dma_address[i] = dma_map_page// 将页面映射给设备. ttm->dma_address存设备视角的总线地址 , 这里有个快速映射的手段,既可以一页一页映射,又可以一片一片的映射
                
              3. ttm_tt_add_mapping() 页面对应到设备所在地址映射空间, 在umd进行mmap时有用
            4. ret = ttm->func->bind(ttm, bo_mem); // 驱动自己的wrapper的 amdgpu_ttm_backend_bind
              1. if userptr

                1. 来自于umd的page, 可能是, 需要sg存储这些不连续的page
              2. if !amdgpu_gtt_mgr_has_gart_addr
                1. 如果当前tbo还没有在gart虚拟地址范围申请地址, 那抱歉, 标记一个假的地址, 返回
              3. amdgpu_ttm_tt_pte_flags
                1. 获取当前bo的页表项的标记
              4. amdgpu_gart_bind
                1. 绑定到gart表, 不赘述
          4. 看原来的区域怎么搞: if (bo->mem->mem_type == SYSTEM) // 如果原来区域在系统内存,那好, 该umap就umap, 该释放就是放, vm_bo_invalidate,kunmap, 把老的挪走, 新的换上, 地址用新的mem刚申请的那个地址, 就move完成
        3. 上边2, 是new不是显存并且old是系统内存(if (bo->mem->mem_type == SYSTEM)) , 如果new的区域不是fix(VRAM)的但是old的是GTT的, 那就需要通知driver的move_notify, 将old的GTT释放, 并且umap,然后再 ttm_bo_move_ttm
          1. 这里需要注意的是, 原区域是GTT的话, 需要unbind释放页表和占位资源
          2. 再次标记新ttm_tt的cached属性
          3. 新的区域如果是GTT, 需要bind页表
          4. 然后, 就可以新老替换(结构体拷贝), 标记完成, 并且将刚给new的mm_node释放
      3. 如果new_mem 和 old_mem 在上边的一堆判断中都没法做, 但是驱动有办法, 那就驱动帮忙做
      4. 如果驱动也不管, 那只好 memcpy_fromio ttm_bo_move_memcpy()
      5. if (bo->mem.mm_node) 如果刚才的操作已经实现了gpu视角的空间申请
        1. 获取tbo基于gpu视角的地址, VRAM是物理地址, GTT是虚拟地址或者假地址
      6. 如果刚才的新的驱动是VRAM的, 因为ttm_tt本身不是vram的表征, 所以释放掉

amdgpu kfd TTM create GTT相关推荐

  1. 显卡 内存分配 linux,【原创】Linux环境下的图形系统和AMD R600显卡编程(4)——AMD显卡显存管理机制...

    显卡使用的内存分为两部分,一部分是显卡自带的显存称为VRAM内存,另外一部分是系统主存称为GTT内存(graphics translation table和后面的GART含义相同,都是指显卡的页表,G ...

  2. 20220211关于TL-WDN6200(RTL8812AU)在ubuntu20.04.3下安装驱动程序的历险记

    20220211关于TL-WDN6200(RTL8812AU)在ubuntu20.04.3下安装驱动程序的历险记 2022/2/11 14:42 一个超级巨大的合作伙伴报告,华硕无畏Pro14 锐龙版 ...

  3. amd显卡linux卡死,Radeon 520显卡使用amdgpu时的死机问题 [不用点进来看了,解决方法是换一台电脑]...

    硬件:Dell Inspiron 15-3576,Intel Core i5-8250U/UHD620+AMD Radeon 520(核心为Hainan,GCN1.0/Southern Island) ...

  4. AMDGPU doorbell offset分配

    文章目录 前言 一.bpftrace+test case 二.结果 结果分析 前言 本文主要是debug AMDGPU SDMA的doorbell offset. 一.bpftrace+test ca ...

  5. arch linux对32amd,AMDGPU (简体中文)

    翻译状态:本文是 AMDGPU 的翻译.上次翻译日期:2019-09-02.如果英文版本有所更改,则您可以帮助同步翻译. amdgpu 是 AMD Radeon 显卡的开源图形驱动. 选择正确的驱动 ...

  6. mongo报错:not authorized on bb to execute command { create: \“xxx\“...}

    mongo报错: {"ok" : 0,"errmsg" : "not authorized on bb to execute command { cr ...

  7. Struts2 Cannot create a session after the response has been committed 一个不起眼的错误

    严重: Servlet.service() for servlet default threw exception java.lang.IllegalStateException:  Cannot c ...

  8. Ubuntu20.04安装zabbix以及Cannot create the configuration file解决

    添加zabbix的扩展源 echo 'deb http://mirrors.aliyun.com/zabbix/zabbix/5.0/ubuntu/dists/ focal main' >> ...

  9. Oracle报错createPool,Jmeter中连接Oracle报错Cannot create PoolableConnectionFactory

    填坑贴,之前一直用jmeter2.13版本进行oracle测试,今天改为3.2版本,发现按照以往的方法执行测试,JDBC Request结果始终报错:Cannot create PoolableCon ...

最新文章

  1. 在Windows 8.1上使用Fiddler重定向http请求进行前端调试
  2. java 变量 占用空间_Java-空变量是否需要内存空间
  3. leetcode的回溯算法题目用这个模板解题,一网打尽,so easy!!!
  4. classes是什么意思怎么读_KY啥意思?托马仕空品教你怎么读空气
  5. PHP的array_column
  6. 六、springcloud之配置中心Config
  7. 拒绝无脑试错:写给萌新的“科学炼丹”入门手册
  8. 2月第三周各国家.NET域名排名Top10:中国第三
  9. 在 Web 级集群中动态调整 Pod 资源限制
  10. 软件测试的知识点总结
  11. [WDS] Disconnected解决方法
  12. SQL之累积计算问题--HQL面试题1
  13. wps表格怎么按特定的顺序对数据进行排序
  14. 统一文档服务器,统一标准化文档oraclei服务器安装基础手册.doc
  15. cisco packet tracer_交换机配置/mac地址表(图解version:8+)
  16. 如何成为一个高情商的员工(附全书思维导图)
  17. 图片随鼠标滑轮滚动变大变小
  18. 电脑史话-计算机先驱巴贝奇
  19. 前端开发面试题及答案
  20. 【Kay】Java的一些Bonus

热门文章

  1. perl环境配置以及Eclipse安装perl开发插件
  2. Sourcetree 无法打开
  3. linux 命令中英文对照,收集
  4. vimeo 镜像_Vimeo API – OAuth和上传示例
  5. MacOS利用终端与Linux服务器上传与下载文件
  6. 目前用到的原型设计工具总结
  7. 微信小程序input数据的双向绑定
  8. 赋范空间与巴拿赫空间
  9. sfc流程图怎么画_SFC顺序功能图教程
  10. 做人呢,一定要谨记下面两个原则