首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

KVM/QEMU 部署与设备绑定

KVM/QEMU 部署与设备绑定

1. 前置检查

1
2
3
4
zcat /proc/config.gz | grep -E 'VFIO|IOMMU|KVM'
test -e /dev/kvm
find /sys/kernel/iommu_groups -type l
dmesg | grep -Ei 'iommu|vfio'

先证明硬件 IOMMU和 group存在,再配置 VFIO。

2. 推荐配置

1
2
3
4
CONFIG_VFIO=y/m
CONFIG_VFIO_PCI=y/m
CONFIG_VFIO_IOMMU_TYPE1=y/m
CONFIG_KVM=y

不要启用 VFIO_NOIOMMU作为生产替代。

3. PCI绑定

1
2
3
4
5
6
DEV=0000:01:00.0
readlink -f /sys/bus/pci/devices/$DEV/iommu_group
basename "$(readlink -f /sys/bus/pci/devices/$DEV/driver)"
echo vfio-pci > /sys/bus/pci/devices/$DEV/driver_override
echo $DEV > /sys/bus/pci/devices/$DEV/driver/unbind
echo $DEV > /sys/bus/pci/drivers_probe

命令必须按实际 driver状态调整;切换网络/存储设备可能立即中断系统。

4. Group完整性

列出:

1
2
GROUP=$(basename "$(readlink -f /sys/bus/pci/devices/$DEV/iommu_group)")
find /sys/kernel/iommu_groups/$GROUP/devices -maxdepth 1 -type l

组内每个 function和 bridge关系都需评估,不能只绑定目标 function。

5. 权限

QEMU进程需:

  • group node访问;
    -足够 memlock;
    -KVM访问;
    -必要 hugepages;
    -设备 firmware/ROM;
    -受控 cgroup/device ACL。

不建议 chmod 666 /dev/vfio/*

6. QEMU

典型参数概念:

1
-device vfio-pci,host=0000:01:00.0

ARM virt machine还需正确 GIC/ITS、guest firmware和 MMIO window。具体参数取决于 QEMU版本。

7. 启动前

-停止 host业务;
-确认 reset能力;
-备份 console;
-确认 rootfs/network不依赖目标;
-验证组隔离;
-验证 guest driver;
-准备失败回绑。

8. 关闭

Guest shutdown后确认 DMA停止、fd关闭和 reset成功,再清 driver_override并 probe原 driver。无法 reset的设备可能需整机重启。

9. RK3588限制

在当前 DTS无 PCIe IOMMU映射的前提下,上述流程预期会在 group/Type1 attach阶段不满足安全条件;不要以 unsafe no-IOMMU强行完成。

VFIO 调试、性能、故障与安全加固

VFIO 调试、性能、故障与安全加固

1. 基线

1
2
3
4
5
lspci -nnk
find /sys/kernel/iommu_groups -type l
ls -l /dev/vfio
cat /proc/iomem
dmesg | grep -Ei 'vfio|iommu|fault|reset'

2. Group not viable

检查同组:

  • multifunction siblings;
  • upstream bridge;
    -音频 function;
    -原 host driver;
    -driver_override;
    -未绑定 device。

不要用 ACS override补丁假装硬件隔离,除非接受其安全风险。

3. MAP_DMA失败

常见:

  • memlock不足;
  • IOVA overlap;
  • page alignment;
    -超出 aperture;
    -reserved region;
    -pin user page失败;
    -domain未 attach;
    -权限 flags错误。

4. IOMMU fault

记录 requester、IOVA、direction和时间。对照 QEMU memory listener mappings和 guest DMA。Fault后设备可能持续发 DMA,先隔离/停止再调试。

5. Reset失败

表现:

-第二次启动 VM失败;
-guest driver timeout;
-MSI残留;
-BAR状态异常;
-host reboot才能恢复。

检查 FLR/PM/bus reset和同 bus影响。

6. 性能

影响因素:

  • IOMMU page size;
  • IOTLB miss;
  • vCPU/IRQ affinity;
  • hugepages;
  • eventfd/irq bypass;
  • NUMA;
  • DMA map批量;
    -dirty logging;
    -host power management。

RK3588通常 UMA,但 CPU cluster和 IRQ affinity仍影响延迟。

7. 安全加固

-关闭 no-IOMMU;
-最小 /dev/vfio/N ACL;
-仅绑定必要设备;
-模块签名;
-限制 memlock;
-禁用无用 vendor/mdev driver;
-QEMU sandbox/SELinux;
-验证 firmware和 option ROM;
-监控 IOMMU fault;
-定期测试 reset和 teardown。

8. Debug开关

可使用 dynamic debug:

1
echo 'file drivers/vfio/* +p' > /sys/kernel/debug/dynamic_debug/control

通配支持依 shell和 dynamic debug parser;也可逐文件开启。生产环境避免长期高日志。

9. 威胁模型

IOMMU主要限制 DMA,不会自动防止:

-设备 firmware漏洞;
-PCIe peer-to-peer;
-共享 reset/sideband;
-CPU MMIO误用;
-中断 DoS;
-host VFIO/kernel漏洞;
-恶意 migration stream。

设备直通扩大攻击面,应只给可信 VM/进程。

Linux 6.1 VFIO 文档索引

Linux 6.1 VFIO 文档索引

源码:rk3588/kernel-6.1/drivers/vfio/

文档 内容
VFIO子系统架构与源码总览.md group/container/device总体设计
源码目录与模块索引.md 文件、Kconfig和架构适用性
01-VFIO-Core设备组与Container模型.md 注册、隔离和fd对象
02-UAPI打开绑定与IOCTL调用链.md legacy VFIO UAPI
03-Type1-IOMMU与DMA映射.md map/unmap、IOVA、domain
04-内存钉扎Dirty-Logging与迁移.md pinning、dirty bitmap、migration
05-Eventfd中断与Virqfd机制.md INTx/MSI、eventfd、irqfd
06-VFIO-PCI配置空间BAR与Reset.md vfio-pci设备模型
07-VFIO-Platform与AMBA设备.md platform region/IRQ/reset
08-Mdev与厂商迁移驱动.md mediated device、mlx5、HiSilicon
09-No-IOMMU模式与安全边界.md 不安全模式和权限
10-RK3588-IOMMU与PCIe透传可行性.md 本树实际能力核对
11-KVM-QEMU部署与设备绑定.md 检查和部署流程
12-调试性能故障与安全加固.md group、fault、reset、性能

关键结论:RK3588主 defconfig未启用 VFIO/KVM;MMU-600 SMMUv3节点默认 disabled,PCIe root complex未见 iommu-map。不能据 ROCKCHIP_IOMMU=y推断 PCIe endpoint具备安全 DMA隔离。

VFIO 子系统架构与源码总览

VFIO 子系统架构与源码总览

1. 目标

VFIO在 IOMMU隔离下把设备安全交给可信用户进程或虚拟机:

1
2
3
4
5
6
7
8
9
userspace/QEMU
| group fd / device fd / container fd
VFIO Core
| bus driver ops
vfio-pci / vfio-platform / mdev
| DMA map
Type1 IOMMU backend
|
IOMMU domain -> hardware

2. 三个对象

  • group:最小安全隔离单位;
  • device:region、IRQ、reset、migration等;
  • container:一个或多个 group共享的 IOMMU地址空间。

Legacy ABI节点:

1
2
/dev/vfio/vfio
/dev/vfio/<group-id>

Device fd由 VFIO_GROUP_GET_DEVICE_FD返回匿名 inode。

3. 为什么是Group

若同组设备可绕过 IOMMU隔离互相 DMA,单独交出一个设备仍不安全。本树还通过 IOMMU group DMA ownership控制 container接管;组内相关设备必须脱离会发起 DMA的 host driver或由 VFIO统一管理。

4. Type1 backend

vfio_iommu_type1.c

  • attach/detach group;
    -创建/复用 iommu domain;
  • user VA pin pages;
  • IOVA映射;
  • unmap/dirty bitmap;
  • notifier;
  • DMA ownership。

5. Device driver

VFIO bus driver实现 vfio_device_ops,Core转发:

  • open/close;
  • ioctl;
  • read/write;
  • mmap;
  • request;
  • match;
  • migration/dirty feature。

6. PCI

vfio-pci导出 config space、BAR、ROM、IRQ、reset和 power state,并拦截敏感配置寄存器,不能把 config space当普通 memory直接完全透传。

7. Platform

VFIO platform导出 platform resources和 IRQ,需要可用 reset方法确保交接前后设备状态可控。

8. 安全前提

-可用 IOMMU domain;
-完整 group;
-可信 reset;
-禁止 host driver并发;
-正确 pin/account;
-中断隔离;
-无 hidden DMA path;
-用户进程拥有高权限且可信。

9. RK3588

Rockchip IOMMU主要连接 VPU/ISP/VOP/NPU等集成 IP。PCIe DTS无 iommu-map,因此不能默认安全透传 PCIe endpoint;需硬件和 DT/driver完整支持。

drivers/vfio 源码目录与模块索引

drivers/vfio 源码目录与模块索引

Core

文件 作用
vfio_main.c group/device注册、fd、ioctl、feature
container.c /dev/vfio/vfio和 IOMMU backend
vfio_iommu_type1.c 通用 Type1 DMA映射
iova_bitmap.c IOVA范围位图
virqfd.c eventfd/irqfd触发与关闭
vfio.h 内部 group/container定义

总线

  • pci/:通用 vfio-pci、config、region、IRQ、reset;
  • platform/:platform/AMBA;
  • mdev/:mediated device bus;
  • fsl-mc/:NXP Management Complex;
  • SPAPR TCE/EEH:POWER专用。

PCI扩展

  • pci/mlx5/:mlx5 migration/dirty tracking;
  • pci/hisilicon/:HiSilicon accelerator migration;
  • IGD和 zdev:x86/s390专用。

Kconfig

1
2
3
4
5
6
7
8
9
10
VFIO
-> IOMMU_API
-> VFIO_IOMMU_TYPE1 on ARM64+MMU

VFIO_PCI
-> VFIO_PCI_CORE
-> VFIO_VIRQFD

VFIO_PLATFORM
-> VFIO_VIRQFD

RK3588配置事实

主 defconfig有:

1
2
3
4
PCI=y
PCIE_ROCKCHIP_HOST=y
PCIE_DW_ROCKCHIP=y
ROCKCHIP_IOMMU=y

未找到 VFIO、VFIO_PCI、VFIO_PLATFORM或 KVM显式配置。最终产品 .config仍可能由 fragment改变,应以 /proc/config.gz核对。

架构不适用

  • SPAPR/EEH:POWER;
  • fsl-mc:NXP;
  • IGD:x86 Intel;
  • zdev:s390;
  • mlx5/HiSilicon vendor migration:只有对应 PCI硬件和配置才有意义。

UAPI

主头文件:include/uapi/linux/vfio.h。内核文档:

  • Documentation/driver-api/vfio.rst
  • Documentation/driver-api/vfio-mediated-device.rst
  • Documentation/virt/kvm/devices/vfio.rst

FBDev Core 注册与生命周期

FBDev Core 注册与生命周期

1. 对象

struct fb_info包含:

  • device和node编号;
  • fb_ops
  • fb_var_screeninfo可变模式;
  • fb_fix_screeninfo固定信息;
  • screen base/size;
  • pseudo palette/cmap;
  • pixmap;
  • modelist;
  • flags/state;
  • lock、refcount、deferred I/O;
  • driver private par

2. fb_ops

驱动常实现:

  • open/release;
  • read/write;
  • check_var/set_par;
  • setcolreg/setcmap;
  • blank/pan_display;
  • fillrect/copyarea/imageblit;
  • cursor;
  • sync;
  • ioctl/compat_ioctl;
  • mmap;
  • destroy。

Core提供缺省read/write和software drawing helper。

3. 分配

1
2
3
4
framebuffer_alloc(private_size, dev)
-> allocate fb_info + aligned driver private
-> set parent device and fbcon rotation hint
-> initialize optional backlight-curve lock

注册阶段才初始化主要refcount、lockmm_lock、modelist和默认pixmap。硬件停机仍需正确remove顺序。

4. 注册

1
2
3
4
5
6
7
8
register_framebuffer(info)
-> firmware fb acquires aperture range when applicable
-> hold registration_lock
-> allocate fb node
-> create /sys/class/graphics/fbN for fixed FB_MAJOR
-> initialize modelist/pixmap
-> publish registered_fb[N]
-> call fbcon_fb_registered()

Node数量受FB_MAX限制。

本版本普通注册并不通过通用fb notifier广播FB_EVENT_FB_REGISTERED;源码中的该事件调用仅受特定Gumstix配置保护。不要把它当成所有驱动都能观察到的注册通知。

5. Open

fb_open()按minor从registered_fb[]取对象,增加引用并调用driver fb_open。若设备正在unregister,必须拒绝新open。

6. Mode设置

Core先调用fb_check_var()规范化请求,再在必要时调用fb_set_par()编程硬件;随后更新cmap、pan和notifier。

check_var不能产生超出pixel clock、stride、VRAM或接口能力的模式。

7. Drawing

fbcon和Core通过:

  • fb_fillrect
  • fb_copyarea
  • fb_imageblit
  • fb_cursor

驱动可硬件加速,也可使用CFB/SYS helper。Helper选择取决于framebuffer位于I/O memory还是system memory。

8. Notifier

Clients可监听注册、注销、mode、blank、suspend、resume等事件。Notifier callback不能反向制造锁顺序死锁。

9. Unregister

1
2
3
4
5
6
7
8
9
10
unregister_framebuffer
-> hold registration_lock
-> destroy class device
-> unregister PM VT switch
-> unbind fbcon
-> release default pixmap/modelist
-> remove registered_fb entry
-> cleanup sysfs
-> call fbcon_fb_unregistered()
-> put initial fb_info reference

Core注释明确:如果不在module_exit()中注销,driver应实现fb_open/fb_release自行确保没有进程仍使用设备。仍被open/mmap的显存不能提前free。

10. Suspend

Driver持有console semaphore时调用fb_set_suspend(info, 1/0)通知Core/fbcon,配合blank、clock、power-domain和显存保存。

11. 并发

Core使用console lock、registration lock、info lock和refcount协调VT、userspace、notifier及remove。Driver私有寄存器/queue仍需自身锁。

12. DRM兼容层

DRM fbdev emulation也构造fb_info并注册framebuffer,因此/dev/fb0存在不代表系统正在运行legacy fbdev硬件driver。

FBDev 用户接口、IOCTL、MMap 与 Sysfs

FBDev 用户接口、IOCTL、MMap 与 Sysfs

1. /dev/fbN

字符设备由fbmem Core统一提供,minor对应registered_fb[N]。File operations转发到具体fb_ops

2. Read/Write

默认fb_sys_read/writefb_read/write按file offset访问framebuffer:

  • 检查screen size和offset;
  • 在I/O memory与system memory间选择copy方法;
  • 处理partial copy和signal;
  • 更新offset。

高性能绘制通常使用mmap,不使用write逐帧复制。

3. MMap

默认或driver fb_mmap把framebuffer/aperture映射给用户。

必须检查:

  • offset和length;
  • smem_len;
  • page alignment;
  • overflow;
  • MMIO register区域是否允许;
  • cache/write-combine属性;
  • device移除与VMA生命周期。

把控制寄存器和显存一起映射给非特权进程风险很高。

4. 常用IOCTL

命令 作用
FBIOGET_VSCREENINFO 获取可变mode
FBIOPUT_VSCREENINFO 设置mode
FBIOGET_FSCREENINFO 获取显存、stride、类型
FBIOGETCMAP/PUTCMAP colormap
FBIOPAN_DISPLAY 改x/y offset
FBIOBLANK blank/power
FBIO_CURSOR cursor(依实现)
vendor ioctl 驱动私有扩展

Compat ioctl必须转换含pointer的结构。

5. Pan/Double Buffer

若virtual resolution大于visible resolution,应用可在同一显存中准备多个buffer,再用PAN切换offset。

Pan不保证vblank同步;驱动需实现等待或提供扩展。

6. Pixel Format

fb_var_screeninfo用bits_per_pixel及RGBA bitfield描述格式。它不同于DRM fourcc,应用不能仅凭bpp推断通道顺序。

7. Sysfs

fbsysfs.c暴露:

  • bits_per_pixel;
  • blank;
  • console rotation;
  • cursor;
  • mode/modes;
  • pan;
  • virtual size;
  • stride;
  • name/state等。

写属性最终仍调用fb_ops并经过合法性检查。

8. Deferred I/O

fb_defio通过page fault/page dirty和delayed work收集修改,定时调用driver callback刷新。

适用于SPI/e-paper/USB等慢速设备,不适合高帧率scanout。

9. Colormap

Truecolor常使用pseudo palette;pseudocolor使用硬件cmap。fb_set_cmap逐entry调用setcolreg,需校验start/len。

10. 权限

能mmap /dev/fbN通常可读当前屏幕并覆盖显示内容。产品应:

  • 限制node group;
  • 不向普通容器透传;
  • 避免映射寄存器;
  • 清除重新分配的display buffer;
  • 防止模式设置影响安全UI。

11. 错误排查

1
2
3
4
ls -l /dev/fb*
cat /sys/class/graphics/fb0/name
fbset -fb /dev/fb0 -i
cat /proc/fb

若由DRM emulation产生,还应检查/sys/class/drm和DRM日志。

显示模式、EDID 与 Device Tree Timing

显示模式、EDID 与 Device Tree Timing

1. 数据模型

display_timing每个参数可有min/typ/max:

  • pixelclock;
  • hactive、hfront porch、hsync、hback porch;
  • vactive、vfront porch、vsync、vback porch;
  • sync polarity和data enable flags。

videomode是选定后的具体数值。

2. 转换

videomode_from_timing()通常取typ值并转换flags。反向转换用于跨fbdev/DRM/panel helper共享。

3. DT结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
display-timings {
native-mode = <&timing0>;
timing0: timing-0 {
clock-frequency = <...>;
hactive = <...>;
hfront-porch = <...>;
hsync-len = <...>;
hback-porch = <...>;
vactive = <...>;
vfront-porch = <...>;
vsync-len = <...>;
vback-porch = <...>;
};
};

属性可为单值或范围。

4. OF API

  • of_get_display_timing()
  • of_get_display_timings()
  • of_get_videomode()
  • native mode选择;
  • timing释放。

Parser必须检查缺失属性、范围顺序和overflow。

5. fbdev ModeDB

modedb.c维护标准video modes,解析video=参数并做最佳匹配。fbcvt.c生成CVT mode。

6. EDID

fbmon.c解析EDID:

  • header/checksum;
  • established/standard timings;
  • detailed timing descriptors;
  • monitor range;
  • preferred mode。

fb_ddc.c可通过I2C DDC读取EDID。

7. Mode验证

候选mode还必须满足:

  • display controller pixel clock;
  • output PHY/link bandwidth;
  • plane/stride和memory bandwidth;
  • panel固定时序;
  • bridge限制;
  • porch/sync范围。

DT能解析不等于硬件可用。

8. HDMI Helper

hdmi.c提供HDMI相关通用结构/信息处理辅助,但RK3588 HDMI controller、PHY、HDCP和connector状态主要在DRM/vendor驱动中。

9. 时钟误差

实际PLL可能只能近似pixelclock。Driver应检查允许误差并把实际mode反馈给上层,防止面板抖动或音视频不同步。

10. RK3588

固定panel常由DT panel timing/compatible描述;HDMI/DP/eDP通常通过EDID和DRM mode probing。VOP2输出route决定video port连接哪个connector。

11. 常见故障

现象 检查
无mode EDID/DDC、DT timing、connector状态
花屏 pixel format、clock、lane/PHY
偏移 porch/sync polarity
间歇黑屏 link bandwidth、PLL误差、HPD
panel亮但无图 route/endpoint/VOP plane

12. 安全

EDID来自外部显示器,应视为不可信:校验长度、extension count、descriptor offset和乘法溢出,避免恶意EDID触发越界。