Page MenuHomeFreeBSD

D44306.id138470.diff
No OneTemporary

D44306.id138470.diff

diff --git a/sys/compat/linuxkpi/common/include/linux/module.h b/sys/compat/linuxkpi/common/include/linux/module.h
--- a/sys/compat/linuxkpi/common/include/linux/module.h
+++ b/sys/compat/linuxkpi/common/include/linux/module.h
@@ -32,6 +32,8 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/module.h>
+#include <sys/queue.h>
+#include <sys/linker.h>
#include <linux/list.h>
#include <linux/compiler.h>
@@ -51,7 +53,26 @@
#define MODULE_SUPPORTED_DEVICE(name)
#define MODULE_IMPORT_NS(_name)
+/*
+ * THIS_MODULE is used to differentiate modules on Linux. We currently
+ * completely stub out any Linux struct module usage, but THIS_MODULE is still
+ * used to populate the "owner" fields of various drivers. Even though we
+ * don't actually dereference these "owner" fields they are still used by
+ * drivers to check if devices/dmabufs/etc come from different modules. For
+ * example, during DRM GEM import some drivers check if the dmabuf's owner
+ * matches the dev's owner. If they match because they are both NULL drivers
+ * may incorrectly think two resources come from the same module.
+ *
+ * To handle this we specify an undefined symbol __this_linker_file, which
+ * will get special treatment from the linker when resolving. This will
+ * populate the usages of __this_linker_file with the linker_file_t of the
+ * module.
+ */
+#ifdef KLD_MODULE
+#define THIS_MODULE ((struct module *)&__this_linker_file)
+#else
#define THIS_MODULE ((struct module *)0)
+#endif
#define __MODULE_STRING(x) __stringify(x)
@@ -97,9 +118,33 @@
#define module_exit_order(fn, order) \
SYSUNINIT(fn, SI_SUB_OFED_MODINIT, (order), _module_run, (fn))
-#define module_get(module)
-#define module_put(module)
-#define try_module_get(module) 1
+/*
+ * linuxkpi modules use struct module *, but this is really the FreeBSD struct
+ * module instead of a linux one. These modules are populated by THIS_MODULE, which
+ * is a macro that's really a casted pointer to the linker file for this module. So
+ * to bump the reference count we cast it to a linker file, and then up the file's
+ * refcount
+ */
+static inline void
+module_get(struct module *module)
+{
+ linker_file_t file = (linker_file_t)module;
+ file->refs++;
+}
+
+static inline void
+module_put(struct module *module)
+{
+ linker_file_t file = (linker_file_t)module;
+ file->refs--;
+}
+
+static inline int
+try_module_get(struct module *module)
+{
+ module_get(module);
+ return 1;
+}
#define postcore_initcall(fn) module_init(fn)
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -906,6 +906,20 @@
KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%p, name=%s, deps=%d\n",
file, name, deps));
+ /*
+ * Treat the __this_linker_file as a special symbol. This is a global that
+ * linuxkpi uses to populate the THIS_MODULE value. In this case we can
+ * simply return the linker_file_t.
+ *
+ * Modules compiled statically into the kernel are assigned NULL.
+ */
+ if (strcmp(name, "__this_linker_file") == 0) {
+ address = file == linker_kernel_file ? NULL : (caddr_t)file;
+ KLD_DPF(SYM, ("linker_file_lookup_symbol: resolving special symbol"
+ " __this_linker_file to %p\n", address));
+ return (address);
+ }
+
if (LINKER_LOOKUP_SYMBOL(file, name, &sym) == 0) {
LINKER_SYMBOL_VALUES(file, sym, &symval);
if (symval.value == 0)
diff --git a/sys/sys/linker.h b/sys/sys/linker.h
--- a/sys/sys/linker.h
+++ b/sys/sys/linker.h
@@ -44,6 +44,11 @@
* Object representing a file which has been loaded by the linker.
*/
typedef struct linker_file* linker_file_t;
+/*
+ * Special symbol which will be replaced by a reference to the linker_file_t
+ * of the module it is used in.
+ */
+extern linker_file_t __this_linker_file;
typedef TAILQ_HEAD(, linker_file) linker_file_list_t;
typedef caddr_t linker_sym_t; /* opaque symbol */

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 25, 5:32 AM (20 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32111303
Default Alt Text
D44306.id138470.diff (3 KB)

Event Timeline