尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

ARM64平台Linux内核驱动编译实战:为飞腾CPU适配SM750显卡

ARM64平台Linux内核驱动编译实战:为飞腾CPU适配SM750显卡 1. 项目概述当国产CPU遇上“冷门”显卡最近在折腾一台基于飞腾FT-2000/4处理器的国产化主机系统装的是Ubuntu 22.04 LTS。硬件配置里有一张SM750/768的显卡这卡在x86世界里可能都快被遗忘了但在我们这国产化平台上还挺常见很多工控机、一体机里都用它做基础显示输出。装完系统桌面是起来了但总感觉哪里不对劲分辨率锁在1024x768上不去外接显示器也没反应lspci里能看到显卡但glxinfo一看渲染器是llvmpipe软件渲染这明显是驱动没装上。这其实是一个挺典型的场景在基于飞腾ARM架构的平台上为一些老旧的或特定领域的显卡寻找并安装合适的Linux驱动。SM750/768是硅谷数模Silicon Motion比较早期的2D显示芯片其开源驱动sm750fb早已被并入Linux内核的staging目录但默认编译配置和针对ARM64架构特别是飞腾平台的兼容性需要我们自己动手调整。这个过程不仅仅是运行一个安装脚本那么简单它涉及到内核配置、源码编译、模块加载以及对国产平台UEFI固件特性的理解。如果你手头也有类似的飞腾D2000或FT-2000/4机器正为显卡驱动发愁或者对在非x86架构上搞定驱动这件事感兴趣那这篇从踩坑到填坑的实录应该能帮到你。2. 核心需求与挑战拆解在开始动手前我们得先搞清楚目标是什么以及路上有哪些“拦路虎”。2.1 核心需求让显卡在飞腾平台上正常工作说得直白点我们的目标就三个正确的显示输出让系统能识别并使用SM750/768显卡输出图像到正确的接口通常是VGA或DVI支持合理的分辨率至少1080p。启用硬件加速虽然SM750是2D显卡但正确的驱动能提供fbdev或drm框架支持将图形显示工作从CPU软件渲染卸载到显卡减轻CPU负担提升桌面操作的流畅度。系统集成与稳定驱动要以内核模块的形式正确安装能随系统启动自动加载并且不会导致系统崩溃、黑屏或与其他驱动冲突。2.2 面临的主要挑战为什么在飞腾上装这个驱动会比在普通x86电脑上更麻烦主要有以下几点架构差异飞腾FT-2000/4、D2000是ARMv8架构的64位处理器aarch64。而绝大多数Linux显卡驱动的预编译包尤其是闭源驱动都是为x86_64架构准备的。SM750的开源驱动虽然代码通用但内核配置和编译环境必须针对ARM64。内核配置的坑SM750的驱动CONFIG_FB_SM750在主流内核中位于staging目录。staging是代码进入内核主线前的“候车室”里面的驱动可能编译警告较多默认不一定启用或者依赖一些不常见的配置选项。在ARM64平台上这些依赖项可能需要额外关注。固件与引导的特殊性许多飞腾主板采用符合国产化要求的UEFI固件其图形输出协议GOP可能与通用标准存在细微差异。在驱动初始化阶段如果帧缓冲区Framebuffer设置不当可能导致引导阶段或加载驱动时黑屏。信息稀缺围绕飞腾平台和SM750这种组合的社区讨论和现成教程非常少。大部分经验都来自x86平台直接套用可能会失败需要自己摸索和调试。3. 环境准备与内核源码获取工欲善其事必先利其器。我们首先需要一个完整的编译环境和正确版本的内核源码。3.1 系统基础环境确认首先登录你的飞腾主机打开终端确认系统基本信息uname -a # 输出应包含 aarch64 和 Ubuntu 版本信息例如Linux hostname 5.15.0-xx-generic #xx-Ubuntu SMP ... aarch64 aarch64 aarch64 GNU/Linux lsb_release -a # 查看Ubuntu具体版本如22.04 LTS lspci | grep -i vga # 或 lspci | grep -i silicon # 确认SM750/768显卡已被系统识别。输出可能类似01:00.0 VGA compatible controller: Silicon Motion, Inc. SM750/768 (rev 01)3.2 安装必要的编译工具链编译内核模块需要开发工具和内核头文件。在Ubuntu上安装以下包sudo apt update sudo apt install -y build-essential libncurses-dev libssl-dev bc flex bison libelf-dev dwarves sudo apt install -y linux-headers-$(uname -r)注意linux-headers-$(uname -r)安装的是与你当前运行内核版本一致的头文件这对于后续编译外部模块DKMS方式至关重要。但如果你想深度定制内核配置可能需要获取完整源码。3.3 获取与当前内核版本匹配的源码最稳妥的方法是获取与你系统当前运行内核版本号完全一致的源码。Ubuntu提供了简便的方式# 查看精确的内核版本 uname -r # 例如5.15.0-91-generic # 安装对应版本的源码包 sudo apt install -y linux-source-5.15.0安装后源码通常位于/usr/src/linux-source-5.15.0.tar.bz2。解压它cd /usr/src sudo tar -xaf linux-source-5.15.0.tar.bz2 cd linux-source-5.15.0实操心得直接使用发行版提供的内核源码包能最大程度保证与当前系统内核的API兼容性避免因版本差异导致编译出的模块无法插入Invalid module format错误。这对于驱动开发新手来说是最安全的选择。4. 内核配置与SM750驱动编译这是最核心的一步我们需要在内核配置中启用SM750驱动并针对ARM64平台进行编译。4.1 生成当前内核的配置基准为了避免从零开始配置成千上万个选项我们以当前运行内核的配置为起点# 将当前内核的配置复制到源码目录 cp /boot/config-$(uname -r) .config这个.config文件包含了当前Ubuntu内核的所有配置选项其中就可能有FB_SM750相关的设置很可能被禁用。4.2 启动内核配置界面并定位驱动运行菜单式配置工具make menuconfig如果提示缺少ncurses库请确认已安装libncurses-dev。在图形化界面中我们需要找到SM750驱动的配置项。使用键盘方向键导航。按下/键进入搜索模式。输入SM750回车。它会告诉你这个配置项的位置通常是Device Drivers - Graphics support - Frame buffer Devices - SiliconMotion SM750 framebuffer support (FB_SM750)根据提示按1键可以直接跳转到该配置项。4.3 启用SM750驱动及其依赖跳转后你会看到FB_SM750选项它可能被标记为 未设置、M编译为模块或*编译进内核。我们选择M编译为模块这样更灵活。关键步骤解析将驱动编译为模块M意味着它会生成一个独立的.ko文件如sm750fb.ko可以在系统运行时动态加载或卸载无需重新编译整个内核。这对于调试和更新驱动非常方便。按下空格键将其切换为M。但这里有一个至关重要的坑仅仅启用FB_SM750可能不够。你需要检查并确保它的依赖项也被启用。按回车键进入FB_SM750的子选项如果有或者退出后检查相关依赖。通常SM750驱动依赖于FB_CFB_FILLRECT,FB_CFB_COPYAREA,FB_CFB_IMAGEBLIT这些是帧缓冲区的通用加速函数通常默认已启用。DRM或FB相关的其他基础支持。在Graphics support菜单下确保Support for frame buffer devices被启用。一个更稳妥的方法是在配置完成后使用make olddefconfig命令让系统自动处理所有依赖关系将新启用的选项所依赖的项都设为默认值。# 退出 menuconfig 后执行 make olddefconfig4.4 针对ARM64平台的编译现在开始编译驱动模块。我们不需要编译整个内核只编译我们修改过的模块部分这样可以节省大量时间。# 准备编译环境这步会生成一些必要的头文件链接 make prepare make modules_prepare # 编译 SM750 相关的驱动模块 make Mdrivers/video/fbdevM参数指定了包含我们需要编译的驱动的子目录路径。编译过程会持续几分钟最终在drivers/video/fbdev/目录下生成sm750fb.ko等内核模块文件。注意事项编译过程中如果出现大量警告warning只要不是错误error通常可以忽略。staging目录下的驱动代码警告较多是常见现象。但如果出现“Error 1”等编译错误则需要根据错误信息排查可能是缺少某个头文件或依赖的配置项未正确打开。5. 驱动模块安装与加载测试编译成功只是第一步让内核正确加载并识别它才是关键。5.1 安装编译好的模块将新编译的模块安装到系统的标准模块目录中通常是/lib/modules/$(uname -r)/kernel/drivers/下的相应子目录。# 安装模块 sudo make Mdrivers/video/fbdev modules_install执行此命令后sm750fb.ko会被复制到/lib/modules/$(uname -r)/extra/或/lib/modules/$(uname -r)/kernel/drivers/video/fbdev/目录下。同时系统会运行depmod命令更新模块依赖关系。5.2 手动加载驱动并验证在配置系统自动加载前我们先手动测试一下模块是否能正常工作。# 先卸载可能存在的旧版本或冲突模块如果有的话 sudo modprobe -r sm750fb 2/dev/null # 加载新编译的模块 sudo modprobe sm750fb # 查看模块加载信息 dmesg | tail -20 # 重点查找包含 “sm750”、“fb0”、“Silicon Motion” 字样的行。 # 成功的输出可能类似 # [ 12.345678] sm750fb: framebuffer at 0x...., mapped to 0x.... # [ 12.345679] sm750fb: VRAM at 0x...., size 64MB # [ 12.345680] fb0: sm750fb frame buffer device # 检查帧缓冲设备 ls -l /dev/fb* # 应该能看到 /dev/fb0 设备文件。 # 检查显示接口是否被正确识别 xrandr --listproviders # 如果驱动支持DRM/KMS这里可能会列出新的显示提供者。如果dmesg中没有显示严重的错误如probe failed,failed to map memory并且出现了fb0设备说明驱动加载初步成功。5.3 配置系统启动时自动加载为了让驱动在每次启动时生效我们需要将其添加到内核的模块加载列表中。# 将模块名添加到 /etc/modules 文件中 echo sm750fb | sudo tee -a /etc/modules # 或者更推荐使用 modules-load.d 方式创建一个专用配置文件 echo sm750fb | sudo tee /etc/modules-load.d/sm750.conf使用modules-load.d的方式更模块化便于管理。5.4 更新初始RAM文件系统initramfs这一步非常重要尤其是当你的根文件系统在启动早期就需要访问这个驱动时例如用于控制台显示。更新initramfs会将新安装的内核模块打包进启动镜像。sudo update-initramfs -u -k all更新完成后强烈建议重启系统以全面测试驱动在完整启动流程中的表现。sudo reboot6. 桌面环境配置与分辨率设置驱动加载成功设备文件也有了但桌面环境可能还是没使用它或者分辨率不正确。这时就需要配置显示服务器通常是X11或Wayland。6.1 为X11服务器配置显示设备Ubuntu 22.04 默认使用GNOME桌面其显示服务器可能是X11或Wayland。我们首先按X11来配置因为它对老旧硬件的支持更成熟。创建或编辑X11配置文件sudo nano /etc/X11/xorg.conf.d/20-sm750.conf如果/etc/X11/xorg.conf.d目录不存在可以创建它。写入基本配置Section Device Identifier SM750 Driver fbdev # SM750开源驱动通常通过fbdev框架工作 Option fbdev /dev/fb0 EndSection Section Screen Identifier Default Screen Device SM750 Monitor Configured Monitor SubSection Display Modes 1920x1080 1280x1024 1024x768 # 将你期望的分辨率放在最前面 EndSection EndSection注意Driver fbdev是通用帧缓冲驱动。如果SM750驱动实现了完整的DRM/KMS支持理论上可以使用modesetting驱动性能更好。但对于staging中的sm750fbfbdev通常是更可靠的选择。你可以尝试将Driver改为modesetting如果不行再换回fbdev。保存并重启显示管理器sudo systemctl restart gdm3 # 或者 lightdm、sddm根据你的登录管理器而定重启后登录桌面检查分辨率是否已改变。6.2 使用xrandr命令行工具调整如果X11配置不生效或者你想临时测试可以使用xrandr工具。# 查看当前显示输出和可用模式 xrandr # 假设输出名为 “default” 或 “fb0”尝试设置新分辨率 # 首先用 cvt 生成一个模型行modeline cvt 1920 1080 60 # 输出会给出一个 Modeline例如“1920x1080_60.00” 一堆数字 # 使用 xrandr 新建一个模式并应用 xrandr --newmode 1920x1080_60 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync vsync xrandr --addmode default 1920x1080_60 xrandr --output default --mode 1920x1080_60如果xrandr提示找不到default输出请先用xrandr --listmonitors查看正确的输出名称。6.3 针对Wayland的考量如果你的系统运行在Wayland下可以通过echo $XDG_SESSION_TYPE查看情况会有所不同。Wayland不直接使用xorg.conf而是依赖于内核的DRM/KMS驱动和Compositor如Mutter。如果sm750fb驱动正确地向内核DRM子系统注册了设备并且支持KMS那么GNOME on Wayland应该能自动识别并使用它。验证方法# 查看DRM设备 ls /sys/class/drm/ # 应该能看到类似 card0 的目录。 # 进入目录查看状态 cat /sys/class/drm/card0/status # 如果连接了显示器可能会显示 “connected”。 # 查看内核的DRM日志 sudo dmesg | grep -i drm如果DRM日志中出现了SM750的相关信息并且/sys/class/drm/card0存在说明驱动可能已经以DRM模式工作。此时分辨率设置通常由桌面环境或gnome-control-center中的“显示”设置来管理。7. 常见问题排查与调试实录在实际操作中几乎不可能一帆风顺。下面是我在飞腾D2000平台上遇到的一些典型问题及解决方法。7.1 驱动编译失败问题现象执行make Mdrivers/video/fbdev时出现错误编译中断。可能原因与排查缺少依赖的头文件或工具错误信息通常会指明。确保已安装build-essential、linux-headers和所有必要的开发库。对于ARM64有时需要特定的交叉编译工具链吗不在飞腾主机本机编译使用系统自带的gcc即可。内核配置不完整make modules_prepare没有执行或执行失败。确保在编译模块前成功执行了make prepare和make modules_prepare。源码版本不匹配使用的内核源码版本与当前运行的内核版本差异过大。务必使用apt安装的与uname -r匹配的源码包。驱动代码本身问题staging驱动可能有代码错误。查看具体的错误行有时可以通过简单的补丁修复。可以尝试搜索该错误信息看是否有社区补丁。作为最后手段可以考虑在menuconfig中尝试启用CONFIG_FB_SM750_DEBUG等调试选项但通常不必要。7.2 模块加载失败或系统黑屏问题现象sudo modprobe sm750fb后命令挂起或系统黑屏/冻结或dmesg中出现probe failed、ioremap failed等错误。排查步骤检查内核消息这是最重要的线索。即使黑屏如果系统没有完全死锁可以尝试通过SSH远程登录或者使用串口控制台查看dmesg。dmesg | grep -i -A5 -B5 sm750 dmesg | grep -i -A5 -B5 error资源冲突常见的错误是failed to claim resource或ioremap failed for MMIO。这表示驱动请求的内存映射区域MMIO或中断号IRQ与其他设备冲突。可以通过cat /proc/iomem和cat /proc/interrupts查看资源分配情况。解决起来比较棘手可能需要在内核启动参数中为PCI设备预留资源或者调整BIOS/UEFI设置中的PCI资源配置。飞腾平台特定问题有些飞腾主板的UEFI固件对PCIe资源配置比较特殊。尝试在UEFI设置中将显示相关的选项如“CSM Support”兼容性支持模块设置为“Disabled”强制使用纯UEFI模式或者反之启用CSM。这有时能解决早期显卡的初始化问题。使用insmod代替modprobe并传递参数modprobe加载失败时可以尝试用insmod直接指定模块路径并传递一些调试参数。sudo insmod /lib/modules/$(uname -r)/extra/sm750fb.ko debug1查看dmesg输出的调试信息。可用的参数通常可以在驱动源码的MODULE_PARM_DESC附近找到。7.3 驱动加载成功但分辨率不对或无显示问题现象dmesg显示驱动加载成功/dev/fb0也存在但桌面分辨率仍是低分辨率或者外接显示器无信号。排查步骤检查EDID信息显示器通过EDID向显卡报告其支持的分辨率。驱动可能未能正确读取EDID。# 安装 edid-decode 工具 sudo apt install edid-decode # 尝试读取EDID可能需要root权限 sudo cat /sys/class/drm/card0-*/edid | edid-decode如果输出显示“No EDID”或解析失败说明EDID读取有问题。可以在X11配置中手动指定ModeLine如前文xrandr部分所示。确认活动显示输出有些主板同时集成了飞腾的显示核心可能很弱和独立的SM750。需要确认系统实际使用的是哪个显卡。lspci -v | grep -A10 -B2 VGA # 查看哪个VGA设备是主设备。Xorg日志也可能有线索。 cat /var/log/Xorg.0.log | grep -i using driver可能需要通过UEFI/BIOS设置指定主显示设备为“PCIe”或“External Graphics”。帧缓冲区控制台冲突如果Linux内核的文本控制台tty绑定在了fb0上可能会干扰图形桌面的使用。可以尝试修改内核启动参数将控制台切换到串口ttyS0或VGA文本模式。 编辑/etc/default/grub在GRUB_CMDLINE_LINUX行添加或修改GRUB_CMDLINE_LINUX... consolettyS0,115200n8然后运行sudo update-grub并重启。这样图形桌面就能独占帧缓冲区了。7.4 性能不佳或桌面卡顿问题现象驱动工作但桌面操作明显卡顿glxinfo显示渲染器可能还是llvmpipe软件渲染。原因与优化驱动模式确认是否在使用fbdev驱动。fbdev性能有限。如果dmesg显示驱动注册了DRM设备尝试在X11配置中使用Driver modesetting。modesetting驱动是通用的DRM/KMS驱动性能通常优于fbdev。2D加速SM750是2D加速卡。确保X11的2D加速扩展如EXA或XAA取决于驱动被启用。对于fbdev加速功能有限。可以尝试安装xserver-xorg-video-fbdev包的最新版。内存分配检查驱动日志中VRAM显存的分配大小。如果分配过小会影响性能。有些驱动模块可以通过参数调整显存大小例如sudo modprobe sm750fb vram64单位MB具体参数名需查源码。但这需要驱动支持且不保证有效。终极方案如果对图形性能要求较高SM750可能无法满足。需要考虑更换为在ARM平台上有更好开源驱动支持的显卡如部分AMD的GCN架构老显卡amdgpu驱动或更早期的ATI显卡radeon驱动但这又涉及到飞腾主板PCIe插槽的兼容性和供电问题是另一个层面的挑战了。8. 总结与后续维护建议经过以上步骤你应该已经成功在飞腾FT-2000/4或D2000的Ubuntu系统上让SM750/768显卡从“黑箱”状态变成了可用的显示输出设备。这个过程的核心在于理解ARM64平台与x86的差异、掌握内核模块的编译与配置方法、以及具备通过日志dmesg, Xorg.log进行问题定位的能力。最后分享几点维护建议内核升级每次通过apt upgrade升级系统内核后新内核不会自动包含你手动编译的sm750fb.ko模块。你需要重新执行编译和安装步骤从获取新内核头文件开始。可以考虑将编译过程写成脚本自动化。DKMS动态内核模块支持为了更优雅地处理内核升级强烈建议将SM750驱动制作成DKMS包。这样每次安装新内核时DKMS会自动为你重新编译驱动。这需要编写一个简单的dkms.conf文件将驱动源码纳入DKMS管理。这是生产环境更推荐的做法。备份配置妥善保管你修改过的内核配置文件.config、X11配置文件以及任何有效的内核启动参数。这些是系统恢复和重建的关键。关注上游偶尔去查看一下主线Linux内核的staging目录看看drivers/staging/sm750fb/是否有更新。虽然变化可能很慢但万一有重要的修复或功能改进呢你可以尝试将新代码合并到你的本地版本中。在国产化平台上的这类实践很多时候没有现成的答案需要的就是这种“摸着石头过河”的耐心和从底层日志中寻找线索的能力。希望这篇详尽的记录能为你照亮前进路上的一小段。
返回列表