svn commit: r187535 - in stable/7/sys: . compat/freebsd32
compat/ia32 contrib/pf dev/ath/ath_hal dev/cxgb
John Baldwin
jhb at FreeBSD.org
Wed Jan 21 08:14:45 PST 2009
Author: jhb
Date: Wed Jan 21 16:14:43 2009
New Revision: 187535
URL: http://svn.freebsd.org/changeset/base/187535
Log:
MFC: Add support for installing 32-bit system calls from kernel modules.
Modified:
stable/7/sys/ (props changed)
stable/7/sys/compat/freebsd32/freebsd32_misc.c
stable/7/sys/compat/freebsd32/freebsd32_util.h
stable/7/sys/compat/ia32/ia32_sysvec.c
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/dev/ath/ath_hal/ (props changed)
stable/7/sys/dev/cxgb/ (props changed)
Modified: stable/7/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/7/sys/compat/freebsd32/freebsd32_misc.c Wed Jan 21 15:51:15 2009 (r187534)
+++ stable/7/sys/compat/freebsd32/freebsd32_misc.c Wed Jan 21 16:14:43 2009 (r187535)
@@ -2589,3 +2589,83 @@ freebsd32_xxx(struct thread *td, struct
return (error);
}
#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/7/sys/compat/freebsd32/freebsd32_util.h
==============================================================================
--- stable/7/sys/compat/freebsd32/freebsd32_util.h Wed Jan 21 15:51:15 2009 (r187534)
+++ stable/7/sys/compat/freebsd32/freebsd32_util.h Wed Jan 21 16:14:43 2009 (r187535)
@@ -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/7/sys/compat/ia32/ia32_sysvec.c
==============================================================================
--- stable/7/sys/compat/ia32/ia32_sysvec.c Wed Jan 21 15:51:15 2009 (r187534)
+++ stable/7/sys/compat/ia32/ia32_sysvec.c Wed Jan 21 16:14:43 2009 (r187535)
@@ -96,8 +96,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");
static u_long ia32_maxdsiz = IA32_MAXDSIZ;
More information about the svn-src-stable
mailing list