[PATCH] Automatic kernel version module dependencies..

John Baldwin jhb at freebsd.org
Fri Feb 8 15:33:20 PST 2008

So one of the things that people run into periodically are problems with 
mismatched kernels and modules.  My understanding of our kernel module ABI 
compatibility is that if you build a module on in a X.Y build environment the 
module should work fine for all kernels with version X.Z where Z >= Y.  In 
concrete terms, a module built on a 6.2 system is not guaranteed to work on a 
6.1 kernel, a 5.2 kernel, or a 7.0 kernel.  However, it should work fine on 
6.2, 6.3, etc.

The patch below implements this policy by create a 'kernel' module version 
based on __FreeBSD_version.  It then adds a version dependency on 'kernel' in 
every kernel module that requires a version range starting with the current 
__FreeBSD_version and ending with the maximum __FreeBSD_version value for the 
current branch.  This does seem to work in that a kernel module compiled with 
artificial values of __FreeBSD_version refuses to load when it violates the 
rule above (too old or wrong branch).  One thing this doesn't fix is that 
right now the error from the kernel linker is simply that "kernel could not 
be found" or some such.  It might be nicer if the error could be "module 
requires kernel version X to Y, but only Z was found", but that would be a 
separate patch.

--- //depot/vendor/freebsd/src/sys/kern/kern_module.c	2007/12/06 23:12:58
+++ //depot/user/jhb/acpipci/kern/kern_module.c	2008/02/07 18:59:28
@@ -414,6 +414,8 @@
 	return (error);
+MODULE_VERSION(kernel, __FreeBSD_version);
 #ifdef COMPAT_IA32
 #include <sys/mount.h>
 #include <sys/socket.h>
--- //depot/vendor/freebsd/src/sys/sys/module.h	2006/04/17 19:46:13
+++ //depot/user/jhb/acpipci/sys/module.h	2008/02/07 22:11:55
@@ -114,7 +114,20 @@
 	MODULE_METADATA(_md_##module##_on_##mdepend, MDT_DEPEND,	\
 	    &_##module##_depend_on_##mdepend, #mdepend)
+ * Every kernel has a 'kernel' module with the version set to
+ * __FreeBSD_version.  We embed a MODULE_DEPEND() inside every module
+ * that depends on the 'kernel' module.  It uses the current value of
+ * __FreeBSD_version as the minimum and preferred versions.  For the
+ * maximum version it rounds the version up to the end of its branch
+ * (i.e. M99999 for M.x).  This allows a module built on M.x to work
+ * on M.y systems where y >= x, but fail on M.z systems where z < x.
+ */
+#define	MODULE_KERNEL_MAXVER	(roundup(__FreeBSD_version, 100000) - 1)
 #define	DECLARE_MODULE(name, data, sub, order)				\
+	MODULE_DEPEND(name, kernel, __FreeBSD_version,			\
+	    __FreeBSD_version, MODULE_KERNEL_MAXVER);			\
 	MODULE_METADATA(_md_##name, MDT_MODULE, &data, #name);		\
 	SYSINIT(name##module, sub, order, module_register_init, &data)	\
 	struct __hack

John Baldwin

More information about the freebsd-arch mailing list