跳转至内容

内核模式设置

来自 ArchWiki
(重定向自 KMS)

本文章或章节需要扩充。

原因: KMS 和无根 X (1.16),参见 Talk:Kernel mode settingXorg#Rootless Xorg。(在 Talk:Kernel mode setting 中讨论)

Kernel Mode Setting (KMS) 是一种在内核空间而不是用户空间设置显示分辨率和深度的技术。

Linux 内核的 KMS 实现支持帧缓冲区的原生分辨率,并允许即时切换控制台(tty)。KMS 还支持更新的技术(如 DRI2),这有助于减少画面瑕疵并提高 3D 性能,甚至支持内核空间的节能功能。

注意 专有的 NVIDIA 驱动程序(自 364.12 起)也实现了内核模式设置,但它不使用内置的内核实现,并且用于高分辨率控制台的 fbdev 驱动仅作为可选的实验性功能存在(自 545.29 起)。

背景

以前,显卡设置是 X 服务器的工作。因此,在 虚拟控制台 中实现精美的图形并不容易。此外,每次从 X 切换到虚拟控制台(Ctrl+Alt+F2)时,服务器都必须将显卡控制权交给内核,这很慢并会导致闪烁。当控制权交还给 X 服务器时(当 X 在 VT7 中运行时为 Alt+F7),也会发生同样的“痛苦”过程。

通过 Kernel Mode Setting (KMS),内核现在能够设置显卡模式。这使得启动画面、虚拟控制台和 X 之间的快速切换成为可能,等等。

配置

首先,请注意,对于您使用的任何方法,都应始终禁用

  • 引导加载程序 中的任何 vga= 选项,因为它们会与 KMS 启用的原生分辨率冲突。
  • 启用与驱动程序冲突的帧缓冲区的任何 video= 行。

本文或本章节已过时。

原因: Arch 官方支持的内核 多年来一直内置simpledrm KMS 驱动 [1]。这意味着 Arch 用户始终具有早期 KMS 启动。所以这一节更多的是关于“何时simpledrm 将控制权转移给另一个驱动程序”。(在 Talk:Kernel mode setting 中讨论)

本文章或章节需要扩充。

原因: 提及simpledrm 及其作为通用图形驱动程序的能力。(在 Talk:Kernel mode setting 中讨论)

Late KMS start

IntelNouveauATIAMDGPU 驱动程序已自动为所有芯片组启用 KMS,因此您无需执行任何操作。

专有的 NVIDIA 驱动程序支持 KMS(自 364.12 起),需要手动启用

Early KMS start

提示 如果遇到分辨率问题,可以检查强制模式是否有帮助。

KMS 通常在initramfs 阶段之后初始化。然而,也可以在 initramfs 阶段启用 KMS。将所需的显卡驱动模块添加到 initramfs 配置文件中。

  • mgag200 用于 Matrox 显卡。
  • 取决于所使用的 QEMU 显卡(qemu 选项 -vga typelibvirt <video><model type='type'>[2]
    • bochs 用于 std (qemu) 和 vga/bochs (libvirt),
    • virtio-gpu 用于 virtio
    • qxl 用于 qxl
    • vmwgfx 用于 vmware (qemu) 和 vmvga (libvirt),
    • cirrus 用于 cirrus
  • 取决于 VirtualBox 显卡控制器
    • vmwgfx 用于 VMSVGA,
    • vboxvideo 用于 VBoxVGA 或 VBoxSVGA。

Initramfs 的配置说明因您使用的 initramfs 生成器而略有不同。

mkinitcpio

对于树内模块,请确保 kms 已包含在 /etc/mkinitcpio.conf 的 HOOKS 数组中(自 mkinitcpio v33 起即为默认设置)。

对于树外模块,请将模块名称放在 MODULES 数组中。例如,要为 NVIDIA 显卡驱动启用早期 KMS:

/etc/mkinitcpio.conf
MODULES=(... nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)
注意 如果您使用 PRIME 图形处理单元 (GPU),且 Intel 集成显卡 (IGP) 是主 GPU,AMD 是独立 GPU,则 intel_agp 可能导致从休眠恢复时出现问题(显示器无信号)。有关详细信息,请参阅 [3]

如果您使用#强制模式和EDID 方法,您还应该将自定义文件嵌入 initramfs 中。

/etc/mkinitcpio.conf
FILES=(/usr/lib/firmware/edid/your_edid.bin)

然后重新生成 initramfs

Booster

如果您使用 Booster,可以通过以下配置更改加载所需模块:

/etc/booster.yaml
modules_force_load: i915

如果您使用#强制模式和EDID 方法,您还应该将自定义文件嵌入到您的 booster 镜像中。

/etc/booster.yaml
extra_files: /usr/lib/firmware/edid/your_edid.bin

然后重新生成 booster 镜像

Dracut

Dracut 通过其 --force_drivers 命令或 force_drivers+="" 配置条目行,支持早期加载(在 initramfs 阶段,通过 modprobe)。例如:

/etc/dracut.conf.d/myflags.conf
# ...
force_drivers+=" amdgpu "
# ...

故障排除

我的字体太小了

有关如何更改控制台字体以使用大字体的说明,请参阅 Linux console#Fonts。Terminus 字体(terminus-font)有多种尺寸可选,例如 ter-132b 尺寸更大。

或者,禁用 modesetting 可能会切换到较低的分辨率,使字体看起来更大。

强制模式和EDID

如果您的原生分辨率未自动配置,或者根本未检测到显示器,则您的显示器可能不发送 EDID 文件,或者只发送一个损坏的 EDID 文件。内核将尝试捕获此情况并设置最典型分辨率之一。

如果您有显示器的 EDID 文件,您只需明确强制它(见下文)。然而,大多数情况下,您无法直接访问一个有效的 EDID 文件,因此有必要提取一个现有的并修复它,或者生成一个新的。

通过遵循上游文档(另请参阅此处的简短指南),可以在内核编译期间为各种分辨率和配置生成新的 EDID 二进制文件。此文章中详细概述了其他解决方案。在大多数情况下,提取现有的 EDID 文件更容易,例如,如果您的显示器在 Windows 下工作正常,您可能会幸运地从相应的驱动程序中提取 EDID,或者如果一个具有相同设置的类似显示器可以工作,您可以使用来自 read-edid 包中的 get-edid(1)。您还可以尝试在 /sys/class/drm/*/edid 中查找。

准备好 EDID 文件后,将其放在一个目录中,例如在 /usr/lib/firmware/ 下名为 edid 的目录,并将您的二进制文件复制到其中。

要在启动时加载它,请在 内核命令行中指定以下内容:

drm.edid_firmware=edid/your_edid.bin

为了仅将它应用于特定的连接器,请使用:

drm.edid_firmware=VGA-1:edid/your_edid.bin

如果要设置多个 edid 文件,请使用:

drm.edid_firmware=VGA-1:edid/your_edid.bin,VGA-2:edid/your_other_edid.bin

如果您正在进行 早期 KMS,则必须 将自定义 EDID 文件包含在 initramfs 中,否则会遇到问题。

drm.edid_firmware 参数的值也可以在启动后通过写入 /sys/module/drm/parameters/edid_firmware 来修改。

# echo edid/your_edid.bin > /sys/module/drm/parameters/edid_firmware

这只会对新插入的显示器生效,已插入的屏幕将继续使用其现有的 EDID 设置。但是,对于外部显示器,重新插拔它们足以看到效果。

要在启动后加载 EDID,如果内核未处于 锁定模式,您可以使用 debugfs 而不是内核参数。这对于交换连接器上的显示器或仅用于测试非常有用。一旦有了上述 EDID 文件,请运行:

# cat correct-edid.bin > /sys/kernel/debug/dri/0/HDMI-A-2/edid_override

并禁用:

# echo -n reset > /sys/kernel/debug/dri/0/HDMI-A-2/edid_override

如果您的显示器支持热插拔,您还可以触发一次热插拔,使显示器使用您刚刚加载的新 EDID(例如,加载到 edid_override 中),这样您就不必物理上重新插拔显示器或重启了。

# echo 1 > /sys/kernel/debug/dri/0/HDMI-A-2/trigger_hotplug

强制模式

注意 下面描述的方法有些不完善,因为例如 Xorg 不会考虑指定的解决方案,因此鼓励用户使用上述方法。但是,使用 video= 命令行指定分辨率对所有 Wayland 合成器都很有用。

来自 nouveau wiki

可以在内核命令行上强制设置模式。不幸的是,DRM 情况下的 video 命令行选项文档非常少。关于如何使用它的零散信息可以在以下找到:

格式是:

video=<driver>:<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
  • <driver>: 在启动时指定视频模式。
  • <conn>: 指定视频连接类型,如 VGA、DVI、HDMI 等,请参阅 /sys/class/drm/ 中的可用连接器。
  • <xres>: 水平分辨率(像素)。
  • <yres>: 垂直分辨率(像素)。
  • [M]: 启用 VESA Coordinated Video Timings (CVT) 来计算视频模式时序,而不是从数据库查找模式。
  • [R]: 在使用 CVT 时,启用数字显示器的减少消隐计算。这会减少水平和垂直消隐间隔以节省带宽。
  • [-<bpp>]: 指定颜色深度或每像素位数(例如,-24 表示 24 位颜色)。
  • [@<refresh>]: 指定刷新率(Hz)。
  • [i]: 启用隔行扫描模式。
  • [m]: 为 CVT 计算添加边距(xres 的 1.8% 向下取整到 8 像素,yres 的 1.8%)。
  • [e]: 输出强制开启。
  • [D]: 数字输出强制开启(例如,DVI-I 连接器)。
  • [d]: 输出强制关闭。

您可以使用多次 video= 来覆盖多个输出的模式,例如,强制 DVI 分辨率为 1024x768,刷新率为 85 Hz,而 TV-out 关闭。

video=DVI-I-1:1024x768@85 video=TV-1:d

选项也可以跟在模式后面,使用逗号作为分隔符。

video=DVI-I-1:720x480,rotate=180

有效选项包括:

  • margin_topmargin_bottommargin_leftmargin_right (整数):边距的像素数,通常用于处理电视机的过扫描。
  • reflect_x (布尔值):沿 X 轴执行轴对称。
  • reflect_y (布尔值):沿 Y 轴执行轴对称。
  • rotate (整数):将初始帧缓冲区旋转 x 度。有效值为 0、90、180 和 270。
  • tv_mode:模拟电视模式。值为 "NTSC"、"NTSC-443"、"NTSC-J"、"PAL"、"PAL-M"、"PAL-N" 或 "SECAM" 之一。
  • panel_orientation,值为 "normal"、"upside_down"、"left_side_up" 或 "right_side_up" 之一。仅适用于 KMS 驱动程序,这将设置 KMS 连接器上的“面板方向”属性,作为 KMS 用户的提示。

要获取连接器的名称和当前状态,您可以使用以下 shell 单行命令:

$ for p in /sys/class/drm/*/status; do con=${p%/status}; echo -n "${con#*/card?-}: "; cat $p; done
DVI-I-1: connected
HDMI-A-1: disconnected
VGA-1: disconnected

禁用 modesetting

您可能出于各种原因希望禁用 KMS。要禁用 KMS,请将 nomodeset 添加为内核参数。有关更多信息,请参阅 Kernel parameters

除了 nomodeset 内核参数外,对于 Intel 显卡,您需要添加 i915.modeset=0;对于 Nvidia 显卡,您需要添加 nouveau.modeset=0。对于 Nvidia Optimus 双显卡系统,您需要添加所有三个内核参数(即 "nomodeset i915.modeset=0 nouveau.modeset=0")。

注意 一些 Xorg 驱动程序在禁用 KMS 时将无法工作。有关详细信息,请参阅您特定驱动程序的 wiki 页面。