Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jan 2009 16:28:15 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org
Subject:   svn commit: r187536 - in stable/6/sys: . compat/freebsd32 compat/ia32
Message-ID:  <200901211628.n0LGSFev083048@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed Jan 21 16:28:15 2009
New Revision: 187536
URL: http://svn.freebsd.org/changeset/base/187536

Log:
  MFC: Add support for installing 32-bit system calls from kernel modules.

Modified:
  stable/6/sys/   (props changed)
  stable/6/sys/compat/freebsd32/freebsd32_misc.c
  stable/6/sys/compat/freebsd32/freebsd32_util.h
  stable/6/sys/compat/ia32/ia32_sysvec.c

Modified: stable/6/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/6/sys/compat/freebsd32/freebsd32_misc.c	Wed Jan 21 16:14:43 2009	(r187535)
+++ stable/6/sys/compat/freebsd32/freebsd32_misc.c	Wed Jan 21 16:28:15 2009	(r187536)
@@ -2298,3 +2298,83 @@ freebsd32_xxx(struct thread *td, struct 
 }
 
 #endif
+
+int
+syscall32_register(int *offset, struct sysent *new_sysent,
+    struct sysent *old_sysent)
+{
+	if (*offset == NO_SYSCALL) {
+		int i;
+
+		for (i = 1; i < SYS_MAXSYSCALL; ++i)
+			if (freebsd32_sysent[i].sy_call ==
+			    (sy_call_t *)lkmnosys)
+				break;
+		if (i == SYS_MAXSYSCALL)
+			return (ENFILE);
+		*offset = i;
+	} else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
+		return (EINVAL);
+	else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
+	    freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
+		return (EEXIST);
+
+	*old_sysent = freebsd32_sysent[*offset];
+	freebsd32_sysent[*offset] = *new_sysent;
+	return 0;
+}
+
+int
+syscall32_deregister(int *offset, struct sysent *old_sysent)
+{
+
+	if (*offset)
+		freebsd32_sysent[*offset] = *old_sysent;
+	return 0;
+}
+
+int
+syscall32_module_handler(struct module *mod, int what, void *arg)
+{
+	struct syscall_module_data *data = (struct syscall_module_data*)arg;
+	modspecific_t ms;
+	int error;
+
+	switch (what) {
+	case MOD_LOAD:
+		error = syscall32_register(data->offset, data->new_sysent,
+		    &data->old_sysent);
+		if (error) {
+			/* Leave a mark so we know to safely unload below. */
+			data->offset = NULL;
+			return error;
+		}
+		ms.intval = *data->offset;
+		MOD_XLOCK;
+		module_setspecific(mod, &ms);
+		MOD_XUNLOCK;
+		if (data->chainevh)
+			error = data->chainevh(mod, what, data->chainarg);
+		return (error);
+	case MOD_UNLOAD:
+		/*
+		 * MOD_LOAD failed, so just return without calling the
+		 * chained handler since we didn't pass along the MOD_LOAD
+		 * event.
+		 */
+		if (data->offset == NULL)
+			return (0);
+		if (data->chainevh) {
+			error = data->chainevh(mod, what, data->chainarg);
+			if (error)
+				return (error);
+		}
+		error = syscall32_deregister(data->offset, &data->old_sysent);
+		return (error);
+	default:
+		error = EOPNOTSUPP;
+		if (data->chainevh)
+			error = data->chainevh(mod, what, data->chainarg);
+		return (error);
+	}
+}

Modified: stable/6/sys/compat/freebsd32/freebsd32_util.h
==============================================================================
--- stable/6/sys/compat/freebsd32/freebsd32_util.h	Wed Jan 21 16:14:43 2009	(r187535)
+++ stable/6/sys/compat/freebsd32/freebsd32_util.h	Wed Jan 21 16:28:15 2009	(r187536)
@@ -28,14 +28,16 @@
  * $FreeBSD$
  */
 
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
+#ifndef _COMPAT_FREEBSD32_FREEBSD32_UTIL_H_
+#define _COMPAT_FREEBSD32_FREEBSD32_UTIL_H_
 
+#include <sys/cdefs.h>
 #include <sys/exec.h>
 #include <sys/sysent.h>
-#include <sys/cdefs.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
 
 struct freebsd32_ps_strings {
 	u_int32_t ps_argvstr;	/* first of 0 or more argument strings */
@@ -50,3 +52,35 @@ struct freebsd32_ps_strings {
 
 #define FREEBSD32_PS_STRINGS	\
 	(FREEBSD32_USRSTACK - sizeof(struct freebsd32_ps_strings))
+
+extern struct sysent freebsd32_sysent[];
+
+#define SYSCALL32_MODULE(name, offset, new_sysent, evh, arg)   \
+static struct syscall_module_data name##_syscall32_mod = {     \
+       evh, arg, offset, new_sysent, { 0, NULL }               \
+};                                                             \
+                                                               \
+static moduledata_t name##32_mod = {                           \
+       #name,                                                  \
+       syscall32_module_handler,                               \
+       &name##_syscall32_mod                                   \
+};                                                             \
+DECLARE_MODULE(name##32, name##32_mod, SI_SUB_SYSCALLS, SI_ORDER_MIDDLE)
+
+#define SYSCALL32_MODULE_HELPER(syscallname)            \
+static int syscallname##_syscall32 = FREEBSD32_SYS_##syscallname; \
+static struct sysent syscallname##_sysent32 = {         \
+    (sizeof(struct syscallname ## _args )               \
+     / sizeof(register_t)),                             \
+    (sy_call_t *)& syscallname                          \
+};                                                      \
+SYSCALL32_MODULE(syscallname,                           \
+    & syscallname##_syscall32, & syscallname##_sysent32,\
+    NULL, NULL);
+
+int    syscall32_register(int *offset, struct sysent *new_sysent,
+	    struct sysent *old_sysent);
+int    syscall32_deregister(int *offset, struct sysent *old_sysent);
+int    syscall32_module_handler(struct module *mod, int what, void *arg);
+
+#endif /* !_COMPAT_FREEBSD32_FREEBSD32_UTIL_H_ */

Modified: stable/6/sys/compat/ia32/ia32_sysvec.c
==============================================================================
--- stable/6/sys/compat/ia32/ia32_sysvec.c	Wed Jan 21 16:14:43 2009	(r187535)
+++ stable/6/sys/compat/ia32/ia32_sysvec.c	Wed Jan 21 16:28:15 2009	(r187536)
@@ -95,8 +95,6 @@ CTASSERT(sizeof(struct ia32_sigframe4) =
 static register_t *ia32_copyout_strings(struct image_params *imgp);
 static void ia32_fixlimit(struct rlimit *rl, int which);
 
-extern struct sysent freebsd32_sysent[];
-
 SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode");
 
 struct sysentvec ia32_freebsd_sysvec = {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901211628.n0LGSFev083048>