X C Bindings

XCB 是应用与 X 服务器交互使用的 C 绑定函数集,它里面的一些 C 函数是通过 python3-xcbgen 工具生成的,不经过编译在它的源码库是找不到的。而且 XCB 古老到仍然使用 autotools 那套构建系统,想要看到某些函数的“真容”,你还得“千呼万唤”。

Vulkan Application

Vulkan 是一个低开销、跨平台的二维和三维图形与计算的应用程序接口,由 Khronos 在2015年在 GDC 上首次发布。它旨在提供高效能和更均衡的 CPU 和 GPU 占用,类似于 Direct3D 12 和 AMD Mantle。

本文主要记录一下在 llvmpipe 软渲染 Vulkan 驱动下, 一个 vulkan 应用程序 (demo) 的执行过程。

Linux accel 子系统

Linux 计算加速器子系统旨在以通用的方式向用户空间开放计算加速器的接口。这些计算加速器可以是独立的 ASIC, 也可以是 SoC/GPU 内的 IP 块。通常计算加速器包括以下几种类型:

  • 边缘 AI - 在边缘设备上进行推理计算
  • 推理数据中心 - 大型服务器中的单用户/多用户设备
  • 训练数据中心 - 类似于推理数据中心卡,但通常具有更强的计算能力和更高的存储带宽

ROCm

高端硅片可以构建市场,但最终,软件支持往往决定了赢家和输家

        -- Jack Huynh, AMD 高级副总裁兼计算和图形业务集团总经理

AMD 的通用计算平台 ROCm (Radeon Open Compute) 是在通用计算领域与 NVIDIA 的 CUDA (Compute Unified Device Architecture) 相抗衡的软件基础设施。ROCm 实现的其实是由 AMD 发起的 HSA (Heterogeneous System Architecture) 标准,所以它的运行时主要由 3 个部分组成:

OOC: ROCm 平台又叫 Boltzmann 平台,原因据说是为了纪念统计力学和热力学领域著名物理学家路德维希·玻尔兹曼,他的工作对理解物质的微观行为和能量分布有着深远的影响。AMD 选取这个名字,可能是为了强调该平台在高性能计算领域的强大计算力和科学计算的应用前景。

AMD GPU Vulkan Drivers for Linux

AMD 在 Linux 下维护着两套开源 Vulkan 驱动:

  • AMDVLK
    • 从闭源 Windows Vulkan 驱动适配而来,主要不同在 shader 编译后端, AMDVLK 使用基于 LLVM 的 LLPC
  • RADV
    • 是 Mesa 项目的一部分,主要由社区驱动。使用的 shader 编译后端是基于 NIR 的 ACO (AMD COmpiler)

这里主要是记录一下两者的异同点,学习两者不同的设计策略及其作出选择的背后理念。

perfetto

Perfetto

Perfetto 是一个用于 Linux 和 Android 系统上进行系统级和应用级的跟踪和性能分析的开源工具。Perfetto 捆绑了许多数据源,这些数据源能够从不同的系统接口收集详细的性能数据,包括 ftrace, /proc, /sys, native heap profiling 等。Perfetto 还提供了一个基于 Web 的用户界面,用于跟踪数据的可视化和分析。这里主要是对第一次使用 perfetto 做一下记录,方便以后继续学习和整理。

perfetto

OpenGL Shading Languages

GLSL 是一种高级着色语言,语法接近 C 语言。它由 OpenGL ARB 创建,旨在让开发者能够更直接地控制图形管线,而无需使用 ARB 汇编语言或特定硬件语言。

实际上 GLSL 包括大概 6 种着色语言:

  • 顶点着色语言 (.vert)
  • 细分控制语言 (.tesc)
  • 细分评估语言 (.tese)
  • 几何着色语言 (.geom)
  • 片段着色语言 (.frag)
  • 计算着色语言 (.comp)

升2级后的第一盘

升2级后的第一盘棋黑竟然下出了连续11手的AI一选(从黑97到黑121), 当然这也与白的应招有关系。不过 可惜最终黑123还是错失翻盘机会。局后复盘,看到连续11手的一选有点激动,故此记录

龙芯CPU&GPU

CPU

LS3A6000

龙芯的芯片产品可以分为信息化领域和工控/嵌入式领域, 3A6000 也有分别应用于这两个领域的配置,7A2000同样有两种。3A6000 是龙芯第四代微架构的首款产品,同样采用龙芯自主指令集架构LoongArch64(首款LoongArch64架构的处理器是3A5000)

Ubuntu 的 OpenGL 环境

GLVND(Vendor Neutral GL dispatch library)

Source Directory Target APT Package
GLX
EGL
GLDispatch libGLdispatch.so libglvnd0
OpenGL libOpenGL.so libopengl0
GLESv1 libGLESv1_CM.so libgles1
GLESv2 libGLESv2.so libgles2
GL libGL.so.1.7.0 libgl1

ReadPixels in Mesa

glReadPixels

glReadPixels 是将当前绑定的 FBO 里的内容从显存(renderbuffer, 通常是 read renderbuffer) 读到 *data 指向的内存。

1
2
3
void glReadPixels(GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type, void *data);

Replacing NIR with SPIR-V?

“Replacing NIR with SPIR_V?” 是mesa-dev maillist 上2022-01-20的一封邮件主题. 从邮件讨论中我了解到了许多知识,在此记录一下。

名词 全称 解释
IR Intermediate Representation 编译器中使用的中间表示,一般是编译器优化 Pass 和后端的输入
NIR New IR Mesa 中专门为 Graphics shader 设计的一种 IR, 它可以作为特定后端的输入,如 LLVM AMDGPU 后端
SPIR Standard Portable IR 一种用于并行计算和图形的中间语言(interchage language), 由 Khronos Group 在 2012 年引入
SPIR-V SPIR-Vulkan 由 Khronos Group 在 2015 年引入,用来替代原来的 SPIR
RISC Reduced Instruction Set Computer 精简指令集, 与 CISC 相对
RISC-V RISC five 由加州 Berkeley 大学开发的一种开放且模块化的 RISC 指令集架构
SIMD Single Instruction Multiple Data 费林分类法(Flynn’s Taxonomy) 中的一种,其它的还有 SISD, MIMD, MISD
SIMT Single Instruction Multi-Threads SIMD 的一种子类型

学弈

棋理

最近和朋友的孩子下了几盘棋,在惊叹现在孩子的聪慧和学习能力之余,也深感自己的“棋艺”着实有待提高。便又拣起荒废已久的弈城账号,想下几盘找找感觉,结果又一次应了那句,“业精于勤,荒于嬉”。失落之余,索性去 B 站,重看邱百瑞老师的带你零基础学围棋.
再看确实有不一样的感受。围棋的奥妙和那些千古流传的棋理自不必多说,我想自己学习下棋,试着了解棋理的原因,也是被围棋这种“方寸之间有天地,黑白之处显乾坤”的魅力所折服。

我在邮件列表里学英语

Communication is hard, especially with all the different personalities, languages, and
cultures involved in an international community like this.

Faith Ekstrand

It is rules and not our individual smarts that keep us from making mistakes.

Faith Ekstrand

电影里的经典台词

Scent of a woman (1992)

No mistakes in the Tango, not like life. It’s simple, that’s what makes the Tango so great. If you make a mistake, get all tangled up, just Tango on.

Rudy (1993)

Having dreams is what makes life tolerable

The Shawshank Redemption (1994)

Get busy living or get busy dying

Cache 一致性

Cache

音同 cash, 不管是在硬件还是软件都是影响性能的一个重要因素之一。Cache 无论是 CPU cache 还是 GPU cache 一般都分级, L1,L2, 在 Multi-processor CPU/GPU 架构中, L1 一般是分开的,每个 Processor 有一个自己的 L1 Cache, 而 L2 Cache 是全局的,所有 processors 共享的。

Play with HiKey970

环境准备

WSL2 作为上位机

识别 Windows 11 Host 的 USB Serial Device

分别在 Windows 11 上安装 usbipd-win, 在 WSL2 上安装 user space tools for USB/IP

1
2
3
4
5
6
7
Microsoft Windows [版本 10.0.22621.1702]
(c) Microsoft Corporation。保留所有权利。

C:\Windows\System32>usbipd wsl list
BUSID VID:PID DEVICE STATE
1-9 046d:c534 USB 输入设备 Not attached
1-13 04e2:1410 USB 串行设备 (COM4) Not attached

WSL2 Ubuntu-20.04 创建 /dev/ttyUSB0

1
2
3
4
5
6
7
8
9
10
11
[Thu Jun 15 19:19:44 2023] vhci_hcd vhci_hcd.0: pdev(0) rhport(0) sockfd(3)
[Thu Jun 15 19:19:44 2023] vhci_hcd vhci_hcd.0: devid(65546) speed(2) speed_str(full-speed)
[Thu Jun 15 19:19:44 2023] vhci_hcd vhci_hcd.0: Device attached
[Thu Jun 15 19:19:45 2023] vhci_hcd: vhci_device speed not set
[Thu Jun 15 19:19:45 2023] usb 1-1: new full-speed USB device number 2 using vhci_hcd
[Thu Jun 15 19:19:45 2023] vhci_hcd: vhci_device speed not set
[Thu Jun 15 19:19:45 2023] usb 1-1: SetAddress Request (2) to port 0
[Thu Jun 15 19:19:45 2023] usb 1-1: New USB device found, idVendor=04e2, idProduct=1410, bcdDevice= 0.03
[Thu Jun 15 19:19:45 2023] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Thu Jun 15 19:19:45 2023] xr_serial 1-1:1.0: xr_serial converter detected
[Thu Jun 15 19:19:45 2023] usb 1-1: xr_serial converter now attached to ttyUSB0

Recovery 模式应该连接哪个 Type-C (USB SERIAL) 接口

HiKey970 有两个 Type-C 接口,而且当板子被设置为 Recovery 模式时,两个接口均会被识别为“串口”。在左手边的 (J3101) 是用来访问 Debug UART 的,而在 HDMI 和 USB 中间的那个(J1801)是在 Recovery 模式下使用的。而且这两个接口是两个不同厂家提供的芯片,使用完全不同的内核驱动模块

USB-to-Serial on Hikey970

  • 前者(J3101):
    Bus 001 Device 003: ID 04e2:1410 Exar Corp. XR21V1410 USB-UART IC

Select CONFIG_USB_SERIAL_XR on WSL2 Kernal config

  • 后者(J1801):
    Bus 001 Device 002: ID 12d1:3609 Huawei Technologies Co., Ltd. USB SER

Select CONFIG_USB_SERIAL_OPTION on WSL2 Kernal config

参考

1. HiKey970 官方文档
2. usbipd-win github issues

Linux System Calls

系统调用是Linux 用户态程序与内核通信的接口。 每个特定的文件系统都会在自己的 file_operations里提供各种文件操作接口,这些接口包括像 open, close, ioctl 等等

Syscall signature Function description
int dup(int oldfd);
int dup2(int oldfd, int newfd);
uid_t getuid(void);
uid_t geteuid(void);
pid_t getpid(void); return process ID of calling process
pid_t getppid(void); return process ID of parent of calling process
int ioctl(int fd, unsigned long request, …); 操作底层设备参数,尤其像终端这种字符设备

ioctl

ioctl

ioctl 的返回值

ioctl 成功返回 0, 否则返回 -errno (有的 man ioctl 说ioctl不成功时返回 -1, 这种应该是过时的文档)。

Linux Kernel Debugging

CONFIG_DEBUG_FS

如何在 WSL2 上启用 debugfs

确认下内核是否开启了 debugfs

1
zcat /proc/config.gz | grep CONFIG_DEBUG_FS

要想使用 debugfs,首先要挂载它到 /sys/kernel/debug

1
mount -t debugfs none /sys/kernel/debug/

Knowledge from "[RFC] Plane color pipeline KMS uAPI"

Gamma LUT property

Gamma LUT (Look-Up Table) is a property that is used to correct the color and brightness of an image or video. Gamma LUT is basically a table of values that is used to map input values to output values, for example, it may map low input values to higher output values to brighten the image.

Gamma LUT is used to adjust the gamma curve of an image or video, which means it can be used to correct the brightness and contrast of an image. This property is commonly used in image and video processing applications, such as photo editing software, video editing software, and color grading tools.

Gamma LUT can also be used to correct color shifts caused by different lighting conditions or camera settings. By adjusting the gamma curve of an image or video, it is possible to create a more natural and accurate representation of the original scene.

Submitting My First Linux Kernel Patch

Linux 内核的 patch 是以纯文本的邮件形式进行提交和代码走查的,而且 patch 是先到内核子系统 maintainer 维护的 git tree, 再到 Linus Torvalds 的 main tree。本文主要是以一个 patch 提交的实例来记录一下整个过程中的一些具体操作要点,至于 kernel patch 提交的规范和操作细节内核文档 和各种博客文章有很多,这里不再赘述。

ChatGPT 告诉我的

标准

ACPI 是什么?

ACPI是一个开放标准,全称为Advanced Configuration and Power Interface(高级配置与电源接口)。它是一种用于电源管理和配置硬件设备的接口规范。

ACPI的主要目的是提供一种标准化的方法,使操作系统能够与计算机的固件(如BIOS)进行交互,管理电源管理、设备配置和系统资源的一致性。它定义了一组操作系统接口和数据结构,用于控制和监测硬件设备的电源状态、配置和事件。

通过ACPI,操作系统能够实现电源管理的功能,如系统的睡眠、休眠和唤醒,以及动态调整设备的功耗和性能。它还提供了高级功能,包括热插拔设备的支持、温度传感器的监测以及处理器性能的调整。

ACPI存在于大多数现代计算机系统中,并得到广泛支持。它在各种操作系统中广泛使用,包括Windows、Linux、Apple macOS等。通过ACPI,计算机系统能够更好地管理电源和硬件资源,实现能效和性能的平衡,提供更好的用户体验。

UEFI GOP 是什么?

UEFI GOP 是 UEFI(统一可扩展固件接口)中的一个图形输出协议。它提供了在 UEFI 环境下进行图形输出的标准接口。

UEFI GOP 的主要功能包括:

  • 提供图形模式设置、获取当前图形模式等图形初始化相关功能。

  • 提供绘制像素、填充矩形、绘制线条等基本图形输出功能。

  • 提供双缓冲区切换、视口管理等高级图形功能。

  • 支持各种颜色格式如 RGB、YUV 等。

  • 提供与硬件无关的抽象接口,通过 GOP 驱动与特定硬件交互。

  • 支持全屏和窗口两种输出模式。

  • 支持各种分辨率的图形输出。

通过使用 UEFI GOP,操作系统和应用可以在 UEFI 阶段实现图形界面和图形输出,如启动菜单、系统配置界面等。许多操作系统的启动器都会使用 GOP 进行图形化显示。

所以简单来说,UEFI GOP 为 UEFI 固件和操作系统提供了标准的图形输出接口,使其可以实现固件过程中的图形化显示和交互。它是实现 UEFI 图形环境的基础。

HSA 是什么?

HSA(Heterogeneous System Architecture) 是一种异构系统架构,用于在CPU和GPU等异构处理器之间进行并行计算。其主要特点包括:

  • 协处理器架构:HSA定义了主处理器(CPU)和协处理器(GPU等)之间的关系,协处理器协助CPU完成计算任务。

  • 统一地址空间:CPU和协处理器共享同一个虚拟地址空间,可以直接访问对方的内存。

  • 协作计算模型:支持CPU和协处理器之间的并行计算,任务可以自动在最合适的处理器上运行。

  • 优化数据传输:通过DMA等机制优化CPU和协处理器之间的数据传输。

  • 标准化程序接口:为开发人员提供标准化的程序接口,简化异构计算的软件设计。

HSA让CPU和GPU之间可以高效协作,优化系统整体的并行计算性能,被认为是未来异构计算架构的发展方向。AMD是HSA的主要推动者,其APU产品已经开始支持HSA。HSA也吸引了其他处理器厂商的广泛支持。

总而言之,HSA是一种创新的异构系统架构,通过处理器协作和优化提升整体计算性能,对高效并行计算有重要意义。

目前支持HSA标准的SoC产品不多,主要有:

  • AMD Kaveri APU:这是AMD于2014年发布的首款HSA 1.0兼容APU,集成CPU和GPU,支持共享虚拟内存。

  • AMD Carrizo APU:2015年发布,同样支持HSA 1.0,并进一步增强了CPU和GPU的协作计算能力。

  • AMD Ryzen APU:如Ryzen 5 2400G,集成Vega graphics,支持共享内存和异构计算。

  • AMD Raven Ridge APU:首款集成Vega图形的Ryzen移动APU,支持HSA。

  • Qualcomm Snapdragon 820:高通在Snapdragon 820平台增加了HSA 1.1支持。

  • 领悟科技(HSA Foundation)Mustang-V100-A10:这是全球首块完全兼容HSA 1.0规范的独立heterogeneous SoC。

  • 领悟科技(HSA Foundation)Mustang-F100-A10:进一步优化的heterogeneous SoC。

总体来说,AMD是目前最主要的HSA支持厂商,其多款APU产品都实现了HSA规范。高通也加入了HSA支持。此外,一些创业公司如领悟科技也推出了支持HSA的SoC。随着规范的逐步完善,预计未来将会有更多的异构SoC产品实现HSA兼容。

我:那么符合 HSA 标准的 APU 与普通的 SoC 有什么区别?

ChatGPT:

符合HSA标准的APU和普通SoC的主要区别有:

  1. 统一地址空间

HSA APU采用统一地址空间,CPU和GPU可以直接访问对方的缓存和内存,简化数据传输。普通SoC的CPU和GPU存在独立的地址空间。

  1. 优化的内存访问

HSA APU支持CPU和GPU直接访问系统内存,无需数据复制,提高效率。普通SoC需要在内存空间之间进行数据复制。

  1. 标准化的程序接口

HSA提供标准化的程序接口如HSAIL,简化异构编程的复杂ity。普通SoC缺乏统一的接口。

  1. 优化的协作计算

HSA APU通过协处理器等机制,可根据workload自动在CPU和GPU间分配任务,调度更优化。普通SoC无法做到如此灵活的协作计算。

  1. 更高效的互联

HSA APU采用高速互联如AMD的Infinity Fabric,提升CPU和GPU之间的数据传输速度。

  1. 更紧密的硬件协作

HSA APU通过硬件级的优化如内存控制器集成,实现更紧密的协作。

综上,HSA APU通过硬件架构和软件接口的优化,实现了CPU与GPU更加紧密、高效的异构计算,相比普通SoC有明显优势。这使其在并行计算性能上有显著提升。

Linux

mmu_notifier vs. mmu_interval_notifier

M: please shed light on the distinction mmu_notifier from mmu_interval_notifier in the linux kernel

C: In the Linux kernel, both MMU notifier and MMU interval notifier are used to track changes in page tables and memory mappings. However, there are some differences between the two:

MMU notifier is used to track changes to page tables and memory mappings, and it is designed to be a general-purpose notifier. It is used by various subsystems in the kernel, such as memory management, file systems, and device drivers.

MMU interval notifier, on the other hand, is used specifically to track changes to a range of memory pages. It is used by subsystems that need to be notified of changes to a particular range of memory pages, such as virtualization subsystems.

In summary, MMU notifier is a more general-purpose notifier used to track changes to page tables and memory mappings, while MMU interval notifier is used specifically to track changes to a range of memory pages.

Installable Client Driver

来自 ChatGPT 的解释

What is Vulkan ICD?

Vulkan ICD (Installable Client Driver) is a software component that enables the Vulkan API (Application Programming Interface) to interact with the hardware of a computer system. Vulkan is a low-level graphics API developed by the Khronos Group, which provides developers with more control over hardware resources, leading to improved performance and efficiency in graphics-intensive applications such as video games. The Vulkan ICD is responsible for managing the communication between the Vulkan API and the graphics hardware of a system. It is typically provided by the manufacturer of the graphics card as a driver for the system.

Light Display Manager

Light Display Manager 是一个轻量级的跨桌面环境的 Display Manager, 可以支持多种显示技术,如 X11, Mir, Wayland.

Build

Dependencies

  • 开发包依赖

    • libpam0g-dev
    • libgcrypt20-dev
    • libglib2.0-dev
    • libxklavier-dev
  • 构建工具依赖

    • intltool
    • yelp-tools
    • gtk-doc-tools
  • 安装

Lightdm 可执行程序路径 /usr/sbin/lightdm, 日志默认路径 /var/log/lightdm/lightdm.log. 所以构建时可以使用

  • --prefix 指定安装路径 (默认 /usr/local)
  • --localstatedir 指定日志路径 (默认 $prefix/var/log/lightdm)
  • --sysconfdir 指定 lightdm.conf 路径 (默认 $prefix/etc/lightdm)
1
2
3
./autogen.sh --prefix=/usr --localstatedir=/var --sysconfdir=/etc --disable-tests
make -j $JOBS
sudo make install

Graphics Boot-up

lightdm starts Xorg

Using Sanitizers

Sanitizer 简介

Sanitizer 是一个动态 Bug 检测的工具,它可以检测的 Bug 有以下几类:

  • AddressSanitizer (ASan):
    • use-after-free
    • double-free
    • buffer (heap, stack, and global buffer) overflows
  • MemorySanitizer (MSan): uninitialized memory reads
  • UndefinedBehaviorSanitizer (UBSan)
    • signed integer overflow
    • use-of-null-pointer
    • division by zero
  • ThreadSanitizer: data races, deadlocks
  • LeakSanitizer: memory leaks

参考

[1]Be wise, sanitize: Keeping your C++ code free from bugs
[2]An LLVM developer setup: Modern C++ development tools

Building Linux Kernel

Should Know Something About Kernel Building

  • 配置内核最简单的方法是 make olddefconfig
  • 内核配置保存在 .config
  • 内核源码树里包含命令行修改 .config 的脚本 scripts/config
  • 内核构建依赖 flex, bison 词法分析程序

Build on Ubuntu 22.04

Environment

configuration version
distro Ubuntu 22.04 Jammy Jellyfish
gcc 11.2.0
original kernel 5.15.0-43-generic
building kernel v6.0

Compilation Errors

Errors Resolution
gelf.h: No such file or directory apt install libelf-dev
<openssl/opensslv.h>: No such file or directory apt install libssl-dev
No rule to make target ‘debian/canonical-certs.pem’ scripts/config –disable SYSTEM_TRUSTED_KEYS
No rule to make target ‘debian/canonical-revoked-certs.pem’ scripts/config –disable SYSTEM_REVOCATION_KEYS

Build on WSL2

Build Config

1
make KCONFIG_CONFIG=Microsoft/config-wsl

Compilation Errors

apt install -y dwarves

这是一个非常常见的依赖问题

1
2
3
4
5
6
7
8
  LD      vmlinux.o
MODPOST vmlinux.symvers
MODINFO modules.builtin.modinfo
GEN modules.builtin
BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF
make: *** [Makefile:1218: vmlinux] Error 1

Direct WSL to the new vmlinux

新内核产生

1
2
3
4
5
6
7
8
9
  AS      arch/x86/boot/header.o
CC arch/x86/boot/version.o
LD arch/x86/boot/setup.elf
OBJCOPY arch/x86/boot/setup.bin
OBJCOPY arch/x86/boot/vmlinux.bin
BUILD arch/x86/boot/bzImage
Kernel: arch/x86/boot/bzImage is ready (#3)
MODPOST modules-only.symvers
GEN Module.symvers

新内核生效

  1. mv arch/x86/boot/bzImage /mnt/c/Users/luc/

  2. 编辑 /mnt/c/Users/luc/.wslconfig, 添加下面两行

1
2
[wsl2]
kernel=C:\\Users\\luc\\bzImage

NOTE: 如果以上两行添加进 /etc/wsl.conf 文件,不会有任何作用, 因为 /etc/wsl.conf 不支持 wsl2 Section

  1. 配置完成后,重启 WSL Ubuntu 20.04, 新编译的内核将生效。不要用 wsl --terminate.
1
wsl --shutdown Ubuntu-20.04

打开 CONFIG_DRM_VKMS

1
make nconfig

NOTE: 在 WSL 上不能将配置项置为 ‘M’, 而要 ‘Y’

配置更改后重新 make

Testing With IGT on WSL2

1
2
3
4
5
6
7
8
9
10
11
➜  tests git:(master) sudo ./kms_writeback --device "sys:/sys/devices/platform/vkms"
IGT-Version: 1.27.1-g45da871d (x86_64) (Linux: 5.15.90.1-microsoft-standard-WSL2+ x86_64)
(kms_writeback:9671) igt_kms-WARNING: Output Writeback-1 could not be assigned to a pipe
Starting subtest: writeback-pixel-formats
Subtest writeback-pixel-formats: SUCCESS (0.000s)
Starting subtest: writeback-invalid-parameters
Subtest writeback-invalid-parameters: SUCCESS (0.000s)
Starting subtest: writeback-fb-id
Subtest writeback-fb-id: SUCCESS (0.018s)
Starting subtest: writeback-check-output
Subtest writeback-check-output: SUCCESS (0.124s)
  • dmesg
1
2
3
4
5
6
[10893.662944] [IGT] kms_writeback: executing
[10893.673240] [IGT] kms_writeback: starting subtest writeback-pixel-formats
[10893.674026] [IGT] kms_writeback: starting subtest writeback-invalid-parameters
[10893.675055] [IGT] kms_writeback: starting subtest writeback-fb-id
[10893.693563] [IGT] kms_writeback: starting subtest writeback-check-output
[10893.826984] [IGT] kms_writeback: exiting, ret=0

观“老石谈芯”视频笔记 (二)

Glossary

  • PoC: Proof of Concept, 概念验证
  • Chisel: tExtended on Scala
  • GDSII: 版图
  • RTL: Register-Transfer Level, RTL 语言包括 SystemVerilog, Verilog, VHDL等
  • FIRRTL: Chisel 的“翻译器”, Chisel -> Verilog
  • shift left: 把验证和调试放在 tape in 阶段
  • GEM5: C Simulator for GPU
  • PPA: Power, Performance, Area, used in deciding how to optimize semiconductor designs

LLVM

LLVM & llvm-project

LLVM 是 Low-Level Virtual Machine 的简写,但事实上它与虚拟机关系不大。我们更熟悉它是一套工具链,包括 clang /'klæŋ/, lld, lldb 等等。接触 LLVM 是因为 Mesa llvmpipe 使用 LLVM, 还有 AMDGPU 和 Radeon 的编译器后端都使用 LLVM IR,所以要编译 Mesa 的 -Dgallium-drivers=llvmpipe,radeonsi 都依赖于 LLVM 的诸多组件, 构建 Linux 内核的 eBPF 程序也依赖 LLVM, 构建 perfetto 也依赖 LLVM。这里主要记录 LLVM 的构建和使用的一些问题。

Regular Expression

Regular Expressions

GNU Extensions

Shorthand Classes

shorthand equivalence
\w [[:alnum:]_]
\W [^[:alnum:]_]
\s [[:space:]]
\S [^[:space:]]

Word Boundaries

shorthand matches
\b position at a word boundary
\B position not at a word boundary
\< position at the start of a word
\> position at the end of a word
\` (backtick) position at the start of subject string
\' (single quote) position at the end of subject string

Advanced Shell

Bash Shell

Parameter Expansion

Use an alternate value

1
2
${var:+WORD}
${var+WORD}

如果 var 没有设置或为空,则这个变量展开为 Nothing (注意:不是空 empty, 是 nothing), 如果被设置了(不包括被设置成空),它展开为 + 后面的 WORD.

如果冒号被省略,则 var 即使被设置为空,它也展开为 + 后面的 WORD

Indirect

1
${!var}

如果 var 的值是 MESA_DEBUG, 那么这个形式展开后是变量 MESA_DEBUG 的值,例如 export MESA_DEBUG=1, var=MESA_DEBUG, 则最后的展开结果是 1

Quoted

1
${var@Q}

@Q 指变量展开后的值被单引号引起来,例如 export ABC=abc, echo "ABC=${ABC@Q}" 的结果是 ABC='abc'

Text Manipulation

Linux 下的文本处理三剑客: grep, sed, awk, 除了它们其实还有一些小巧的命令,如 tr, cut 也可以帮助我们快速处理和格式化文本。
下面以一个例子为例。

在 Linux 内核源码树里,搜索出目录 drivers/gpu/drm 下所有的 DRIVER_NAME 定义,并排序后格式化输出

命令如下:

1
rg '#define DRIVER_NAME' drivers/gpu/drm --no-heading | tr -s '\t' | tr '\t' ' ' | tr -s ' ' | awk -F':' '{printf("%-52s%-40s\n",$1,$2)}' | sort -k4 | xclip -i
  • rg (ripgrep) 比 grep 更快,更强大
  • tr 在不带任何选项时,默认执行替换,例子是中将 tab 替换成 空格, -s 表示 squeeze-repeats, 就是去重
  • awk 天生支持 C-Style printf

输出结果:

  • 格式化之前:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
drivers/gpu/drm/solomon/ssd130x.c:#define DRIVER_NAME	"ssd130x"
drivers/gpu/drm/solomon/ssd130x-i2c.c:#define DRIVER_NAME "ssd130x-i2c"
drivers/gpu/drm/solomon/ssd130x-spi.c:#define DRIVER_NAME "ssd130x-spi"
drivers/gpu/drm/exynos/exynos_drm_drv.c:#define DRIVER_NAME "exynos"
drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c:#define DRIVER_NAME "imx8qxp-display-pixel-link"
drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c:#define DRIVER_NAME "imx8qxp-pxl2dpi"
drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c:#define DRIVER_NAME "imx8qxp-pixel-combiner"
drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c:#define DRIVER_NAME "imx8qxp-ldb"
drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c:#define DRIVER_NAME "imx8qm-ldb"
drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c:#define DRIVER_NAME "dw-hdmi-gp-audio"
drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c:#define DRIVER_NAME "dw-hdmi-ahb-audio"
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c:#define DRIVER_NAME "dw-hdmi-i2s-audio"
drivers/gpu/drm/meson/meson_dw_hdmi.c:#define DRIVER_NAME "meson-dw-hdmi"
drivers/gpu/drm/meson/meson_drv.c:#define DRIVER_NAME "meson"
drivers/gpu/drm/omapdrm/omap_drv.c:#define DRIVER_NAME MODULE_NAME
drivers/gpu/drm/sprd/sprd_drm.c:#define DRIVER_NAME "sprd"
drivers/gpu/drm/savage/savage_drv.h:#define DRIVER_NAME "savage"
drivers/gpu/drm/i810/i810_drv.h:#define DRIVER_NAME "i810"
drivers/gpu/drm/mediatek/mtk_drm_drv.c:#define DRIVER_NAME "mediatek"
drivers/gpu/drm/mga/mga_drv.h:#define DRIVER_NAME "mga"
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h:#define DRIVER_NAME "amdgpu"
drivers/gpu/drm/vboxvideo/vbox_drv.h:#define DRIVER_NAME "vboxvideo"
drivers/gpu/drm/vkms/vkms_drv.c:#define DRIVER_NAME "vkms"
drivers/gpu/drm/via/via_dri1.c:#define DRIVER_NAME "via"
drivers/gpu/drm/sti/sti_drv.c:#define DRIVER_NAME "sti"
drivers/gpu/drm/imx/ipuv3/imx-ldb.c:#define DRIVER_NAME "imx-ldb"
drivers/gpu/drm/udl/udl_drv.h:#define DRIVER_NAME "udl"
drivers/gpu/drm/nouveau/nouveau_drv.h:#define DRIVER_NAME "nouveau"
drivers/gpu/drm/mgag200/mgag200_drv.h:#define DRIVER_NAME "mgag200"
drivers/gpu/drm/vgem/vgem_drv.c:#define DRIVER_NAME "vgem"
drivers/gpu/drm/qxl/qxl_drv.h:#define DRIVER_NAME "qxl"
drivers/gpu/drm/radeon/radeon_drv.h:#define DRIVER_NAME "radeon"
drivers/gpu/drm/rockchip/rockchip_drm_drv.c:#define DRIVER_NAME "rockchip"
drivers/gpu/drm/virtio/virtgpu_drv.h:#define DRIVER_NAME "virtio_gpu"
drivers/gpu/drm/tiny/gm12u320.c:#define DRIVER_NAME "gm12u320"
drivers/gpu/drm/tiny/simpledrm.c:#define DRIVER_NAME "simpledrm"
drivers/gpu/drm/tiny/ofdrm.c:#define DRIVER_NAME "ofdrm"
drivers/gpu/drm/v3d/v3d_drv.c:#define DRIVER_NAME "v3d"
drivers/gpu/drm/gma500/psb_drv.h:#define DRIVER_NAME "gma500"
drivers/gpu/drm/hyperv/hyperv_drm_drv.c:#define DRIVER_NAME "hyperv_drm"
drivers/gpu/drm/sis/sis_drv.h:#define DRIVER_NAME "sis"
drivers/gpu/drm/tdfx/tdfx_drv.h:#define DRIVER_NAME "tdfx"
drivers/gpu/drm/i915/i915_driver.h:#define DRIVER_NAME "i915"
drivers/gpu/drm/r128/r128_drv.h:#define DRIVER_NAME "r128"
drivers/gpu/drm/tiny/cirrus.c:#define DRIVER_NAME "cirrus"
drivers/gpu/drm/tegra/drm.c:#define DRIVER_NAME "tegra"
drivers/gpu/drm/ast/ast_drv.h:#define DRIVER_NAME "ast"
drivers/gpu/drm/vc4/vc4_drv.c:#define DRIVER_NAME "vc4"
  • 格式化之后:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h             #define DRIVER_NAME "amdgpu"            
drivers/gpu/drm/ast/ast_drv.h #define DRIVER_NAME "ast"
drivers/gpu/drm/tiny/cirrus.c #define DRIVER_NAME "cirrus"
drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c #define DRIVER_NAME "dw-hdmi-ahb-audio"
drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c #define DRIVER_NAME "dw-hdmi-gp-audio"
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c #define DRIVER_NAME "dw-hdmi-i2s-audio"
drivers/gpu/drm/exynos/exynos_drm_drv.c #define DRIVER_NAME "exynos"
drivers/gpu/drm/tiny/gm12u320.c #define DRIVER_NAME "gm12u320"
drivers/gpu/drm/gma500/psb_drv.h #define DRIVER_NAME "gma500"
drivers/gpu/drm/hyperv/hyperv_drm_drv.c #define DRIVER_NAME "hyperv_drm"
drivers/gpu/drm/i810/i810_drv.h #define DRIVER_NAME "i810"
drivers/gpu/drm/i915/i915_driver.h #define DRIVER_NAME "i915"
drivers/gpu/drm/imx/ipuv3/imx-ldb.c #define DRIVER_NAME "imx-ldb"
drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c #define DRIVER_NAME "imx8qm-ldb"
drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c #define DRIVER_NAME "imx8qxp-display-pixel-link"
drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c #define DRIVER_NAME "imx8qxp-ldb"
drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c #define DRIVER_NAME "imx8qxp-pixel-combiner"
drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c #define DRIVER_NAME "imx8qxp-pxl2dpi"
drivers/gpu/drm/mediatek/mtk_drm_drv.c #define DRIVER_NAME "mediatek"
drivers/gpu/drm/meson/meson_drv.c #define DRIVER_NAME "meson"
drivers/gpu/drm/meson/meson_dw_hdmi.c #define DRIVER_NAME "meson-dw-hdmi"
drivers/gpu/drm/mga/mga_drv.h #define DRIVER_NAME "mga"
drivers/gpu/drm/mgag200/mgag200_drv.h #define DRIVER_NAME "mgag200"
drivers/gpu/drm/nouveau/nouveau_drv.h #define DRIVER_NAME "nouveau"
drivers/gpu/drm/tiny/ofdrm.c #define DRIVER_NAME "ofdrm"
drivers/gpu/drm/qxl/qxl_drv.h #define DRIVER_NAME "qxl"
drivers/gpu/drm/r128/r128_drv.h #define DRIVER_NAME "r128"
drivers/gpu/drm/radeon/radeon_drv.h #define DRIVER_NAME "radeon"
drivers/gpu/drm/rockchip/rockchip_drm_drv.c #define DRIVER_NAME "rockchip"
drivers/gpu/drm/savage/savage_drv.h #define DRIVER_NAME "savage"
drivers/gpu/drm/tiny/simpledrm.c #define DRIVER_NAME "simpledrm"
drivers/gpu/drm/sis/sis_drv.h #define DRIVER_NAME "sis"
drivers/gpu/drm/sprd/sprd_drm.c #define DRIVER_NAME "sprd"
drivers/gpu/drm/solomon/ssd130x.c #define DRIVER_NAME "ssd130x"
drivers/gpu/drm/solomon/ssd130x-i2c.c #define DRIVER_NAME "ssd130x-i2c"
drivers/gpu/drm/solomon/ssd130x-spi.c #define DRIVER_NAME "ssd130x-spi"
drivers/gpu/drm/sti/sti_drv.c #define DRIVER_NAME "sti"
drivers/gpu/drm/tdfx/tdfx_drv.h #define DRIVER_NAME "tdfx"
drivers/gpu/drm/tegra/drm.c #define DRIVER_NAME "tegra"
drivers/gpu/drm/udl/udl_drv.h #define DRIVER_NAME "udl"
drivers/gpu/drm/v3d/v3d_drv.c #define DRIVER_NAME "v3d"
drivers/gpu/drm/vboxvideo/vbox_drv.h #define DRIVER_NAME "vboxvideo"
drivers/gpu/drm/vc4/vc4_drv.c #define DRIVER_NAME "vc4"
drivers/gpu/drm/vgem/vgem_drv.c #define DRIVER_NAME "vgem"
drivers/gpu/drm/via/via_dri1.c #define DRIVER_NAME "via"
drivers/gpu/drm/virtio/virtgpu_drv.h #define DRIVER_NAME "virtio_gpu"
drivers/gpu/drm/vkms/vkms_drv.c #define DRIVER_NAME "vkms"
drivers/gpu/drm/omapdrm/omap_drv.c #define DRIVER_NAME MODULE_NAME

TexLive

Markdown to PDF

Highly recommended 3 utilities:

  • pandoc 标记语言转换领域的”瑞士军刀”
  • TexLive 开发最为活跃的 TeX 发行版之一
  • eisvogel 简洁的 pandoc LaTex 模板

eisvogel 要求一个完整的 TexLive 的安装环境,但通常像 CentOS 这样的 Linux 发行版自带的 TexLive 并不完整。

How to Install texlive.iso

Quick Install

将 TexLive 的镜像下载并挂载后,通过顶层目录下的 install-tl 这个 Perl 脚本程序安装,整个安装过程要注意以下几点。

mount ISO image

假设在 Linux 下,通过 root 用户或 sudo 挂载镜像文件

1
2
mkdir -p /mnt/iso
mount /path/to/texlive.iso /mnt/iso -o loop

run installer

TexLive 的 installer 是一个 perl script, 提供 text mode 和 GUI mode 两种安装模式.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
======================> TeX Live installation procedure <=====================

======> Letters/digits in <angle brackets> indicate <=======
======> menu items for actions or customizations <=======
= help> https://tug.org/texlive/doc/install-tl.html <=======

Detected platform: GNU/Linux on x86_64

<B> set binary platforms: 1 out of 6

<S> set installation scheme: scheme-full

<C> set installation collections:
40 collections out of 41, disk space required: 7262 MB (free: 168365 MB)

<D> set directories:
TEXDIR (the main TeX directory):
!! default location: /usr/local/texlive/2022
!! is not writable or not allowed, please select a different one!
TEXMFLOCAL (directory for site-wide local files):
/usr/local/texlive/texmf-local
TEXMFSYSVAR (directory for variable and automatically generated data):
/usr/local/texlive/2022/texmf-var
TEXMFSYSCONFIG (directory for local config):
/usr/local/texlive/2022/texmf-config
TEXMFVAR (personal directory for variable and automatically generated data):
~/.texlive2022/texmf-var
TEXMFCONFIG (personal directory for local config):
~/.texlive2022/texmf-config
TEXMFHOME (directory for user-specific files):
~/texmf

<O> options:
[ ] use letter size instead of A4 by default
[X] allow execution of restricted list of programs via \write18
[X] create all format files
[X] install macro/font doc tree
[X] install macro/font source tree
[ ] create symlinks to standard directories
[X] after install, set CTAN as source for package updates

<V> set up for portable installation

Actions:
<I> start installation to hard disk
<P> save installation profile to 'texlive.profile' and exit
<Q> quit

Enter command:
1
2
3
4
5
6
7
8
9
10
11
12
13
Options customization:

<P> use letter size instead of A4 by default: [ ]
<E> execution of restricted list of programs: [X]
<F> create all format files: [X]
<D> install font/macro doc tree: [X]
<S> install font/macro source tree: [X]
<L> create symlinks in standard directories: [X]
binaries to: /usr/bin
manpages to: /usr/man
info to: /usr/info
<Y> after install, set CTAN as source for package updates:
[X]

最好勾选此选项,避免使用 TexLive 时各种 Not Found, 原因是 TexLive 默认安装路径并不是标准 Linux 可执行程序的路径(如 /usr/bin), 而是 /usr/local/texlive, 如在 x86_64 安装 texlive2022.iso, 则可执行程序被安装在 /usr/local/texlive/2022/bin/x86_64-linux. 假如不想因为该路径没有在 PATH 里,最好就是在安装时直接在 /usr/bin 下创建相应符号链接。

texlive-full

在使用 xelatex, pdflatex 等 latex 程序时,可以常常遇到类似

! LaTeX Error: File 'fontawesome.sty' not found

xxx.sty 这样的报错,一般是缺少某个 texlive 包,但 texlive 的包太多了,如果懒得一个一个安装,可以

sudo apt install texlive-full

find

find 命令

find 命令用来在目录树里查找文件。本文主要介绍 GNU find. 它从每个 starting-point 开始递归搜索,通过求值 expression 的真值来确定输出结果。

find 的命令行组成

example-of-find

  • Options
  • Starting-point
  • Expression
    • Tests
    • Actions
    • Global options
    • Position options
    • Operators

Examples

  • 只在当前目录搜索(不递归)不以 f 或 g 或 h 开头的目录

    • find . -maxdepth 1 -name '[^fgh]*' -type d
  • 排除/proc 和 /tmp 这两个目录

    • find / -path /proc -prune -o -path /tmp -prune -o -name "README.md"
      • -prune 告诉 find 跳过前面的目录,也可以用 \( -o \) 将多个 -path 合并,只保留一个 -prune
  • 只在当前目录查找除了指定及隐藏目录以外的所有目录,打印并删除

    • find -maxdepth 1 \( -path ./gh -o -path ./aaa -o -path ./mesa-install -o -path ./1.3.290.0 -o -path ./1.3.280.1 \) -prune -o -type d ! -name ".*" -print -exec rm -rf {} \;
      • 注意匹配隐藏目录时用 .*, . 在 shell 里不是通配符
  • 查找 ~/gh 目录下只有文件属主(u)有执行权限(x)的文件 (精确匹配文件的 permission bits)

    • find ~/gh -perm u=x -type f
  • 查找 ~/gh 目录下文件属主(u)有执行权限(x) 的文件(组用户(g)或其它用户(o)可能有或没有执行权限)

    • find ~/gh -perm -u=x -type f

GL_ARB_geometry_shader4

Geometry Shader Input Layout Qualifiers

Geometry shader只能在接口限定符(interface qualifier)in前加Input Layout Qualifiers, 不能在输入块(input block), 块成员(block member), 或变量声明(variable declaration)前加Input Layout Qualifiers。

这些Input Layout Qualifiers有

My english is poor

A language that doesn’t affect the way you think about programming, is not worth knowing.

Alan J. Perlis, Recipient of 1966 Turing Award

弈城围棋

简介

弈城围棋是弈城围棋网推出的一款围棋学习和网络对战的 App. 它可安装在包括 Windows, Android, iOS, iPad, MacOS 在内的各个平台。

OpenGL Pipeline

OpenGL Pipeline

OpenGL Pipeline Stage Flowchart

说明:

  1. 蓝色框表示是Programmable Shader Stages
  2. 虚线框表示是Optional Shader Stages

C++ Template

C++中的模板

C++中的模板可分为class template和function template. 它们之间存在不同,例如,function template不能partially specialized(偏特化)

mesa中的winsys层

winsys有什么用

winsys像一个桥梁,它要将GPU渲染的结果传输到窗口系统的framebuffer,由显示系统将其呈现在屏幕上。

TTM vs GEM

TTM和GEM

Translation Table Maps(TTM)和Graphics Execution Manager(GEM)是Linux内核DRM子系统的两个内存管理器,前者先于后者被实现,也可以说GEM是为了解决TTM存在的一些问题才被设计出来的。下面的表格对它们两个的特点做了简单比较。

Hello, Rust

Rust Basic

  • Rust的编译器 rustc
  • Rust程序的构建系统或包管理器 cargo

Cargo.toml

[dependencies]

增加rand crate包后再执行构建

cargo update会做些什么

首先要了解的是在安装rustup后,在$HOME下会创建一个.cargo目录,它的目录结构大概如下

/home/luc/.cargo
|-- bin
|   |-- cargo
|   |-- cargo-clippy
|   |-- cargo-fmt
|   |-- cargo-miri
|   |-- clippy-driver
|   |-- rls
|   |-- rust-gdb
|   |-- rust-lldb
|   |-- rustc
|   |-- rustdoc
|   |-- rustfmt
|   `-- rustup
|-- env
`-- registry
    |-- cache
    |   `-- github.com-1ecc6299db9ec823
    |-- index
    |   `-- github.com-1ecc6299db9ec823
    `-- src
        `-- github.com-1ecc6299db9ec823

8 directories, 13 files

cargo update会根据工程目录下的Cargo.tomlDependencies的版本信息下载相应版本的依赖以及依赖的依赖,cargo update后的.cargo目录结构大概如下

/home/luc/.cargo
|-- bin
|   |-- cargo
|   |-- cargo-clippy
|   |-- cargo-fmt
|   |-- cargo-miri
|   |-- clippy-driver
|   |-- rls
|   |-- rust-gdb
|   |-- rust-lldb
|   |-- rustc
|   |-- rustdoc
|   |-- rustfmt
|   `-- rustup
|-- env
`-- registry
    |-- cache
    |   `-- github.com-1ecc6299db9ec823
    |       |-- libc-0.2.98.crate
    |       |-- rand-0.3.23.crate
    |       `-- rand-0.4.6.crate
    |-- index
    |   `-- github.com-1ecc6299db9ec823
    `-- src
        `-- github.com-1ecc6299db9ec823
            |-- libc-0.2.98
            |-- rand-0.3.23
            `-- rand-0.4.6

11 directories, 16 files

perf 和火焰图

环境 & 版本

  • Linux 5.10.16.3-microsoft-standard-WSL2 x86_64 x86_64
  • Ubuntu 20.04.2 LTS
  • perf version 5.10.16.3

NOTE: 如果没有特别说明,以下perf命令都在root权限下执行

CPU Hotplug in Linux

A Puzzle

如果先调用sched_setaffinity将线程绑定到CPU1上,再将CPU1逻辑关闭(offline),会发生什么?在Linux系统中,要回答这个问题,先要搞清楚Linux下的3个机制:

  • CPU hotplug
  • cpuset
  • scheduling affinity

CPU hotplug

CPU hotplug的意思是, Linux允许Logically ShutdownBring Up CPU, 用户可以通过sysfs接口操作

shutdown
1
echo 0 > /sys/devices/system/cpu/cpu1/online
bring up
1
echo 1 > /sys/devices/system/cpu/cpu1/online

What if the cpu is shutdown

/proc/interrupts, /proc/cpuinfo, top都将看不到它

What happened if the cpu is shutdown

我只列出跟上面的疑问有关系的:

  • All processes are migrated away from this outgoing CPU to new CPUs. The new CPU is chosen from each process’ current cpuset, which may be a subset of all online CPUs.

当关闭CPU1后,原来运行在CPU1上的进程将被移到新的CPU们上调度,具体哪个CPU是从这个进程当前的cpuset中选择,所以疑问转换成了“sched_setaffinity对进程当前的cpuset做了什么?”

cpuset

udev, sysfs & libudev

udev

udev是Linux系统管理/dev的内核组件,它负责在系统运行时动态的创建和删除/dev下的设备文件(节点)。

  • 当设备被检测到时创建设备文件
  • 当设备被移除时删除设备文件
  • /etc/udev/rules.d允许用户自定义设备文件的权限,路径和符号链接

udev显然是支持Hotplug, 而且保证/dev下的设备节点是实时更新的。而且它强大的用户自定义行为非常灵活。但它的问题是:

  • 用户自定义规则的存在让应用程序很难确定特定的设备文件和设备类型
  • 同一类型的多个设备,设备文件的创建顺序是不确定的

Reference

libudev and sysfs tutorial

GL_ARB_transform_feedback

Transform Feedback 引入

Transform Feedback首先是DirectX3D引入的,但在DirectX3D中它不叫TF, 而是叫Stream Output Stage. 它第一次被引入OpenGL是在2006年,但当时是以扩展的形式GL_EXT_transform_feedback引入的,它正式成为OpenGL Required Core Features是在OpenGL 3.0(2008), 在这之后,OpenGL 4.0, 4.2, 4.6又分别引入了一些TF相关的新特性。

OpenGL Extensions和Version

Talk About

  • OpenGL Extensions有哪些分类?
  • Conformant OpenGL implementation是什么?
  • OpenGL Extensions和OpenGL Versions有什么关系?
  • OpenGL Extensions和conformant OpenGL implementation有什么关系?

gcc那些事儿

内置宏

编译器会预定义许多宏,尤其在交叉编译时,不同的工具链编译器会定义不同的宏。例如:

  • aarch64
  • __ARM_ARCH_7A
  • __ARM_ARCH_8A

g++ 那些事儿

Installation on the Ubuntu

除了安装 C++ 标准库实现 libstdc++-9, g++-9 这些软件包外,还要安装 g++

dpkg-deb --contents /var/cache/apt/archives/g++_4%3a9.3.0-1ubuntu2_amd64.deb

1
2
3
4
5
6
7
8
9
10
11
12
drwxr-xr-x root/root         0 2020-03-20 21:52 ./
drwxr-xr-x root/root 0 2020-03-20 21:52 ./usr/
drwxr-xr-x root/root 0 2020-03-20 21:52 ./usr/bin/
drwxr-xr-x root/root 0 2020-03-20 21:52 ./usr/share/
drwxr-xr-x root/root 0 2020-03-20 21:52 ./usr/share/doc/
drwxr-xr-x root/root 0 2020-03-20 21:52 ./usr/share/man/
drwxr-xr-x root/root 0 2020-03-20 21:52 ./usr/share/man/man1/
lrwxrwxrwx root/root 0 2020-03-20 21:52 ./usr/bin/g++ -> g++-9
lrwxrwxrwx root/root 0 2020-03-20 21:52 ./usr/bin/x86_64-linux-gnu-g++ -> g++-9
lrwxrwxrwx root/root 0 2020-03-20 21:52 ./usr/share/doc/g++ -> cpp
lrwxrwxrwx root/root 0 2020-03-20 21:52 ./usr/share/man/man1/g++.1.gz -> g++-9.1.gz
lrwxrwxrwx root/root 0 2020-03-20 21:52 ./usr/share/man/man1/x86_64-linux-gnu-g++.1.gz -> g++-9.1.gz

了解 Linux DRM 子系统

DRM driver features

新DRM驱动的特性

  • DRIVER_GEM

使用GEM内存管理器,所有新的驱动都应该支持。

  • DRIVER_MODESET

支持Kernel Modesetting Interfaces

  • DRIVER_RENDER

支持专门的渲染节点, 即**/dev/dri/renderD**

  • DRIVER_ATOMIC

支持所有的Atomic Modesetting用户空间API

  • DRIVER_SYNCOBJ

支持drm_syncobj, 用于渲染命令提交的显式同步。

  • DRIVER_SYNCOBJ_TIMELINE

支持drm_syncobjtimeline特性

旧DRM驱动的特性

  • DRIVER_USE_AGP
  • DRIVER_LEGACY
  • DRIVER_PCI_DMA
  • DRIVER_SG
  • DRIVER_HAVE_DMA
  • DRIVER_HAVE_IRQ
  • DRIVER_KMS_LEGACY_CONTEXT

内核 DRM 子系统是如何维护的

内核 DRM 子系统的代码仓库托管在cgit上,Upstream DRM Subsystem Repository, 这个仓库最主要的两个分支

  • drm-next

    这个分支的补丁包括 DRM 核心和所有 GPU 驱动的新特性

  • drm-fixes

参考

[0] DRM Maintainer Tools

Mesa Gallium 驱动框架

Gallium Framework

-Dgallium-drivers-Ddri-drivers 的区别,以及它们与 -Degl 的关系

从构建的角度看, -Dgallium-drivers-Ddri-drivers 是无关的。

1
2
3
DRI platform:    drm
DRI drivers: no
DRI driver dir: /usr/lib/x86_64-linux-gnu/dri
1
2
3
EGL:             yes
EGL drivers: builtin:egl_dri2 builtin:egl_dri3
EGL/Vulkan/VL platforms: x11 surfaceless drm xcb
1
2
3
Gallium drivers: swrast panfrost
Gallium st: mesa
HUD lmsensors: no
1
2
3
build/src/gallium/targets/dri/libgallium_dri.so
build/src/gallium/targets/dri/8381c20@@gallium_dri@sha/target.c.o
build/src/gallium/targets/dri/8381c20@@gallium_dri@sha/megadriver_stub.c.o
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@startuml
class pipe_loader_device

class pipe_loader_sw_device {
sw_driver_descriptor * dd
.. !GALLIUM_STATIC_TARGETS ..
util_dl_library * lib
..
sw_winsys * ws
int fd
}

class pipe_loader_drm_device {
drm_driver_descriptor * dd
.. !GALLIUM_STATIC_TARGETS ..
util_dl_library * lib
..
int fd
}

pipe_loader_device <|-- pipe_loader_drm_device
pipe_loader_device <|-- pipe_loader_sw_device
@enduml

resource_copy_region

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Copy a block of pixels from one resource to another.
* The resource must be of the same format.
* Resources with nr_samples > 1 are not allowed.
*/
void (*resource_copy_region)(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src,
unsigned src_level,
const struct pipe_box *src_box);

resource_copy_region 只能在 buffer 与 buffer 之间或 texture 与 texture 之间 memcpy, 而且源与目标的 format 必须相同。之所以不能做 buffers 与 textures 之间的 memcpy, 至少是因为缺少 stride 参数。一些硬件(如 nvidia) 可以通过专门的 copy engine 完成这些拷贝,但对于其它硬件可能需要一个 compute shader 去做这些拷贝。另一方面,那些专门的 copy engine 通常是比较慢的,所以只在那些带宽非常有限的 PCIe 传输场景下才有用。如果想利用全部的
VRAM 带宽(甚至 infinity cache bandwidth), 你很可能必须使用 compute shaders.

OpenGL Program Object

Shader Object

创建和使用Shader Object的API:

  • GLuint glCreateShader(GLenum shaderType);
  • void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
  • void glCompileShader(GLunit shader);

Vulkan

Vulkan 是一个低开销、跨平台的二维和三维图形与计算的应用程序接口,由 Khronos 在2015年在 GDC 上首次发布。它旨在提供高效能和更均衡的 CPU 和 GPU 占用,类似于 Direct3D 12 和 AMD Mantle。

在这里主要收集一些与 Vulkan 强相关的一些项目,便于 Vulkan 的学习和使用。

Wayland

Wayland Architecture

为了理解wayland的架构和它与X的区别,最好是看看从一个输入事件到这个输入事件的结果呈现到屏幕上这个过程都发生了什么。

Mesa 的 GLX 实现

GLX

GLX (Initialism for “OpenGL Extension to the X Window System”) is an extension to the X Window System core protocol providing an interface between OpenGL and the X Window System as well as extensions to OpenGL itself. (From WiKi)

Mesa的 GLX 实现自从 Delete Mesa Classic 已经从原来的 3 种变成现在的 2 种:

  • dri
  • xlib
flowchart TD
    A[xlib or gallium-xlib]
    A --> x11
    A --> xext
    A --> xcb
    B[dri]
    B --> x11
    B --> xext
    B --> xfixes
    B --> xcb-glx
    B --> xcb-shm

如果是xlib, 它的源码位于

  • mesa/drivers/x11

如果是gallium-xlib, 它的源码位于

  • gallium/winsys/sw/xlib
  • gallium/frontends/glx/xlib
  • gallium/targets/libgl-xlib

xlib

dri

在 Linux 下 dri-based glx 实现我们只关注 3 个实现:

源文件 关键函数
dri2_glx.c dri2CreateScreen()
dri3_glx.c dri3_create_screen()
drisw_glx.c driswCreateScreenDriver()

dri2CreateScreen

dri2CreateScreen

driswCreateScreenDriver

driswCreateScreenDriver

dri3_create_screen

dri3_create_screen

Git Cheat Sheet

git am

  • git am foo.patch
    • 应用补丁 foo.patch (注意与 git apply 的区别,git am 同时会将commit log 也应用上去)

lspci 学习笔记

与 PCI 设备相关的一些 IDs

  • Device ID: 4 位十六进制数字
  • Vendor ID: 4 位十六进制数字
  • Domain ID: 4 位十六进制数字
1
2
3
4
5
3772:00:00.0 0100: 1af4:1049 (rev 01)
5401:00:00.0 0880: 1af4:105a (rev 01)
b30b:00:00.0 0302: 1414:008e
c4c5:00:00.0 0100: 1af4:1049 (rev 01)
cdbf:00:00.0 0100: 1af4:1049 (rev 01)

lspci -Dn 的输出格式是:

1
<domain>:<bus>:<slot>.<func>

这里的 slot 其实就是 device, 而且只包含 2 位十六进制数字。我们可以从 lspci源码看到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void
show_slot_path(struct device *d)
{
struct pci_dev *p = d->dev;

if (opt_path)
{
struct bus *bus = d->parent_bus;
struct bridge *br = bus->parent_bridge;

if (br && br->br_dev)
{
show_slot_path(br->br_dev);
if (opt_path > 1)
printf("/%02x:%02x.%d", p->bus, p->dev, p->func);
else
printf("/%02x.%d", p->dev, p->func);
return;
}
}
printf("%02x:%02x.%d", p->bus, p->dev, p->func);
}

lspci 之所以只使用 2 位十六进制数字分别表示 bus, slot(dev), 是因为它们被定义成 8 位位宽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
u16 domain_16; /* 16-bit version of the PCI domain for backward compatibility */
/* 0xffff if the real domain doesn't fit in 16 bits */
u8 bus, dev, func; /* Bus inside domain, device and function */

/* These fields are set by pci_fill_info() */
unsigned int known_fields; /* Set of info fields already known (see pci_fill_info()) */
u16 vendor_id, device_id; /* Identity of the device */
u16 device_class; /* PCI device class */
int irq; /* IRQ number */
pciaddr_t base_addr[6]; /* Base addresses including flags in lower bits */
pciaddr_t size[6]; /* Region sizes */
pciaddr_t rom_base_addr; /* Expansion ROM base address */
pciaddr_t rom_size; /* Expansion ROM size */
struct pci_cap *first_cap; /* List of capabilities */
char *phy_slot; /* Physical slot */
char *module_alias; /* Linux kernel module alias */
char *label; /* Device name as exported by BIOS */
int numa_node; /* NUMA node */
pciaddr_t flags[6]; /* PCI_IORESOURCE_* flags for regions */
pciaddr_t rom_flags; /* PCI_IORESOURCE_* flags for expansion ROM */
int domain; /* PCI domain (host bridge) */
pciaddr_t bridge_base_addr[4]; /* Bridge base addresses (without flags) */
pciaddr_t bridge_size[4]; /* Bridge sizes */
pciaddr_t bridge_flags[4]; /* PCI_IORESOURCE_* flags for bridge addresses */
u8 prog_if, rev_id; /* Programming interface for device_class and revision id */
u16 subsys_vendor_id, subsys_id; /* Subsystem vendor id and subsystem id */
struct pci_dev *parent; /* Parent device, does not have to be always accessible */
int no_config_access; /* No access to config space for this device */

/* Fields used internally */
struct pci_access *access;
struct pci_methods *methods;
u8 *cache; /* Cached config registers */
int cache_len;
int hdrtype; /* Cached low 7 bits of header type, -1 if unknown */
void *aux; /* Auxiliary data for use by the back-end */
struct pci_property *properties; /* A linked list of extra properties */
struct pci_cap *last_cap; /* Last capability in the list */
};

Xorg config 之 Device Section

1
2
3
4
5
Section "Device"
Identifier "name"
Driver "driver"
BusID "bus-id"
EndSection

Device Section 中 BusID 的格式是

1
PCI:bus:device:func

Xorg log 中的 PCI 信息格式

1
2
3
4
xf86Msg(X_PROBED, "PCI:%s(%u@%u:%u:%u) %04x:%04x:%04x:%04x ", prim,
info->bus, info->domain, info->dev, info->func,
info->vendor_id, info->device_id,
info->subvendor_id, info->subdevice_id);

日志中的 PCI BusID 格式是

1
bus@domain:device:func

Blog using Hexo

npm

hexo 依赖的很多 nodejs 包都过期了,但发现在Ubuntu 23.04 上很难更新(编译node-sass 要用的 python2 都需要自己源码编译安装),索性先搁置吧。

Altering Your GCC/Python Version Easily

What’s the problem

有时在你的系统上可能已经安装了多个gcc版本(gcc-4.8, gcc-8, gcc-9)或Python版本(Python, Python 2.7, Python 3.8), 那么当你执行gcc或python命令时,到底用的是哪个gcc或python版本呢?而且如何方便地指定我们期望使用的版本呢?在大多数Linux发行版都有一个update-alternatives命令专门处理这种情况。

EGLImage

Overview

EGLImage的存在是为了更方便地在EGL client API之间共享2D Image Data. 那什么是EGL client API呢?OpenGL, OpenGL ES, OpenVG都是EGL client API. EGLImage与下面3个EGL Extensions有关:

  • EGL_KHR_image
  • EGL_KHR_image_base
  • EGL_KHR_image_pixmap

DRM format modifier

FourCC

FourCC format code是Linux内核DRM子系统用来描述framebuffer像素格式。它们被定义在内核源码include/uapi/drm/drm_fourcc.h. 基本上FourCC format code足以描述framebuffer中像素的内容了,但是随着GPU的更新,原来线性排列的buffers,为了获取更好的性能,可能会采取vendor specific的布局方式。另外,这些buffer也可能保存的是各种不同的压缩数据,这样一来,原来的FourCC format code就无法携带新的buffer
layout或compression format的信息,DRM format modifier就是用来解决这些问题的。

glamor

Introduction

glamor是一个开源的2D加速驱动,它作为Xorg的一个模块被实现。相比传统的DDX 2D加速驱动,glamor主要有以下2个好处:

  • 使用非常通用的EGL/OpenGL API去操作GPU硬件,省去了手动为每个不同的GPU编写2D加速驱动的麻烦
  • 有了glamor,不再需要传统的2D DDX驱动

Build X Server (Xorg) from Source

Motivation

Given that a difficulty to add a custom X11 device driver or module or extension for Xserver, I try to find out how an Xserver is built and its dependent drivers and modules and extensions are orgnized together by building it from source.

Pixmap in X

XYPixmap

The data for a XYPixmap is organized as a set of bitmaps representing individual bit planes, with the planes appearing from MSB to LSB in bit order just as demonstrated below. Every pixel value is 0x55 (b’01010101) in this example.

ARB_sparse_texture

Overview(#158)

复杂的OpenGL应用和对高分辨率的追求使纹理的大小巨增,但是可供一个GPU使用的物理内存是有限的,一旦内存使用殆尽,内存换页就可能发生,性能严重下降,或者更糟,应用直接挂了。但另一方面GPU可访问的地址空间目前已经可以达到GB,甚至TB.

Smart Pointer

smart pointer是C++11引入的,被包含在C++标准库中。smart pointer是为了管理对象的所属(object ownership)而设计的,smart pointer对象负责自动地销毁所关联对象。常见的smart pointer有:

ARB_texture_storage

Overview(#117)

ARB_texture_storage的主要目的是简化纹理一致性(consistency)和完整性(completeness)检查,以减小实现的开销。

ARB_texture_swizzle

概述(#84)

传统的OpenGL纹理格式(texture format)的纹理数据存储和解释是统一的,纹理就是被解释成颜色。而在现代OpenGL应用中,大多数纹理并不是代表颜色,而是代表像shadow maps, normal maps, page tables, occlusion data等等这样的数据。对于后者,我们将纹理数据称作”RGBA”,只是对数据在现有模型上的一种方便的映射,但并不是数据实际上的准确解释。

ARB_shader_ballot

概述(#183)

ARB_shader_ballot给一组线程(a group of invocations)提供某些形式的线程间(cross-invocation)通信的能力。它要么是通过广播某个线程作用域里的值,要么是通过一个位数组(bitarray)表示一组线程中每个线程作用域里的可能的值。

ARB_texture_view

概述(#124)

ARB_texture_view的主要目的是通过创建已有纹理对象的视图(view), 来产生新的纹理对象,以达到共享同一纹理存储(data store)的目的。它可以从以下3个方面创建纹理视图:

ARB_point_parameters

概述(#14)

ARB_point_parameters允许用户设置点的扩展几何特征。这些点的几何特征主要用来渲染粒子或微小光源,通常被称为光点(Light Points).

vim 速查手册

Visual Block Selection

  • 选择 {}(curly braces) 之间的行(包括 {})

    • v%
  • 选择 {}(curly braces) 之间的行(不包括 {})

    • vi{

注意:光标必须放在 { 或者 }

Copy & Paste

Copy to clipboard

  • Normal 模式
    • "+y

Paste from clipboard

X11 window system 有 3 个 selections:

  • PRIMARY 表示当前的可见 selection
  • SECONDARY
  • CLIPBOARD 通常所说的剪贴板,用来完成剪贴,复制和粘贴操作

Vim 有两个专门的寄存器分别与 PRIMARY selection 和 CLIPBOARD selection 对应

  • "* (quotestar) PRIMARY
  • "+ (quoteplus) CLIPBOARD

如果要在 Vim 内部剪贴,复制/粘贴就使用 quotestar, 如果要将内容剪贴,复制/粘贴到系统剪贴板,就使用 quoteplus

举个例子,在 WSL Ubuntu 里如果想粘贴 Windows 剪贴板里的内容到 vim (最好是 neovim, 因为 vim 可能未使能 clipboard)

1
echo "Hello, world!" | clip.exe
  • Normal 模式
    • "+p

如果想粘贴 Ubuntu 剪贴板里的内容

1
echo "Hello, world!" | xclip
  • Normal 模式
    • "*p

Copy from above or below

在 Insert 模式下

  • <ctrl-y> copies the character from the line above
  • <ctrl-e> copies the character from the line below (本行就是这样输入的)

Search & Replace

删除多行 C-style 注释

  • s;/\*\_.\{-}\*/;;

    • ; 因为要匹配 /, 为了省去转义 / 的麻烦,将 search 命令的分隔符由 / 改为 ;

    • /\* 匹配开始的 /*

    • \_. 匹配任意字符,包括 \n, 所以常用在多行匹配

    • \{-} 指非贪婪 (non-greedy) 匹配,即匹配最短的字串,默认是贪婪匹配,匹配最长的字串

    • \*/ 匹配结尾的 */

    • ;; 指使用空替换匹配结果,即删除

    • 以下是 vim 中在单行中使用的通配符 (wildcard), 这些通配符一般不能匹配换行 \n

      • . 匹配除了 \n 的任意字符
      • ^ 行首,即锚点 (anchor)
      • $ 行尾,即锚点
      • \s 匹配 space, tab, 但不匹配 \n
    • 以上通配符加上 \_ 后可以在多行匹配中使用,即也可以匹配 \n

      • \_. 匹配任意字符,包括 \n
      • \_^ 多行中第一行行首
      • \_$ 多行中最后一行行尾
      • \_s 匹配 space, tab 和 \n

删除空白行

  • g/^\s*$/d

    • g 指所有行搜索,而不是默认的光标所在行
    • ^\s*$ 匹配行首到行尾之间任意个空白字符,即空白行
    • d 删除命令 (delete)

搜索不匹配某模式的行,即反向搜索

  • /^\(\(^# .*$\)\@!.\)*$

    • / 查找命令 (search) 的提示符
    • ^\(\(The_Regex\)\@!.\)*$ 反向查找的命令固定模式,本例中 The_Regex^# .*$ 即以 # 开头的行,所以整个表达式匹配的就是不以 # 开头的所有行
  • :v/^# .*$/p

    • 与上面的反向查找命令功能相同, 但会将匹配结果显示在 Visual 模式下

大小写转换

  • s/\(^# .*$\)/\L\1/

    • \(The_Regex\) 为了向前索引,即后面 \1 所指的部分,本例中 The_Regex^# .*$, 意思同上
    • \L\1 \LLowercase, 即将 \1 匹配的结果中的所有字母都换成小写
  • s/\(^# .*$\)/\U\1/

    • 与上面的表达式功能相反,即将 \1 匹配的结果中的所有字母都换成大写 (Uppercase)

GCC __attribute__

__attribute__ is a keyword introduced by GCC. It is regarded as an extension of a language. It helps the compiler optimize calls, check code more carefully for correctness, control memory placement and code generation options.

Debugging X11 with tcpdump

X11 is designed as client-server mode. The communication between the X client and server complies with TCP protocol. Recently I have a Windows X server VcXsrv installed on my Windows 10 and I debug an OpenGL demo glxgears on the WSL2 with tcpdump.

Environment

WSL2 is equipped with its own networking interface like a virtual machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.28.233.193 netmask 255.255.240.0 broadcast 172.28.239.255
inet6 fe80::215:5dff:fe27:9562 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:27:95:62 txqueuelen 1000 (Ethernet)
RX packets 221579 bytes 15160108 (15.1 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 306691 bytes 15714800233 (15.7 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 392 bytes 43340 (43.3 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 392 bytes 43340 (43.3 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -C "ipconfig"

Windows IP Configuration


Ethernet adapter vEthernet (WSL):

Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::412b:ad3:5548:67ba%38
IPv4 Address. . . . . . . . . . . : 172.28.224.1
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :

Wireless LAN adapter ±¾µØÁ¬½Ó* 1:

Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :

Wireless LAN adapter ±¾µØÁ¬½Ó* 10:

Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :

Wireless LAN adapter WLAN:

Connection-specific DNS Suffix . : DHCP HOST
Link-local IPv6 Address . . . . . : fe80::954b:e66f:4065:20af%20
IPv4 Address. . . . . . . . . . . : 192.168.2.100
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.2.1

After starting up the X server VcXsrv, you need to export the environmnet variable DISPLAY on the WSL. In case of the vEthernet configuration changed after rebooting you’d better do it like this:

1
export DISPLAY=$(grep 'nameserver' /etc/resolv.conf | awk '{print $2}'):0

NOTE: The Firewall between the host and WSL2 must be disabled or your X client can not connect VcXsrv.

Debugging

I trace the demo glxgears using gdb and tcpdump at the same time.

  • gdb
1
gdb -q -tui glxgears
  • tcpdump
1
sudo tcpdump -vvX not icmp and not arp and not udp and portrange 37900-37999 -w x110224.pcap
  • vv: verboser than -v
  • X: show the packet’s content
  • not icmp: filter out icmp packets
  • not arp: filter out arp packets
  • not udp: filter out udp packets
  • portrange 37900-37999: listening on the ports from 37900 to 37999
  • w x110224.pcap: save the packet captures into the file
1
tcpdump -X -r x110224.pcap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
reading from file /home/luc/github/x110224.pcap, link-type EN10MB (Ethernet)
09:11:56.659816 IP 172.28.233.193.37950 > 172.28.224.1.x11: Flags [P.], seq 2796598646:2796598658, ack 1053772981, win 259, length 12
0x0000: 4500 0034 1d84 4000 4006 fb43 ac1c e9c1 E..4..@.@..C....
0x0010: ac1c e001 943e 1770 a6b0 b576 3ecf 4cb5 .....>.p...v>.L.
0x0020: 5018 0103 2223 0000 6200 0300 0400 0000 P..."#..b.......
0x0030: 4452 4932 DRI2
09:11:56.660218 IP 172.28.224.1.x11 > 172.28.233.193.37950: Flags [P.], seq 1:33, ack 12, win 8211, length 32
0x0000: 4500 0048 d9d7 4000 8006 fedb ac1c e001 E..H..@.........
0x0010: ac1c e9c1 1770 943e 3ecf 4cb5 a6b0 b582 .....p.>>.L.....
0x0020: 5018 2013 cf36 0000 0100 0a00 0000 0000 P....6..........
0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0040: 0000 0000 0000 0000 ........
09:11:56.660232 IP 172.28.233.193.37950 > 172.28.224.1.x11: Flags [.], ack 33, win 259, length 0
0x0000: 4500 0028 1d85 4000 4006 fb4e ac1c e9c1 E..(..@.@..N....
0x0010: ac1c e001 943e 1770 a6b0 b582 3ecf 4cd5 .....>.p....>.L.
0x0020: 5010 0103 2217 0000 P..."...

what codes sends and receives these packets? The first two twenty-byted segments are IP header (20 bytes without option) and TCP header (20 bytes without option) separately in these packets.

The source code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Bool
XQueryExtension(
register Display *dpy,
_Xconst char *name,
int *major_opcode, /* RETURN */
int *first_event, /* RETURN */
int *first_error) /* RETURN */
{
xQueryExtensionReply rep;
register xQueryExtensionReq *req;

LockDisplay(dpy);
GetReq(QueryExtension, req);
req->nbytes = name ? strlen(name) : 0;
req->length += (req->nbytes+(unsigned)3)>>2;
_XSend(dpy, name, (long)req->nbytes);
(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
*major_opcode = rep.major_opcode;
*first_event = rep.first_event;
*first_error = rep.first_error;
UnlockDisplay(dpy);
SyncHandle();
return (rep.present);
}

The gdb log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Starting program: /mnt/c/Users/lulu/Documents/github/demos/src/xdemos/glxgears 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, XextAddDisplay (extinfo=0x7ffff7e77380 <_dri2Info_data>, dpy=0x55555555d2a0,
ext_name=0x7ffff7e76780 <dri2ExtensionName> "DRI2", hooks=0x7ffff7e767a0 <dri2ExtensionHooks>, nevents=0, data=0x0)
at extutil.c:103
XInitExtension (dpy=dpy@entry=0x55555555d2a0, name=name@entry=0x7ffff7e76780 <dri2ExtensionName> "DRI2")
at InitExt.c:44
XQueryExtension (dpy=dpy@entry=0x55555555d2a0, name=name@entry=0x7ffff7e76780 <dri2ExtensionName> "DRI2",
major_opcode=major_opcode@entry=0x7fffffffd984, first_event=first_event@entry=0x7fffffffd988,
first_error=first_error@entry=0x7fffffffd98c) at QuExt.c:39
$2 = {
reqType = 0x62,
pad = 0x0,
length = 0x3,
nbytes = 0x4,
pad1 = 0x0,
pad2 = 0x0
}
$3 = {
type = 0x1,
pad1 = 0x0,
sequenceNumber = 0xa,
length = 0x0,
present = 0x0,
major_opcode = 0x0,
first_event = 0x0,
first_error = 0x0,
pad3 = 0x0,
pad4 = 0x0,
pad5 = 0x0,
pad6 = 0x0,
pad7 = 0x0
}

$2 is Request packet content to VcXsrv, $3 is Reply packet content from VcXsrv. Even that we can notice the three-way handshake of TCP from the zero-lengthed packet in x110224.pcap.

Notes for Mesa

Build

1
meson build -Dprefix=/usr -Dplatforms=x11 -Dgallium-drivers=swrast,panfrost,radeonsi -Dvulkan-drivers=swrast -Dglx=dri -Dllvm=enabled -Dcpp_rtti=false -Dxmlconfig=enabled -Dglvnd=true
1
ninja -C build && sudo ninja -C build install