热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

LinuxGraphics周刊(第6期)

导读:dma-buf:vmap新增对IO-Memory的支持drmgem:vmap新增对IOmemory的支持drmgem:全面启用GEMobjectfunction

导读:

  • dma-buf: vmap 新增对 I/O-Memory 的支持
  • drm/gem: vmap 新增对 I/O memory 的支持
  • drm/gem: 全面启用 GEM object functions
  • drm/ttm: 删除 TTM_PL_FLAG_NO_EVICT,新增 ttm_bo_pin()/ttm_bo_unpin()
  • interfaces: bugfix for use-after-free in mapper 2.0
  • SurfaceFlinger: 采用绝对时间来设置 VSP timer
  • GPU Memory: 新增 libgpumem 用于 BPF 调试
  • Android vulkan 升级到 1.2.158
  • Taiwins 0.2 发布,支持 Lua 脚本


DRM


1. dma-buf: vmap 新增对 I/O-Memory 的支持

之前曾在周刊第1期中报道过关于 为 GEM vmap 添加 I/O memory 的支持 的提交,该提交是以 drm prime 为基础进行修改的,不过该 patch 并没有立即被合入,而是重新提交了基于更底层的 dma-buf 修改的 patch,并最终于9月25日 merge 到 drm-misc 分支,预计将被合入到 linux-5.11 rc1 版本中。以下是该 patch 的背景:

众所周知,CPU 在 kernel space 是通过虚拟地址(virtual address)来访问物理内存的。同样的,如果 CPU 想访问一块 dma buffer 的物理内存,也需要先将该 dma buffer 映射到 kernel 的虚拟地址空间中才能正常访问,而这个映射的操作则由 dma_buf_vmap() 接口来实现。无论该 dma buffer 在物理上是连续的还是离散的,经过 dma_buf_vmap() 后的虚拟地址一定是连续的,这样 CPU 就可以像访问普通内存一样来访问 dma buffer。如果你还不了解 dmabuf 的 vmap 接口,建议回顾一下本人的 《dma-buf 系列之 kmap / vmap》

CPU 访问 dma buffer 的应用场景在 DRM 驱动中非常普遍,如 fbdev console 以及 tinydrm,都会涉及到在驱动中动态修改 framebuffer 内容。由于 CPU 将这块 vmap() 后的内存当作普通内存来访问,因此它使用的操作指令则是通用的 load/store 指令。设想一下,当 vmap 的物理内存来自于 I/O 端口(如外设寄存器)时,会发生什么样的情况?如果是 ARM 平台则不会出现什么异常,因为 ARM 架构中 IO 地址空间是和内存空间统一编址的,所以访问 IO 寄存器和访问普通内存没有什么区别。但是在 SPARC 平台上就会导致 kernel panic,原因是 SPARC 架构中 I/O 地址空间是独立编址的,不能使用普通的 load/store 访存指令来访问 IO 内存,而需要使用专门的 I/O 操作指令才能正常访问 I/O 端口上的内容。

为了解决上述平台兼容性问题,Thomas Zimmermann(drm-misc maintainer, SUSE)向社区提交了一组 patch,新增了 dma_buf_map 结构体,用于专门区分 vmap() 后的地址是位于 IO Memory 还是 System Memory 上。dma_buf_map 具体定义如下:

struct dma_buf_map {union {void __iomem *vaddr_iomem;void *vaddr;};bool is_iomem;
};

该结构体作为 dma_buf_vmap() 的返回值,通过 is_iomem 来告诉调用者当前 memory 的类型,这样驱动程序就可以针对不同的 memory 类型,使用不同的访存接口(如 memcpy() 还是 memcpy_toio())来操作内存,避免 kernel panic 的发生。需要注意的是,该结构体虽然名字中包含“dma buf” 关键字,但是该结构体并不依赖于 dma-buf 驱动,它有自己独立的 dma-buf-map.h 头文件,任何想要区分 IO / System memory 的驱动都可以引用该头文件,而无需开启任何 dma-buf 相关的宏定义。关于该结构体的命名,邮件列表中也有不少反对意见,而 Thomas 解释之所以给它取名带 “dma buf” 关键字,是因为目前只有 dma-buf 驱动才会用到这个结构体,如果后面还有其他驱动也需要用到该结构体,可以到时候再修改,毕竟就现阶段而言,尽早合入该 patch 能加快其他依赖驱动的合入进程。

(其实我个人觉得这个结构体名字取的真的很不好,因为它容易和函数 dma_buf_mmap() 混淆)

详情:[v3,0/4] dma-buf: Flag vmap’ed memory as system or I/O memory


2. drm/gem: vmap 新增对 I/O memory 的支持

基于上面的 dma-buf-map patch,Thomas 将上次关于 GEM I/O memory mapping 的 patch rebase 到了 dma-buf-map 基础上,并对 drm 中凡是和 vmap 相关的接口进行了修改,包括 cma、shmem、vram、ttm、prime、client 以及 drm_gem_object_funcs。除此之外,他还对 drm_fb_helper.c 做了大量修改,并新增了 dma_buf_map_memcpy_to()dma_buf_map_incr() 两个辅助函数来简化 fbdev 驱动访问显存的代码编写。该 patch 将在 linux-5.11 merge window 开启时被合入。

详情:[PATCH v5 00/10] Support GEM object mappings from I/O memory


3. drm/gem: 全面启用 GEM object functions

两个月前曾在周刊第1期中介绍过关于“彻底废弃 drm_driver 中的 prime callbacks,全面启用 GEM Object functions”的消息。drm_gem_object_funcs 从 kernel-4.19 开始被引入,该结构体定义如下(linux-5.10-rc1):

struct drm_gem_object_funcs {void (*free)(struct drm_gem_object *obj);int (*open)(struct drm_gem_object *obj, struct drm_file *file);void (*close)(struct drm_gem_object *obj, struct drm_file *file);void (*print_info)(struct drm_printer *p, unsigned int indent,const struct drm_gem_object *obj);struct dma_buf *(*export)(struct drm_gem_object *obj, int flags);int (*pin)(struct drm_gem_object *obj);void (*unpin)(struct drm_gem_object *obj);struct sg_table *(*get_sg_table)(struct drm_gem_object *obj);void *(*vmap)(struct drm_gem_object *obj);void (*vunmap)(struct drm_gem_object *obj, void *vaddr);int (*mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma);
};

可以看到,该结构体几乎覆盖了所有 dma-buf export 的接口,因此它可以完全取代 drm_driver 结构体中的 prime export 接口。Thomas Zimmermann( drm-misc Maintainer, SUSE)总共提交了 22 笔 patch,其中第 1~ 21 笔 patch 是专门用来清理各个 drm 设备驱动的,将 drm_driver 中的 prime export 接口挪到 drm_gem_object_funcs 中去。第 22 笔 patch 则是彻底删除 drm_driver 中与 prime export 相关的 callbacks。该 patch 已于9月25日合入到 drm-misc-next 分支,接下来准备合入 linux-5.11 主线。

详情:[PATCH v2 00/21] Convert all remaining drivers to GEM object functions


4. drm/ttm: 删除 TTM_PL_FLAG_NO_EVICT,新增 ttm_bo_pin()/ttm_bo_unpin()

TTM(Translation Table Manager)是 DRM 驱动中的一种显存管理机制,和 GEM 是同一个级别的概念,它主要适用于带独立显存的显卡驱动,因此在移动平台很少看到它的身影。因为 ttm 主要适用于带独立显卡的应用场景,因此在分配显存的时候就会涉及到具体显存分配的位置,进一步说就是在 VRAM 中分配还是在系统的 RAM 中分配。为了告诉 ttm 驱动具体应该在什么样的介质上分配 buffer,drm 框架引入了 ttm placement flag,如 TTM_PL_FLAG_SYSTEM 代表在系统 memory 中分配 buffer,TTM_PL_FLAG_VRAM 在 VRAM 中分配 buffer。而当 VRAM 中空间不足时,驱动则会将那些使用频率并不高但是又不能立即释放的 buffer 迁移(驱逐/evict)到 System Memory 中,以此来为新的 buffer 提供可用的空间(有点类似于 kernel 中的 CMA 机制)。而 TTM_PL_FLAG_NO_EVICT 则是告诉驱动当前分配的 buffer 不能进行迁移,一旦分配了就固定在当前介质中了(即pin住了)。随着时间的推移,开发人员发现 TTM_PL_FLAG_NO_EVICT 这个 flag 越来越不好用,因为该 flag 将 buffer 限定死了,有时候我们希望某块 buffer 当我们要使用它时,就将他固定(pin)在 VRAM 中,当我们中途不想用时,就把它 unpin 掉,这样后续就可以对它进行迁移操作,提高 VRAM 的利用率。所以后来各个厂商开始通过 pin_count 引用计数来对某个 buffer 实现 pin/unpin 操作,而不再使用原生的 TTM_PL_FLAG_NO_EVICT flag。Christian König 提交的这组 patch 则顺应了各大厂商的意愿,将 vendor 实现的 pin_count 挪到了 ttm 框架中,通过 ttm_bo_pin()ttm_bo_unpin() 函数来操作 pin_count 引用计数,同时删除了 TTM_PL_FLAG_NO_EVICT flag 和 ttm_bo_create() 函数。该 patch 也将被合入到 Linux-5.11 中。

详情:[PATCH 01/11] drm/ttm: add ttm_bo_pin() ttm_bo_unpin() v2


AOSP


1. ueventd: support DMA-BUF heaps

DMA-BUF Heaps 是用来替代 ION 的多媒体内存分配器,而在周刊第3期中也曾报道过 kernel mainline 已经彻底删除了 ION 驱动,而 Google 也将在 AndroidS 中正式启用 DMA-BUF Heaps 来作为 ION 的备选方案。

如下提交在 rootdir/ueventd.rc 中新增了 dma_heap 节点访问权限:

/dev/dma_heap/system 0666 system system

详情:aosp/core[master]: Setup ueventd to support DMA-BUF heaps


2. interfaces: bugfix for use-after-free in mapper 2.0

在谷歌官方的mapper2.0 hal实现中,通过importBuffer()导入的 native_handle_t 都是保存在 mBufferHandles 集合中的,当应用程序不再需要这个 native_handle_t 时,则通过 freeBuffer() 来释放这个handle所对应的进程资源,最终擦除该 native_handle_t 在 mBufferHandles 中的位置。由于应用程序 importBuffer() 和 freeBuffer() 可能在两个不同的线程中执行,所以在对 mBufferHandles 进行 add/erase 操作时都是用锁保护起来的,以防出现竞争。但最近开发人员发现在 Mapper 2.0 中还是出现了竞争的问题,因为在 freeBuffer() 的实现中, 是先调用底层的 mHal->freeBuffer() 然后再执行 mBufferHandles.erase() 操作,由于互斥锁只保护了 erase 操作,没有保护 mHal->freeBuffer(),这就有可能导致一个线程刚刚执行完 mHal->freeBuffer(),正好另一个线程又在执行 importBuffer() 操作,于是出错。解决方法则是将 mHal->freeBuffer() 和 mBufferHandles.erase() 操作放在同一把锁里保护起来,这样就能避免多线程的竞争问题。

详情:aosp/interfaces[master]: graphics: fix use-after-free in mapper 2.0 passthrough


3. SurfaceFlinger: 采用绝对时间来设置 VSP timer

VSyncPredictor(VSP)是 Android11 新引的一个 Vsync 预测器,它内部有一个 timer 模块,基于 timerfd 来实现的。timerfd 是 Linux 为用户程序提供的一个定时器接口。这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,因此可以配合 select/poll/epoll 等使用。该 patch 的重点是在 timerfd_settime() 函数上,这个函数接收一个 flag 参数,当 flag 为 TFD_TIMER_ABSTIME 时代表设置的是绝对时间,当 flag 为0时代表设置的时间为相对时间。VSP timer 将 timerfd_settime() 封装在了 Timer::alarmIn() 函数中,使用的 flag 都是0(即相对时间),本意是调用 alarmIn(5) 就会在5ms后唤醒定时器,正常情况下没有什么问题的。但是一旦在 alarmIn() 中 timerfd_settime() 之前发生了线程抢占,那么这个 alarmIn() 设置的 timer 就会往后推迟,导致 timer 不准确。因此需要将 timerfd_settime() 的 flag 修改成 TFD_TIMER_ABSTIME,这样采用绝对时间就能避免因线程调度而导致的 timer 不准确的问题发生。

详情:aosp/native[master]: SurfaceFlinger: use TFD_TIMER_ABSTIME for VSP timer


4. AChoreographer: 删除多余的 requestLatestConfig() 操作

AChoreographer 原本就是从 DisplayManager 那边获取刷新率(refresh rate)的,因此没必要通过 requestLatestConfig() 接口从 SurfaceFlinger 那边获取。 AChoreographer 只需要将最新的 refresh rate 封装成一个 event,然后发送给 looper 线程即可。该 Patch 能够确保 AChoreographer 的回调函数的执行是和 DisplayManager 完全同步的。

详情:aosp/native[master]: Fix refresh rate callback fan-out for choreographer


5. GPU Memory: 新增 libgpumem 用于 BPF 调试

为了增加 GPU 调试手段,Google 在 frameworks/native/services/gpuservice/bpfprogs 下新增 gpu_mem.c 文件,用于生成 BPF 调试程序 gpu_mem.o。同时在 frameworks/native/services/gpuservice 下新增了 libgpumem 模块,用于和 BPF 下的 gpu_mem.o 程序通信。当 BPF 加载 gpu_mem.o 文件后,会生成如下调试节点:


  1. /system/etc/bpf/gpu_mem.o
  2. /sys/fs/bpf/map_gpu_mem_gpu_mem_total_map
  3. /sys/fs/bpf/prog_gpu_mem_tracepoint_gpu_mem_gpu_mem_total

通过 libgpumem.so,我们可以抓取当前时刻系统所有进程的 GPU Memory 使用情况,同时也可以直接使用 “adb shell dumpsys gpu --gpumem” 命令来动态打印 gpu memory 的信息,非常方便。

详情:aosp/native[master]: GPU Memory: implement libgpumem to interact with bpf


6. vulkan: 升级 API 版本到 1.2.158

Android 目前的 libvulkan API 版本已升级到 1.2.158,新增如下 API,Extension 无新增。

vkCmdBeginRenderPass2
vkCmdDrawIndexedIndirectCount
vkCmdDrawIndirectCount
vkCmdEndRenderPass2
vkCmdNextSubpass2
vkCreateRenderPass2
vkGetBufferDeviceAddress
vkGetBufferOpaqueCaptureAddress
vkGetSemaphoreCounterValue
vkResetQueryPool
vkSignalSemaphore
vkWaitSemaphores

详情:aosp/native[master]: Vulkan: update generated framework according to vulkan-headers


Wayland


Taiwins 0.2 发布,支持 Lua 脚本

之前曾在我的星球中介绍过 Taiwins 这个新项目(https://t.zsxq.com/R3vJyJM),Taiwins 是一个开源的、模块化的 Wayland Compositor,由 Xichen.Zhou 创建。该项目最初基于 libweston 库开发,可实现平铺式窗口和浮动窗口,编写 client 程序代码量少,易于上手。此次 Taiwins 0.2 版本发布,将底层基础库从原来的 libweston 转移到了 wlroots 库,除了支持 Lua 脚本外,还带来了如下新 feature:


  • dynamic window management.
  • extensible and easy configuration through lua.
  • very efficient GL renderer, updates only the damages.
  • a widget system and you can create widgets through lua as well.
  • built-in shell and application launcher.
  • configurable theme.
  • emacs-like key sequence based binding system.
  • built-in profiler and rendering debugger.

官网:https://taiwins.org/index.html
github: https://github.com/taiwins/taiwins

详情:Taiwins 0.2 is out


推荐阅读
  • NotSupportedException无法将类型“System.DateTime”强制转换为类型“System.Object”
    本文介绍了在使用LINQ to Entities时出现的NotSupportedException异常,该异常是由于无法将类型“System.DateTime”强制转换为类型“System.Object”所导致的。同时还介绍了相关的错误信息和解决方法。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 技术点:1、通过已知的网页路径获得流2、把流转换成字节数组3、把字节数组转换成String字符串显示在TextView控件中一、获得流publicstaticSt ... [详细]
  • Spark 贝叶斯分类算法
    一、贝叶斯定理数学基础我们都知道条件概率的数学公式形式为即B发生的条件下A发生的概率等于A和B同时发生的概率除以B发生的概率。根据此公式变换,得到贝叶斯公式:即贝叶斯定律是关于随机 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了MongoDB快速入门教程(4.1)相关的知识,希望对你有一定的参考价值。4 ... [详细]
  • C#设计模式(8)——桥接模式(Bridge Pattern)
    原文地址:http:www.cnblogs.comzhilipBridgePattern.html原文作者:Learninghard原文出处:博客园一、引言 ... [详细]
  • ———Java培训、Android培训、iOS培训、.Net培训、期待与您交流!———一、引用计数器每个OC对象都有自己的引用计数器,表示“对象被引用 ... [详细]
  • Lodash中文文档(v3.10.1)–“Collection”要领TranslatedbyPeckZegOriginalDocs:Lodashv3.10.1Docs乞助翻译文档的 ... [详细]
  • post请求,携带json对象参数模拟获取tokenpublicstaticStringgetToken()throwsIOException{创建连接CloseableHttp ... [详细]
  • 作者|相学长原文|https:github.comwuomzfxblogblobmasterthis.md日常开发中,我们经常用到this。例如用Jquery绑定事件 ... [详细]
  • C#使用System.Net.Mail类实现邮件发送【.Net开发】
    这篇文章介绍了C#使用System.Net.Mail类实现邮件发送的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值, ... [详细]
  • 1、对于List而言,要不然就使用迭代器,要不然就从后往前删除,从前往后删除会出现角标越界。因为我List有两个remove方法,一个是int作为形参(删除指定位置的元素),一个是 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
author-avatar
nn371417415
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有