跳转至内容

内核模式设置

来自 ArchWiki

本文章或章节需要扩充。

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

内核模式设置 (KMS) 是一种在内核空间而非用户空间设置显示分辨率和深度的方法。

Linux 内核对 KMS 的实现可在帧缓冲(framebuffer)中启用原生分辨率,并允许瞬间切换控制台 (tty)。KMS 还启用了较新的技术(如 DRI2),这有助于减少伪影并提高 3D 性能,甚至实现内核空间的省电功能。

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

背景

此前,配置显卡是 X 服务器的工作。因此,在虚拟控制台中很难实现精美的图形界面。此外,每次从 X 切换到虚拟控制台(Ctrl+Alt+F2)时,服务器必须将显卡的控制权交给内核,这一过程缓慢且会导致闪烁。当控制权交回 X 服务器(当 X 运行在 VT7 时按下 Alt+F7)时,同样会发生这种“痛苦”的过程。

通过内核模式设置 (KMS),内核现在能够设置显卡的模式。这使得引导过程中的精美图形、虚拟控制台与 X 之间的快速切换等成为可能。

配置

首先,请注意无论您使用任何方法,都应始终禁用以下内容:

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

本文或本章节已过时。

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

本文章或章节需要扩充。

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

延迟 KMS 启动

Intel, Nouveau, ATIAMDGPU 驱动程序已经为所有芯片组自动启用了 KMS,因此您无需进行任何操作。

专有的 NVIDIA 驱动程序支持 KMS(自 364.12 版本起),但必须手动启用

早期 KMS 启动

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

KMS 通常在 initramfs 阶段之后初始化。但是,可以在 initramfs 阶段启用 KMS。将视频驱动程序所需的模块添加到 initramfs 配置文件中:

  • 对于 AMDGPU 使用 amdgpu,或者在使用旧版 ATI 驱动程序时使用 radeon
  • 对于 Intel 显卡使用 i915
  • 对于开源 Nouveau 驱动程序使用 nouveau
  • 对于外部 NVIDIA 驱动程序使用 nvidia nvidia_modeset nvidia_uvm nvidia_drm。详见 NVIDIA#DRM kernel mode setting
  • 对于 Matrox 显卡使用 mgag200
  • 取决于所使用的 QEMU 图形(qemu 选项 -vga typelibvirt <video><model type='type'>[2]):
    • std (qemu) 和 vga/bochs (libvirt) 使用 bochs
    • virtio 使用 virtio-gpu
    • qxl 使用 qxl
    • vmware (qemu) 和 vmvga (libvirt) 使用 vmwgfx
    • cirrus 使用 cirrus
  • 取决于 VirtualBox 图形控制器:
    • VMSVGA 使用 vmwgfx
    • VBoxVGA 或 VBoxSVGA 使用 vboxvideo

Initramfs 的配置指令根据您使用的 initramfs 生成器而略有不同。

mkinitcpio

对于内置模块,可以使用 /etc/mkinitcpio.conf 中 HOOKS 数组里的 kms(自 mkinitcpio v33 起的默认设置),或将模块名称放入 MODULES 数组中。

对于外部 NVIDIA 模块,您必须按如下方式将模块名称放入 MODULES 数组中:

/etc/mkinitcpio.conf
MODULES=(... nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)
注意 如果您使用 PRIME 图形处理单元 (GPU),且 Intel 集成显卡 (IGP) 是主 GPU,AMD 为独立显卡,则 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 "
# ...

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

/etc/dracut.conf.d/myflags.conf
install_items+=" /usr/lib/firmware/edid/your_edid.bin "

然后重新生成 dracut 镜像

故障排除

我的字体太小了

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

或者,禁用模式设置可能会切换到较低的分辨率,使字体看起来更大。另一个选择是 KMSCON

强制模式和 EDID

如果您的原生分辨率没有自动配置,或者根本没有检测到显示设备,那么您的显示器可能没有发送 EDID 文件,或者发送的是错误的文件。内核会尝试捕获这种情况并设置一个最典型的分辨率。

如果您拥有显示器的 EDID 文件,只需显式强制执行它(见下文)。然而,通常人们无法直接获得正确的文件,因此有必要提取现有文件并进行修复,或者生成一个新文件。

通过遵循上游文档(另请参阅此处的简短指南),可以在内核编译期间为各种分辨率和配置生成新的 EDID 二进制文件。其他解决方案在本文中详细阐述:Creating and using edid.bin via xorg.conf。在大多数情况下,提取现有文件更容易,例如,如果您的显示器在 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 设置。但对于外部显示器,重新拔插即可看到效果。

如果在内核不在锁定模式 (lockdown mode)下,您可以使用 debugfs 而非内核命令行参数在启动后加载 EDID。如果您在连接器上更换显示器或仅为了测试,这非常有用。一旦您拥有如上所述的 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_override 的)新 EDID,这样您就无需物理拔插显示器或重启。

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

强制模式

注意 下面描述的方法在某种程度上是不完美的,因为例如 Xorg 不会考虑指定的分辨率,因此鼓励用户使用上述方法。但是,使用 video= 命令行指定分辨率对于所有 Wayland 合成器 都是有用的。

摘自nouveau wiki

可以在内核命令行中强制执行模式。不幸的是,video 命令行选项在 DRM 方面文档匮乏。关于如何使用它的片段可以在以下地址找到:

格式为:

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 协调视频时序 (CVT) 来计算视频模式时序,而不是从数据库中查找模式。
  • [R]: 在使用 CVT 时为数字显示启用缩减消隐(reduced blanking)计算。这会减少水平和垂直消隐间隔以节省带宽。
  • [-<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_top, margin_bottom, margin_left, margin_right (整数): 边距的像素数,通常用于处理电视上的过扫描 (overscan)。
  • 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

禁用模式设置

出于各种原因,您可能想要禁用 KMS。要禁用 KMS,请将 nomodeset 作为内核参数添加。更多信息请参阅 内核参数

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

注意 某些 Xorg 驱动程序在禁用 KMS 时将无法工作。详情请参阅特定驱动程序的 wiki 页面。

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.