最近想在本子上装个 virtualbox 跑个 winxp,旧本子,一直用的 32 位 Debian,内核经常更新,现在版本是 5.0.0-rc2+
apt install virtualbox virtualbox-dkms
安装完后,建立虚拟机的时候报错,说不能加载 vboxdrv 模块
dkms build
想着可能是因为内核新,所以 dkms 工作没做好,干脆跑一下 dkms build
。结果一跑,报错了:
# dkms build -m virtualbox -v 5.2.24
Kernel preparation unnecessary for this kernel. Skipping...
Building module:
cleaning build area...
make -j2 KERNELRELEASE=5.0.0-rc2+ -C /lib/modules/5.0.0-rc2+/build M=/var/lib/dkms/virtualbox/5.2.24/build........(bad exit status: 2)
Error! Bad return status for module build on kernel: 5.0.0-rc2+ (i686)
Consult /var/lib/dkms/virtualbox/5.2.24/build/make.log for more information.
查看一下 log /var/lib/dkms/virtualbox/5.2.24/build/make.log
...
CC [M] /var/lib/dkms/virtualbox/5.2.24/build/vboxdrv/r0drv/linux/memuserkernel-r0drv-linux.o
/var/lib/dkms/virtualbox/5.2.24/build/vboxdrv/r0drv/linux/memuserkernel-r0drv-linux.c: In function ‘VBoxHost_RTR0MemUserIsValidAddr’:
/var/lib/dkms/virtualbox/5.2.24/build/vboxdrv/r0drv/linux/memuserkernel-r0drv-linux.c:69:55: error: macro "access_ok" passed 3 arguments, but takes just 2
bool fRc = access_ok(VERIFY_READ, (void *)R3Ptr, 1);
^
/var/lib/dkms/virtualbox/5.2.24/build/vboxdrv/r0drv/linux/memuserkernel-r0drv-linux.c:69:16: error: ‘access_ok’ undeclared (first use in this function)
bool fRc = access_ok(VERIFY_READ, (void *)R3Ptr, 1);
^~~~~~~~~
/var/lib/dkms/virtualbox/5.2.24/build/vboxdrv/r0drv/linux/memuserkernel-r0drv-linux.c:69:16: note: each undeclared identifier is reported only once for each function it appears in
...
第一次遇到这个问题,说 access_ok
宏定义有问题。看了下 /var/lib/dkms/virtualbox/5.2.24/build/vboxdrv/r0drv/linux/the-linux-kernel.h
,已经 include 了 uaccess.h 文件,回头看内核源码,access_ok
确实只定义了两个参数。
纳闷,按理说 virtualbox 这么大个项目不应该出这种问题,内核 API 使用都不对。尝试各种杂乱的修改,最后想起看一下 git log,毕竟内核比较新;结果一查,找到了,commit 96d4f267e40f9509e8a66e2b39e8b95655617693
原来以后会逐渐放弃对 x86_32 的支持,修改主要是:
-#define access_ok(type, addr, size) \
+#define access_ok(addr, size)
upstream 对此做了修改,自己对 access_ok 不是很了解,不过既然 git log 里面提到了 type
参数不常用,干脆也把 virtualbox 代码中对 access_ok 的使用去掉这个参数。注意,修改的是 /usr/src/virtualbox-5.2.24/r0drv/linux/memuserkernel-r0drv-linux.c
;/var/lib/dkms/virtualbox/ 下的是符号链接,如果在这里修改后运行 dkms build 会把修改覆盖掉
66 RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr)
67 {
68 IPRT_LINUX_SAVE_EFL_AC();
69 /*bool fRc = access_ok(VERIFY_READ, (void *)R3Ptr, 1);*/
70 bool fRc = access_ok((void *)R3Ptr, 1); 去掉 type 参数
71 IPRT_LINUX_RESTORE_EFL_AC();
72 return fRc;
73 }
74 RT_EXPORT_SYMBOL(RTR0MemUserIsValidAddr);
修改完成后再 build 成功:
# dkms build -m virtualbox -v 5.2.24
Kernel preparation unnecessary for this kernel. Skipping...
Building module:
cleaning build area...
make -j2 KERNELRELEASE=5.0.0-rc2+ -C /lib/modules/5.0.0-rc2+/build M=/var/lib/dkms/virtualbox/5.2.24/build................
cleaning build area...
DKMS: build completed.
注意,/var/lib/dkms/virtualbox/5.2.24/
下多了子目录 /var/lib/dkms/virtualbox/5.2.24/5.0.0-rc2+
存放成功编译的 virtualbox模块
既然 build 完成了,就加载 vboxdrv 模块试试:
# modprobe vboxdrv
modprobe: FATAL: Module vboxdrv not found in directory /lib/modules/5.0.0-rc2+
手动试试:
# cd /var/lib/dkms/virtualbox/5.2.24/5.0.0-rc2+/i686/module
# ls
vboxdrv.ko vboxnetadp.ko vboxnetflt.ko vboxpci.ko
# insmod vboxdrv.ko
# lsmod | grep vboxdrv
vboxdrv 303104 0
dkms autoinstall
dkms 有个 autoinstall
子命令,执行 autoinstall 后就可以用 modprobe 加载模块了:
# dkms autoinstall
vboxdrv.ko:
Running module version sanity check.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-rc2+/updates/dkms/
vboxnetadp.ko:
Running module version sanity check.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-rc2+/updates/dkms/
vboxnetflt.ko:
Running module version sanity check.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-rc2+/updates/dkms/
vboxpci.ko:
Running module version sanity check.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-rc2+/updates/dkms/
depmod...........
DKMS: install completed.
再确认一下:
# modprobe vboxdrv
# modinfo vboxdrv
filename: /lib/modules/5.0.0-rc2+/updates/dkms/vboxdrv.ko
version: 5.2.24_Debian r128122 (0x00290001)
license: GPL
description: Oracle VM VirtualBox Support Driver
author: Oracle Corporation
srcversion: 254458DAEA255FA9AD97991
depends:
retpoline: Y
name: vboxdrv
vermagic: 5.0.0-rc2+ SMP mod_unload modversions 686
parm: force_async_tsc:force the asynchronous TSC mode (int)
这下 virtualbox 就可以用了