Debian lenny で nvidia-kernel-source がビルドできない人向けの patch を作った

Xen の paravirtualization 関係で定義されている paravirt_ops というシンボルがありまして,nvidia.ko はこのシンボルをリンクします.ところが,この関係が GPL 違反として modpost さんに起こられてしまうので nvidia.ko をビルドできません.


まずは,GPL 違反を検知しないように,以下で引用した手順で kbuild を作り直します.

1. Rebuild the linux-kbuild-2.6.20 .deb:
   a. apt-get update
   b. apt-get build-dep linux-kbuild-2.6.20
      As user:
   c. mkdir linux-kbuild-2.6.20-build
   d. cd linux-kbuild-2.6.20-build
   e. apt-get source linux-kbuild-2.6.20

      The linux-kbuild-2.6.20 sources will be downloaded and unpacked into a folder.
      Cd to that folder, then:
   f. change
linux-kbuild-2.6.20-build/linux-kbuild-2.6-2.6.20/scripts/mod/mod.c and delete lines 1197+1198.
   g. dpkg-buildpackage -uc -us -rfakeroot (the .deb is created) 
http://www.nabble.com/HOWTO:2.6.20-1-k7-+-nvidia-t3679809.html

こうして,作り直した linux-kbuild-2.6.x を dpkg -i でインストールすれば,ひとまず module-assistant 中のコンパイルエラーは出なくなります.

ところがです.この状態で作成した nvidia.ko は Unknown symbol paravirt_ops と言われて insmod することができません.せっかく作れたのに残念です.

上で引用したページを見ると,その後にも手順があります.paravirt_ops への参照を主導で解決させるための手順です.この手順をなんとか Makefile に侵入させることに成功したので,nvidia-kernel-source 全体のパッチを作っておきました.次のような手順でパッチを適用した nvidia-kernel-source.tar.gz を作り直してください.

~$ tar xzf /usr/src/nvidia-kernel-source.tar.gz
~$ cd modules
~/modules$ patch -p1 < ~/nvidia-kernel-source+paravirt_ops.patch
~/modules$ cd ..
~$ tar cf - modules | gzip -9 > nvidia-kernel-source.tar.gz
~$ sudo cp nvidia-kernel-source.tar.gz /usr/src

では,以下,件のパッチです.ホームディレクトリ直下に nvidia-kernel-source+paravirt_ops.patch という名前で保存すると,上記手順通りにできます.

diff -uNr modules.orig/nvidia-kernel/debian/patches/00list modules/nvidia-kernel/debian/patches/00list
--- modules.orig/nvidia-kernel/debian/patches/00list	2007-07-03 10:00:09.000000000 +0900
+++ modules/nvidia-kernel/debian/patches/00list	2007-09-15 18:48:58.000000000 +0900
@@ -2,3 +2,4 @@
 02_pcialias
 03_pci_get_class
 04_minion
+05_paravirt_list
diff -uNr modules.orig/nvidia-kernel/debian/patches/05_paravirt_ops modules/nvidia-kernel/debian/patches/05_paravirt_ops
--- modules.orig/nvidia-kernel/debian/patches/05_paravirt_ops	1970-01-01 09:00:00.000000000 +0900
+++ modules/nvidia-kernel/debian/patches/05_paravirt_ops	2007-09-15 18:56:20.000000000 +0900
@@ -0,0 +1,44 @@
+#!/bin/sh -e
+
+# Patch from accumulated from http://www.minion.de/files/1.0-6629/
+
+if [ $# -lt 1 ]; then
+    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+    exit 1
+fi
+	
+patch_opts="-f -N --no-backup-if-mismatch -p2"
+
+echo $1
+
+case "$1" in
+	-patch) patch $patch_opts -p0 < $0;;
+	-unpatch) patch $patch_opts -p0 -R < $0;;
+	*)
+     		echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
+		exit 1;;
+esac
+
+exit 0
+
+@DPATCH@
+
+--- nv/Makefile.kbuild~	2007-07-03 10:00:09.000000000 +0900
++++ nv/Makefile.kbuild	2007-09-15 18:42:16.000000000 +0900
+@@ -301,6 +301,7 @@
+ # the "package-install" target below.
+ #
+ 
++PARAVIRT_OPS = $(shell grep "D paravirt_ops" /boot/System.map-$(KERNEL_UNAME) | colrm 9)
+ module: cc-version-check xen-sanity-check rivafb-sanity-check nvidiafb-sanity-check
+ 	@if [ -z "$(PATCHLEVEL)" ]; then \
+ 	  echo "failed to determine PATCHLEVEL!"; \
+@@ -314,6 +315,8 @@
+ 	if ! [ -f $(MODULE_OBJECT) ]; then \
+ 	  echo "$(MODULE_OBJECT) failed to build!"; \
+ 	  exit 1; \
++	else \
++	  $(LD) -m elf_i386 --defsym paravirt_ops=0x$(PARAVIRT_OPS) -r -o nvidia.ko nvidia.o nvidia.mod.o; \
+ 	fi
+ 
+ #
diff -uNr modules.orig/nvidia-kernel/debian/rules modules/nvidia-kernel/debian/rules
--- modules.orig/nvidia-kernel/debian/rules	2007-07-03 10:00:09.000000000 +0900
+++ modules/nvidia-kernel/debian/rules	2007-09-15 18:54:31.000000000 +0900
@@ -106,6 +106,7 @@
 		dpatch apply 02_pcialias ; \
                	dpatch status 02_pcialias >>patch-stamp ; \
 	     fi ; \
+	     dpatch apply 05_paravirt_ops ; \
 	fi
 	
 	if [  $(PATCHLEVEL) = 4  ]; then \