amdgpu kfd TTM create GTT
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信息
- ttm_mem_global_alloc // 根据之前计算好的tbo想彻底填充好页面信息所需要的cpu内存的数量, 申请内存, 这里我们给tbo的zone是kernel的, 所以我们再这个函数内部用kernel_zone申请, 看他的zone现在够不够用,不够的话, 需要swapout原来的(ttm_shrink), 这里, 如果刚才的type是ttm_bo_kernel. 那在lru的后端, 最后实在没办法才会swap?(priority = 1)
- 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
- drm_vma_offset_add // 如果cpu可见内存, 添加到vma, 保证在mmap时,可以到ttm_vm.c正常map给umd
- ttm_bo_validate() tbo区域验证和更新, 确保当前bo满足之前的期望值
bo// 当前的bo
placement// 期望的位置和属性
ctx// ttm操作的资源锁, 给dma_resv用的- 所以使用ttm_bo_mem_compat时, param1: 目标place, parem2: 当前区域, param3: 比较后返回的flag
- ttm_bo_move_buffer() // bo:tbo, placement:期望的位置和flag , ctx:dma_resv
- ttm_bo_mem_space() //通过placement决定我们的bo要往哪挪, 挪的空间也要在这准备好(get_node) mem_type = TTM_PL_SYSTEM, 此后new_mem就有了 mm_node 了
- ttm_bo_handle_move_mem(); bo:将要移动的bo, mem:将要移动的位置, false:不可evict, ctx: 当前操作的ctx
- 目标区或者原始区是pci, 或者两区域的cachde不匹配,那就得将原始区的映射释放并且将原始区内存加锁
- 目标区不是显存区域(TTM_MEMTYPE_FLAG_FIXED),有可能是GTT, 有可能是SYSTEM, 反正都是在系统内存那边,cpu都能访问
- tbo还没有页面存储结构, 需要创建ttm_tt(ps:也就是去系统内存搞点内存为了存后边系统内存的页面) ttm_tt_create 这个只是创建了存储页面的指针数组, 还没真正上页面, 此时创建好的ttm_tt->state = tt_unpopulated ;; ttm_tt_init_fields()
- 设置ttm_tt里面已经有页面的cached属性 ttm_tt_set_page_caching, 你会疑惑, 2.1 步骤不是刚创建ttm_tt? 但是有可能之前就已经有页面, 那需要把之前的页面设置cached属性, 但是2.1刚创建的, ttm->state是ttm_unpopulated, 还没页面,所以只是记录了页面属性,并没设置
- 新区域在非SYSTEM区(那就是GTT), ttm_tt_bind() 虚拟地址和物理地址的绑定 ,期间会发生populate和bind
- ttm_tt的mem进行地址绑定, 因为此时tbo->ttm处于一种需要移动状态, ttm_tt->state 一共是三种状态, bound. unbound, populated, 所以我们不确定当前ttm_tt是啥时候创建的 , 所以需要走一遍populated的过程才能进行bound.
- ttm_tt_populate() // 页面上新
- amdgpu_ttm_tt_populate()
1. 如果是USERPTR的内存, 需要创建SG后备存储页面的结构
2. 如果已经有页面,并且还是SG共享页面, 需要将页面保存到ttm->sg里面,并且还需要再次地址bind
3. ttm_populate_and_map_pages() // 获取页面, map到设备侧ttm_pool_populate() //获取后端页面
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. 系统内存页面获取完毕
- 申请完页面需要告诉ttm后端的global记账器, 人家可是需要swapout/in的
tt->dma_address[i] = dma_map_page// 将页面映射给设备. ttm->dma_address存设备视角的总线地址 , 这里有个快速映射的手段,既可以一页一页映射,又可以一片一片的映射
- ttm_tt_add_mapping() 页面对应到设备所在地址映射空间, 在umd进行mmap时有用
- ret = ttm->func->bind(ttm, bo_mem); // 驱动自己的wrapper的 amdgpu_ttm_backend_bind
- if userptr
- 来自于umd的page, 可能是, 需要sg存储这些不连续的page
- if !amdgpu_gtt_mgr_has_gart_addr
- 如果当前tbo还没有在gart虚拟地址范围申请地址, 那抱歉, 标记一个假的地址, 返回
- amdgpu_ttm_tt_pte_flags
- 获取当前bo的页表项的标记
- amdgpu_gart_bind
- 绑定到gart表, 不赘述
- if userptr
- 看原来的区域怎么搞: if (bo->mem->mem_type == SYSTEM) // 如果原来区域在系统内存,那好, 该umap就umap, 该释放就是放, vm_bo_invalidate,kunmap, 把老的挪走, 新的换上, 地址用新的mem刚申请的那个地址, 就move完成
- 上边2, 是new不是显存并且old是系统内存(if (bo->mem->mem_type == SYSTEM)) , 如果new的区域不是fix(VRAM)的但是old的是GTT的, 那就需要通知driver的move_notify, 将old的GTT释放, 并且umap,然后再 ttm_bo_move_ttm
- 这里需要注意的是, 原区域是GTT的话, 需要unbind释放页表和占位资源
- 再次标记新ttm_tt的cached属性
- 新的区域如果是GTT, 需要bind页表
- 然后, 就可以新老替换(结构体拷贝), 标记完成, 并且将刚给new的mm_node释放
- 如果new_mem 和 old_mem 在上边的一堆判断中都没法做, 但是驱动有办法, 那就驱动帮忙做
- 如果驱动也不管, 那只好 memcpy_fromio ttm_bo_move_memcpy()
- if (bo->mem.mm_node) 如果刚才的操作已经实现了gpu视角的空间申请
- 获取tbo基于gpu视角的地址, VRAM是物理地址, GTT是虚拟地址或者假地址
- 如果刚才的新的驱动是VRAM的, 因为ttm_tt本身不是vram的表征, 所以释放掉
amdgpu kfd TTM create GTT相关推荐
- 显卡 内存分配 linux,【原创】Linux环境下的图形系统和AMD R600显卡编程(4)——AMD显卡显存管理机制...
显卡使用的内存分为两部分,一部分是显卡自带的显存称为VRAM内存,另外一部分是系统主存称为GTT内存(graphics translation table和后面的GART含义相同,都是指显卡的页表,G ...
- 20220211关于TL-WDN6200(RTL8812AU)在ubuntu20.04.3下安装驱动程序的历险记
20220211关于TL-WDN6200(RTL8812AU)在ubuntu20.04.3下安装驱动程序的历险记 2022/2/11 14:42 一个超级巨大的合作伙伴报告,华硕无畏Pro14 锐龙版 ...
- amd显卡linux卡死,Radeon 520显卡使用amdgpu时的死机问题 [不用点进来看了,解决方法是换一台电脑]...
硬件:Dell Inspiron 15-3576,Intel Core i5-8250U/UHD620+AMD Radeon 520(核心为Hainan,GCN1.0/Southern Island) ...
- AMDGPU doorbell offset分配
文章目录 前言 一.bpftrace+test case 二.结果 结果分析 前言 本文主要是debug AMDGPU SDMA的doorbell offset. 一.bpftrace+test ca ...
- arch linux对32amd,AMDGPU (简体中文)
翻译状态:本文是 AMDGPU 的翻译.上次翻译日期:2019-09-02.如果英文版本有所更改,则您可以帮助同步翻译. amdgpu 是 AMD Radeon 显卡的开源图形驱动. 选择正确的驱动 ...
- mongo报错:not authorized on bb to execute command { create: \“xxx\“...}
mongo报错: {"ok" : 0,"errmsg" : "not authorized on bb to execute command { cr ...
- Struts2 Cannot create a session after the response has been committed 一个不起眼的错误
严重: Servlet.service() for servlet default threw exception java.lang.IllegalStateException: Cannot c ...
- Ubuntu20.04安装zabbix以及Cannot create the configuration file解决
添加zabbix的扩展源 echo 'deb http://mirrors.aliyun.com/zabbix/zabbix/5.0/ubuntu/dists/ focal main' >> ...
- Oracle报错createPool,Jmeter中连接Oracle报错Cannot create PoolableConnectionFactory
填坑贴,之前一直用jmeter2.13版本进行oracle测试,今天改为3.2版本,发现按照以往的方法执行测试,JDBC Request结果始终报错:Cannot create PoolableCon ...
最新文章
- 在Windows 8.1上使用Fiddler重定向http请求进行前端调试
- java 变量 占用空间_Java-空变量是否需要内存空间
- leetcode的回溯算法题目用这个模板解题,一网打尽,so easy!!!
- classes是什么意思怎么读_KY啥意思?托马仕空品教你怎么读空气
- PHP的array_column
- 六、springcloud之配置中心Config
- 拒绝无脑试错:写给萌新的“科学炼丹”入门手册
- 2月第三周各国家.NET域名排名Top10:中国第三
- 在 Web 级集群中动态调整 Pod 资源限制
- 软件测试的知识点总结
- [WDS] Disconnected解决方法
- SQL之累积计算问题--HQL面试题1
- wps表格怎么按特定的顺序对数据进行排序
- 统一文档服务器,统一标准化文档oraclei服务器安装基础手册.doc
- cisco packet tracer_交换机配置/mac地址表(图解version:8+)
- 如何成为一个高情商的员工(附全书思维导图)
- 图片随鼠标滑轮滚动变大变小
- 电脑史话-计算机先驱巴贝奇
- 前端开发面试题及答案
- 【Kay】Java的一些Bonus