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>