升级到 4.4.0-116 内核后登录循环:图形登录屏幕 -> 黑屏 -> 图形登录屏幕

升级到 4.4.0-116 内核后登录循环:图形登录屏幕 -> 黑屏 -> 图形登录屏幕

无法登录桌面环境apt upgrade && reboot:输入密码后屏幕闪烁变为黑屏并返回登录屏幕。通过终端 ( Ctrl+Alt+F1) 登录可以正常工作。

/var/log/Xorg.0.log说:

(EE) NVIDIA:无法初始化 NVIDIA 内核模块。请参阅
(EE) NVIDIA:系统内核日志以了解更多错误消息,以及
(EE) NVIDIA:查阅 NVIDIA README 以了解详细信息。
(EE) 未检测到任何设备。

$ dmesg说:

nvidia:版本魔法'4.4.0-116-generic SMP mod_unload modversions'应该是'4.4.0-116-generic SMP mod_unload modversions retpoline'

尝试手动加载 nvidia 驱动程序失败:

$ sudo modprobe nvidia
modprobe: ERROR: could not insert 'nvidia': Exec format error

有关的:内核升级后 VirtualBox 无法启动

答案1

问题在于 gcc 版本不支持 retpoline (什么是 retpoline 以及它是如何工作的?). 查看Ubuntu Bug:2 月 21 日的 4.4.0-116 内核更新破坏了 Nvidia 驱动程序(14.04 和 16.04)

就我而言,清除ppa:ubuntu-toolchain-r/test安装默认 gcc 版本并使用 DKMS 重建 nvidia 模块(通过重新安装 4.4.0-116 内核)可以解决问题。请参阅@cjjefcoat 在错误跟踪器上发布的说明

ppa:ubuntu-toolchain-r/test通过清除版本恢复默认 gcc :

$ sudo apt-get install ppa-purge
$ sudo ppa-purge ppa:ubuntu-toolchain-r/test

gcc 版本(在 Ubuntu 16.04 上)具有 retpoline 支持:

$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

重新安装内核:

$ sudo apt-get purge linux-headers-4.4.0-116 linux-headers-4.4.0-116-generic linux-image-4.4.0-116-generic linux-image-extra-4.4.0-116-generic linux-signed-image-4.4.0-116-generic
$ sudo apt-get install linux-generic linux-signed-generic

检查 nvidia 模块:

$ modinfo nvidia_xxx -k 4.4.0-116-generic | grep vermagic
vermagic:       4.4.0-116-generic SMP mod_unload modversions retpoline 

用你的版本替换_xxx--只需在之后按TAB即可modinfo nvidia

retpoline应该在输出中。

之后reboot成功完成。


如果您已经有兼容的 gcc 版本,则可以使用dkms命令重建 nvidia 模块,而无需重新安装内核:

# dkms remove nvidia-xxx/yyy.zzz -k 4.4.0-116-generic
# dkms install nvidia-xxx/yyy.zzz -k 4.4.0-116-generic

我决定重新安装内核,以更新使用错误的 gcc 版本通过 DKMS 重新构建的所有模块。

答案2

我不知道 Ask Ubuntu 是否是解决这些问题的正确地方,但是——正如我需要新的g++并且仍定期更新内核 — — 我编写了一个 bash 脚本,用于 (1) 清除ppa:ubuntu-toolchain-r/test、(2) 为选定的内核重建所有 DKMS 模块、(3) 安装g++-7回 — —这个答案

该脚本按“原样”提供,不提供任何形式的担保。
除非您理解每一行的含义,否则请不要使用它。
它的目的是节省您手动完成的事情的时间(而不是做您不理解的“魔术”)。

剧本:

#!/bin/bash -e

for list in /etc/apt/sources.list.d/ubuntu-toolchain-r*.list; do
    sudo cp -a "$list" "$list.backup"
    echo "Backed up $list to $list.backup"
done
sudo ppa-purge ppa:ubuntu-toolchain-r/test

readarray -t kernels < <(ls -1 /lib/modules)
echo "Kernels: ${kernels[*]}"
for kernel in "${kernels[@]}"; do
    dkms_modules=($(sudo dkms status -k "$kernel" | sed -r 's#^([^,]+), ([^,]+), .*$#\1/\2#'))
    while true; do
        echo
        read -p "Reinstall DKMS-modules (${dkms_modules[*]}) on kernel $kernel? [Y/n] " choice
        if [ "${choice^^}" = N ]; then continue 2; fi
        if [ "${choice^^}" = Y ] || [ -z "$choice" ]; then break; fi
        echo "Expected 'y', 'n' or '', but got '$choice'"
    done
    echo
    for dkms_module in "${dkms_modules[@]}"; do
        sudo dkms remove -k "$kernel" "$dkms_module"
        sudo dkms install -k "$kernel" "$dkms_module"
    done
    echo
    for module in /lib/modules/"$kernel"/updates/dkms/*.ko; do
        vermagic="$(modinfo -F vermagic $module)"
        echo -n "Vermagic for $(basename ${module%.ko}): $vermagic -- "
        fgrep -q retpoline <<<"$vermagic" && echo ok || echo "'retpoline' is missing!!!"
    done
done

for list in /etc/apt/sources.list.d/ubuntu-toolchain-r*.list; do
    sudo mv "$list.backup" "$list"
    echo "Restored $list from $list.backup"
done
sudo apt update
sudo apt install g++-7
sudo apt dist-upgrade

相关内容