如何在 Ubuntu 17.10 x86_64 上使用 LLVM/clang 和 Nvidia 390.25 x86_64 驱动程序构建 4.15.7 内核?

如何在 Ubuntu 17.10 x86_64 上使用 LLVM/clang 和 Nvidia 390.25 x86_64 驱动程序构建 4.15.7 内核?

这是关于我为我的 Nvidia GTX GeForce 860M 显卡启动Ubuntu 17.10 x86_64 clang-built Linux 4.15.7 kernel(目前最新的稳定版本)和专有Nvidia 390.25(目前最新的)驱动程序的成功经验。


问题

Linux 内核 4.15.7 是使用clang主机和目标编译器构建的,并根据默认内核配置与模块一起安装。我不得不禁用模块,因为它有不支持的exofs非标准“嵌入在结构中的 VLA” 。然后,我还在从其专有安装程序中提取驱动程序源代码后对其进行了编译 - 我不得不忽略编译器版本不匹配伪警告,因为内核头文件包含线程模型和平台信息,而 Nvidia 驱动程序脚本检查仅得出版本。clangNvidia 390.25

安装这样构建的 Nvidia 驱动程序模块后,我重新启动了系统,但 Ubuntu 17.10 启动没有完成 - 它卡在了Loading ... 4.15.7

为了进一步隔离内核与 gcc/clang 以及 Nvidia 驱动程序与 gcc/clang 之间的兼容性问题(如果有的话),使用 编译了 Linux 内核 4.15.7,使用gccNvidia 390.25 驱动程序clang,反之亦然。对于第一个,启动过程通过了该Loading ... 4.15.7阶段并转移到某个systemd服务,但卡在那里。对于第二个,它再次卡在该Loading ... 4.15.7阶段。系统journalctl/logs 没有多大帮助。

答案1

阶段1:由于之前使用过 Qemu/Kvm,我想找到启动 clang 构建的内核时的实际失败点。因此,我尝试在 Qemu/kvm busyboxx86_64 上使用 x86_64 默认配置启动 clang 构建的 Linux 内核 4.15.7 映像,并为根文件系统 (initrd) 启动 clang 构建的 x86_64。这很有效。我得到了 shell,busybox实用程序正在运行等等。

在主机 Ubuntu 17.10 x86_64 上:

$ strings -a defconfig-linux-4.15.7/linux-4.15.7/vmlinux | grep "clang version" | head -1
Linux version 4.15.7 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #1 SMP Fri Mar 2 21:15:24 PST 2018

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 17.10
Release:    17.10
Codename:   artful

$ clang -v
clang version 5.0.0-3 (tags/RELEASE_500/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

在 Qemu/kvm 客户机中,Linux 内核 4.15.7(x86_64 defconfig)/Busybox 64 位:

/ # cat /proc/version 
Linux version 4.15.7 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #1 SMP Fri Mar 2 21:15:24 PST 2018
/ # 

/ # uname -arv
Linux (none) 4.15.7 #1 SMP Fri Mar 2 21:15:24 PST 2018 x86_64 GNU/Linux
/ # 
/ # 
/ # strings -a bin/busybox | grep "clang version"
clang version 5.0.0-3 (tags/RELEASE_500/final)
/ # 
/ # 
/ # dmesg | grep QEMU
[    0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
[    0.024000] smpboot: CPU0: Intel QEMU Virtual CPU version 2.5+ (family: 0x6, model: 0x6, stepping: 0x3)
[    0.337415] ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100
[    0.339072] scsi 1:0:0:0: CD-ROM            QEMU     QEMU DVD-ROM     2.5+ PQ: 0 ANSI: 5
/ # 
/ # 

第二阶段:有了上述使用 defconfig 内核的初步成功,我采用了主机 Ubuntu 17.10 内核配置并重建了 Linux 内核 4.15.7 映像。这样,我保留了 busybox 的其余部分,并尝试像之前一样在 Qemu/kvm 上启动它们 - 但这没有奏效。结果为general protection faultskernel oops- kernel panic。我查看了内核堆栈转储。

我注意到第一个问题出在kernel irq work tick逻辑上。然后下一个问题与kernel live instruction update逻辑有关。我对这两个问题都进行了研究。重建了内核。再次尝试使用 Qemu/kvm - 获得了 shell,这次没有崩溃。下一步是安装内核模块和 Nvidia 驱动程序模块。我这样做了,但这次,使用所有的 Ubuntu 内核模块和 Nvidia 驱动程序模块,Qemu/kvm 显示了一些彩色像素并卡住了 - 主要是由于主机硬件和客户机虚拟化硬件之间的差异。所以,我只想尝试使用 Nvidia 驱动程序,因为它是我在主机上用于图形的驱动程序,因此是主要关注点。因此,我在 busybox rootfs 中包含(未安装)Nvidia 驱动程序模块,并尝试像往常一样启动 Qemu/kvm - 这次,由于 rootfs-not-found 导致内核崩溃,尽管有一个 rootfs。

因此,我尝试将所有 Nvidia 驱动程序模块压缩到一个 zip 中,并将其包含在 rootfs 中。但是,当我尝试使用 Qemu/kvm 客户机提取 zip 时,出现了no space left on device。因此,我尝试构建一个 10G 虚拟 qemu 磁盘并在该磁盘中安装 rootfs 以解决空间问题 - 但是,过了一段时间,我取消了这一计划,因为我更感兴趣的是将 clang 构建的 Nvidia 驱动程序应用于真实系统硬件,而不是模拟的 Qemu/kvm 环境(我知道它没有通过 GPU 直通提供的真正 Nvidia 显卡,因此在我尝试在主机的真实系统硬件/显卡上测试 clang 构建的 Nvidia 390.25 驱动程序之前,我还是尝试了一下,只是为了看看 clang 构建的 Nvidia 驱动程序在加载时是否在 Qemu/kvm 中出现任何问题)。

在 Qemu/kvm 客户机中,Linux 内核 4.15.7(主机 Ubuntu 17.10 x86_64 配置)/Busybox64 位:

/ # cat /proc/version 
Linux version 4.15.7 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #20 SMP Sat Mar 3 20:46:15 PST 2018
/ # 
/ # 
/ # uname -arv
Linux (none) 4.15.7 #20 SMP Sat Mar 3 20:46:15 PST 2018 x86_64 GNU/Linux
/ # 
/ # 
/ # 
/ # dmesg | grep QEMU
[    0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
[    0.024000] smpboot: CPU0: Intel QEMU Virtual CPU version 2.5+ (family: 0x6, model: 0x6, stepping: 0x3)
[    0.340776] ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100
[    0.343135] scsi 1:0:0:0: CD-ROM            QEMU     QEMU DVD-ROM     2.5+ PQ: 0 ANSI: 5
/ # 
/ # strings -a bin/busybox | grep "clang version"
clang version 5.0.0-3 (tags/RELEASE_500/final)
/ # 

第 3 阶段及成功:由于我的主要和实际目标是我的主机(Ubuntu 17.10),我直接在主机系统上安装了这个 clang 构建的内核(解决了上述问题)和 Nvidia 390.25 驱动程序。重新启动我的系统。砰!我使用 clang 构建的 4.15.7 内核和 clang 构建的 Nvidia 390.25 驱动程序启动并运行了我的 Ubuntu 17.10 x86_64,没有任何问题。

在主机 Ubuntu 17.10 x86_64 上,使用 clang 构建的 Linux 内核 4.15.7 和 clang 构建的 Nvidia 390.25 GeForce GTX 860M 专有驱动程序 - 我的成功研究和经验:

$ dmesg | grep clang
[    0.000000] Linux version 4.15.7 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #20 SMP Sat Mar 3 20:46:15 PST 2018

$ cat /proc/version 
Linux version 4.15.7 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #20 SMP Sat Mar 3 20:46:15 PST 2018

$ uname -arv
Linux exp 4.15.7 #20 SMP Sat Mar 3 20:46:15 PST 2018 x86_64 x86_64 x86_64 GNU/Linux

$ nvidia-smi
Sun Mar  4 18:15:39 2018       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.25                 Driver Version: 390.25                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 860M    Off  | 00000000:01:00.0 Off |                  N/A |
| N/A   54C    P0    N/A /  N/A |    370MiB /  4046MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

exp@exp:~$ dmesg | grep NVIDIA | grep 390.25
[   17.643496] NVRM: loading NVIDIA UNIX x86_64 Kernel Module  390.25  Wed Jan 24 20:02:43 PST 2018 (using threaded interrupts)
[   17.689835] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms  390.25  Wed Jan 24 19:29:37 PST 2018

$ lsmod | grep nvidia
nvidia_uvm            815104  0 
nvidia_drm             24576  2 
nvidia_modeset       1097728  5 nvidia_drm
nvidia              14352384  334 nvidia_uvm,nvidia_modeset
ipmi_msghandler        61440  2 nvidia,ipmi_devintf
drm                   454656  6 nvidia_drm,i915,drm_kms_helper

# clang-built Linux kernel 4.15.7 image and Nvidia 390.25 driver modules having clang compiler specific
# metadata within them.
#

$ eclang /lib/modules/4.15.7/build/vmlinux | grep "Linux"
++ strings -a /lib/modules/4.15.7/build/vmlinux
++ grep clang
Linux version 4.15.7 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #20 SMP Sat Mar 3 20:46:15 PST 2018
exp@exp:~$ eclang /lib/modules/4.15.7/kernel/drivers/video/nvidia.ko | head -1
++ strings -a /lib/modules/4.15.7/kernel/drivers/video/nvidia.ko
++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)

$ eclang /lib/modules/4.15.7/kernel/drivers/video/nvidia-drm.ko | head -1
++ strings -a /lib/modules/4.15.7/kernel/drivers/video/nvidia-drm.ko
++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)

$ eclang /lib/modules/4.15.7/kernel/drivers/video/nvidia-uvm.ko | head -1
++ strings -a /lib/modules/4.15.7/kernel/drivers/video/nvidia-uvm.ko
++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)

$ eclang /lib/modules/4.15.7/kernel/drivers/video/nvidia-modeset.ko | head -1
++ strings -a /lib/modules/4.15.7/kernel/drivers/video/nvidia-modeset.ko
++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)

# DMI specific hardware information - verifies and confirms the physical hardware used
# instead of QEMU or any other virtual platform for running clang-built kernel and
# Nvidia 390.25 driver.
#

$ sudo dmidecode -t bios | grep Vendor
    Vendor: LENOVO

$ sudo dmidecode -t system | grep "Manufacturer:\|Version"
    Manufacturer: LENOVO
    Version: Lenovo Y50-70 Touch

$ sudo dmidecode -t processor | grep Version
    Version: Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz

注 1:对于所有详细的日志(来自每个阶段),你可以在这里阅读我对 LLVM-Clang/Linux 内核问题的回答:使用 LLVM/clang 构建 Linux 内核

笔记2:在我看来,clang 的警告比 gcc 更繁琐。但是,目前,为了让内核/nvidia 驱动程序启动并运行,我忽略了它们,看看它们是否不严重(到目前为止它们并不严重)。


更新1:为了通用性,我用后续内核版本(截至 2018 年 3 月中旬是最新版本)和最新的 Nvidia 显卡 GTX GeForce 驱动程序 v390.42(截至 2018 年 3 月中旬是最新版本)重复了上述操作 - 它们均在更新内核 4.15.11 代码中的 IRQ 工作滴答逻辑和实时指令更新逻辑后使用与之前相同的方法构建,4.15.10就像我对 4.15.7 所做的那样,最后将它们都直接安装在我的系统硬件上(这次没有进行 Qemu/kvm 实验,因为早期的 4.15.7 内核在处理 IRQ 工作滴答逻辑和实时指令更新逻辑后已经成功启动)。这样,Ubuntu 17.10 x86_64 再次成功出现在我的系统硬件上,在 clang 构建的内核 4.15.11 和 clang 构建的最新 Nvidia 驱动程序 v390.42 上,就像之前在内核 4.15.7 和 Nvidia 驱动程序 v390.25 的情况下一样。4.15.11clang

以下是在 clang 构建的最新 v4.15.11 内核和 clang 构建的最新 Nvidia 驱动程序 v390.42 场景上运行 Ubuntu 17.10 x86_64 的详细信息:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 17.10
Release:    17.10
Codename:   artful

$ cat /proc/version 
Linux version 4.15.11 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #2 SMP Tue Mar 20 05:37:06 PDT 2018

$ eclang /lib/modules/4.15.11/build/vmlinux | grep Linux
++ strings -a /lib/modules/4.15.11/build/vmlinux
++ grep clang
Linux version 4.15.11 (exp@exp) (clang version 5.0.0-3 (tags/RELEASE_500/final)) #2 SMP Tue Mar 20 05:37:06 PDT 2018

$ sudo dmidecode -t system | grep "Manufacturer:\|Version"
    Manufacturer: LENOVO
    Version: Lenovo Y50-70 Touch

$ dmesg | grep NVIDIA
[   19.491452] nvidia: module license 'NVIDIA' taints kernel.
[   19.499360] NVRM: loading NVIDIA UNIX x86_64 Kernel Module  390.42  Sat Mar  3 04:10:22 PST 2018 (using threaded interrupts)
[   19.542830] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms  390.42  Sat Mar  3 03:30:48 PST 2018

$ nvidia-smi
Tue Mar 20 22:15:00 2018       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.42                 Driver Version: 390.42                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 860M    Off  | 00000000:01:00.0 Off |                  N/A |
| N/A   52C    P8    N/A /  N/A |    451MiB /  4046MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

$ glxinfo | grep NVIDIA
server glx vendor string: NVIDIA Corporation
client glx vendor string: NVIDIA Corporation
OpenGL vendor string: NVIDIA Corporation
OpenGL core profile version string: 4.5.0 NVIDIA 390.42
OpenGL core profile shading language version string: 4.50 NVIDIA
OpenGL version string: 4.6.0 NVIDIA 390.42
OpenGL shading language version string: 4.60 NVIDIA
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 390.42

$ lsmod | grep nv
nvidia_uvm            815104  0 
nvidia_drm             24576  2 
nvidia_modeset       1105920  5 nvidia_drm
nvidia              14368768  334 nvidia_uvm,nvidia_modeset
ipmi_msghandler        61440  2 nvidia,ipmi_devintf
drm                   454656  6 nvidia_drm,i915,drm_kms_helper

$ ~/nvidia-driver-compiler.sh 
++ head -1
+++ uname -r
++ eclang /lib/modules/4.15.11/kernel/drivers/video/nvidia.ko
+++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia.ko
+++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)
++ head -1
+++ uname -r
++ eclang /lib/modules/4.15.11/kernel/drivers/video/nvidia-drm.ko
+++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia-drm.ko
+++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)
+++ uname -r
++ head -1
++ eclang /lib/modules/4.15.11/kernel/drivers/video/nvidia-modeset.ko
+++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia-modeset.ko
+++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)
+++ uname -r
++ head -1
++ eclang /lib/modules/4.15.11/kernel/drivers/video/nvidia-uvm.ko
+++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia-uvm.ko
+++ grep clang
clang version 5.0.0-3 (tags/RELEASE_500/final)

$ ~/nvidia_driver_modules_version.sh 
++ grep '^version='
+++ uname -r
++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia.ko
version=390.42
++ grep '^version='
+++ uname -r
++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia-drm.ko
version=390.42
++ grep '^version='
+++ uname -r
++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia-uvm.ko
+++ uname -r
++ grep '^version='
++ strings -a /lib/modules/4.15.11/kernel/drivers/video/nvidia-modeset.ko
version=390.42

相关内容