From 134c31447edb5e8453986ba28bd14b41f2dfbed1 Mon Sep 17 00:00:00 2001 From: Matthew Macy Date: Thu, 6 Nov 2014 10:21:26 -0800 Subject: [PATCH] important NetBSD COMPAT_MACH bits from Attic (cherry picked from commit 36d8b8f9ba66a2288e967f5acd73abd48898cc41) Signed-off-by: Scott K --- sys/compat/mach/Makefile | 16 + sys/compat/mach/arch/powerpc/fasttraps/Makefile | 14 + .../arch/powerpc/fasttraps/mach_fasttraps_cpu.c | 72 ++ .../powerpc/fasttraps/mach_fasttraps_syscall.h | 29 + .../powerpc/fasttraps/mach_fasttraps_syscallargs.h | 51 + .../powerpc/fasttraps/mach_fasttraps_syscalls.c | 41 + .../arch/powerpc/fasttraps/mach_fasttraps_sysent.c | 60 + .../arch/powerpc/fasttraps/mach_fasttraps_thread.c | 83 ++ .../mach/arch/powerpc/fasttraps/syscalls.conf | 13 + .../mach/arch/powerpc/fasttraps/syscalls.master | 61 + sys/compat/mach/arch/powerpc/files.mach_powerpc | 10 + sys/compat/mach/arch/powerpc/ppccalls/Makefile | 14 + .../arch/powerpc/ppccalls/mach_ppccalls_syscall.h | 17 + .../powerpc/ppccalls/mach_ppccalls_syscallargs.h | 38 + .../arch/powerpc/ppccalls/mach_ppccalls_syscalls.c | 42 + .../arch/powerpc/ppccalls/mach_ppccalls_sysent.c | 61 + .../mach/arch/powerpc/ppccalls/syscalls.conf | 13 + .../mach/arch/powerpc/ppccalls/syscalls.master | 62 + sys/compat/mach/files.mach | 27 + sys/compat/mach/mach_bootstrap.c | 81 ++ sys/compat/mach/mach_bootstrap.h | 52 + sys/compat/mach/mach_clock.c | 135 +++ sys/compat/mach/mach_clock.h | 64 + sys/compat/mach/mach_errno.c | 176 +++ sys/compat/mach/mach_errno.h | 106 ++ sys/compat/mach/mach_exception.c | 530 +++++++++ sys/compat/mach/mach_exception.h | 160 +++ sys/compat/mach/mach_exec.c | 458 ++++++++ sys/compat/mach/mach_exec.h | 78 ++ sys/compat/mach/mach_host.c | 241 ++++ sys/compat/mach/mach_host.h | 184 +++ sys/compat/mach/mach_iokit.c | 1211 +++++++++++++++++++ sys/compat/mach/mach_iokit.h | 547 +++++++++ sys/compat/mach/mach_message.c | 1230 ++++++++++++++++++++ sys/compat/mach/mach_message.h | 276 +++++ sys/compat/mach/mach_misc.c | 217 ++++ sys/compat/mach/mach_notify.c | 182 +++ sys/compat/mach/mach_notify.h | 79 ++ sys/compat/mach/mach_port.c | 1004 ++++++++++++++++ sys/compat/mach/mach_port.h | 363 ++++++ sys/compat/mach/mach_semaphore.c | 438 +++++++ sys/compat/mach/mach_semaphore.h | 91 ++ sys/compat/mach/mach_services.c | 362 ++++++ sys/compat/mach/mach_services.h | 99 ++ sys/compat/mach/mach_services.master | 481 ++++++++ sys/compat/mach/mach_services_names.c | 351 ++++++ sys/compat/mach/mach_syscall.h | 110 ++ sys/compat/mach/mach_syscallargs.h | 258 ++++ sys/compat/mach/mach_syscalls.c | 159 +++ sys/compat/mach/mach_sysctl.c | 73 ++ sys/compat/mach/mach_sysctl.h | 43 + sys/compat/mach/mach_sysent.c | 289 +++++ sys/compat/mach/mach_task.c | 707 +++++++++++ sys/compat/mach/mach_task.h | 227 ++++ sys/compat/mach/mach_thread.c | 486 ++++++++ sys/compat/mach/mach_thread.h | 249 ++++ sys/compat/mach/mach_types.h | 113 ++ sys/compat/mach/mach_vm.c | 881 ++++++++++++++ sys/compat/mach/mach_vm.h | 391 +++++++ sys/compat/mach/makemachservices.sh | 133 +++ sys/compat/mach/syscalls.conf | 14 + sys/compat/mach/syscalls.master | 241 ++++ 62 files changed, 14294 insertions(+) create mode 100644 sys/compat/mach/Makefile create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/Makefile create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_cpu.c create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscallargs.h create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscalls.c create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_sysent.c create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_thread.c create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/syscalls.conf create mode 100644 sys/compat/mach/arch/powerpc/fasttraps/syscalls.master create mode 100644 sys/compat/mach/arch/powerpc/files.mach_powerpc create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/Makefile create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscall.h create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscallargs.h create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscalls.c create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_sysent.c create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/syscalls.conf create mode 100644 sys/compat/mach/arch/powerpc/ppccalls/syscalls.master create mode 100644 sys/compat/mach/files.mach create mode 100644 sys/compat/mach/mach_bootstrap.c create mode 100644 sys/compat/mach/mach_bootstrap.h create mode 100644 sys/compat/mach/mach_clock.c create mode 100644 sys/compat/mach/mach_clock.h create mode 100644 sys/compat/mach/mach_errno.c create mode 100644 sys/compat/mach/mach_errno.h create mode 100644 sys/compat/mach/mach_exception.c create mode 100644 sys/compat/mach/mach_exception.h create mode 100644 sys/compat/mach/mach_exec.c create mode 100644 sys/compat/mach/mach_exec.h create mode 100644 sys/compat/mach/mach_host.c create mode 100644 sys/compat/mach/mach_host.h create mode 100644 sys/compat/mach/mach_iokit.c create mode 100644 sys/compat/mach/mach_iokit.h create mode 100644 sys/compat/mach/mach_message.c create mode 100644 sys/compat/mach/mach_message.h create mode 100644 sys/compat/mach/mach_misc.c create mode 100644 sys/compat/mach/mach_notify.c create mode 100644 sys/compat/mach/mach_notify.h create mode 100644 sys/compat/mach/mach_port.c create mode 100644 sys/compat/mach/mach_port.h create mode 100644 sys/compat/mach/mach_semaphore.c create mode 100644 sys/compat/mach/mach_semaphore.h create mode 100644 sys/compat/mach/mach_services.c create mode 100644 sys/compat/mach/mach_services.h create mode 100644 sys/compat/mach/mach_services.master create mode 100644 sys/compat/mach/mach_services_names.c create mode 100644 sys/compat/mach/mach_syscall.h create mode 100644 sys/compat/mach/mach_syscallargs.h create mode 100644 sys/compat/mach/mach_syscalls.c create mode 100644 sys/compat/mach/mach_sysctl.c create mode 100644 sys/compat/mach/mach_sysctl.h create mode 100644 sys/compat/mach/mach_sysent.c create mode 100644 sys/compat/mach/mach_task.c create mode 100644 sys/compat/mach/mach_task.h create mode 100644 sys/compat/mach/mach_thread.c create mode 100644 sys/compat/mach/mach_thread.h create mode 100644 sys/compat/mach/mach_types.h create mode 100644 sys/compat/mach/mach_vm.c create mode 100644 sys/compat/mach/mach_vm.h create mode 100755 sys/compat/mach/makemachservices.sh create mode 100644 sys/compat/mach/syscalls.conf create mode 100644 sys/compat/mach/syscalls.master diff --git a/sys/compat/mach/Makefile b/sys/compat/mach/Makefile new file mode 100644 index 0000000..7cc43a8 --- /dev/null +++ b/sys/compat/mach/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.7 2005/12/11 12:20:20 christos Exp $ + +SYSCALL_DEP= syscalls.conf syscalls.master ../../kern/makesyscalls.sh +SYSCALL_OBJS= mach_sysent.c mach_syscalls.c mach_syscall.h mach_syscallargs.h +MACH_DEP= mach_services.master makemachservices.sh +MACH_OBJ= mach_services.c mach_services.h mach_services_names.c + +all: ${SYSCALL_OBJS} ${MACH_OBJ} + +.include # for HOST_SH + +${SYSCALL_OBJS}: ${SYSCALL_DEP} + ${HOST_SH} ../../kern/makesyscalls.sh syscalls.conf syscalls.master + +${MACH_OBJ}: ${MACH_DEP} + ${HOSH_SH} ./makemachservices.sh diff --git a/sys/compat/mach/arch/powerpc/fasttraps/Makefile b/sys/compat/mach/arch/powerpc/fasttraps/Makefile new file mode 100644 index 0000000..a7d164d --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.5 2005/12/11 12:20:21 christos Exp $ + +.include # for HOST_SH + +DEP= syscalls.conf syscalls.master ../../../../../kern/makesyscalls.sh +OBJS= mach_fasttraps_sysent.c mach_fasttraps_syscalls.c \ + mach_fasttraps_syscall.h mach_fasttraps_syscallargs.h + +${OBJS}: ${DEP} + ${HOST_SH} ../../../../../kern/makesyscalls.sh syscalls.conf syscalls.master + +all: ${OBJS} + +.include diff --git a/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_cpu.c b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_cpu.c new file mode 100644 index 0000000..3969e1d --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_cpu.c @@ -0,0 +1,72 @@ +/* $NetBSD: mach_fasttraps_cpu.c,v 1.8 2008/04/28 20:23:45 martin Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_fasttraps_cpu.c,v 1.8 2008/04/28 20:23:45 martin Exp $"); + +#include +#include + +#include +#include +#include + +#define mach_ignoreZeroFaultbit 0 +#define mach_floatUsedbit 1 +#define mach_vectorUsedbit 2 +#define mach_runningVMbit 4 +#define mach_floatCngbit 5 +#define mach_vectorCngbit 6 +#define mach_timerPopbit 7 +#define mach_userProtKeybit 8 +#define mach_trapUnalignbit 9 +#define mach_notifyUnalignbit 10 +#define mach_bbThreadbit 28 +#define mach_bbNoMachSCbit 29 +#define mach_bbPreemptivebit 30 +#define mach_spfReserved1 31 + +/* We do not emulate anything here right now */ +int +mach_sys_processor_facilities_used(struct lwp *l, const void *v, register_t *retval) +{ + *retval = 0; + return 0; +} + +/* This seems to be called only from within the kernel in Mach */ +int +mach_sys_load_msr(struct lwp *l, const void *v, register_t *retval) +{ + printf("mach_sys_load_msr()\n"); + return 0; +} + diff --git a/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h new file mode 100644 index 0000000..7d01d22 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscall.h @@ -0,0 +1,29 @@ +/* $NetBSD: mach_fasttraps_syscall.h,v 1.13 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.8 2009/01/13 22:27:43 pooka Exp + */ + +#ifndef _MACH_FASTTRAPS_SYS_SYSCALL_H_ +#define _MACH_FASTTRAPS_SYS_SYSCALL_H_ + +#define MACH_FASTTRAPS_SYS_MAXSYSARGS 8 + +/* syscall: "cthread_set_self" ret: "void" args: "mach_cproc_t" */ +#define MACH_FASTTRAPS_SYS_cthread_set_self 1 + +/* syscall: "cthread_self" ret: "mach_cproc_t" args: */ +#define MACH_FASTTRAPS_SYS_cthread_self 2 + +/* syscall: "processor_facilities_used" ret: "int" args: */ +#define MACH_FASTTRAPS_SYS_processor_facilities_used 3 + +/* syscall: "load_msr" ret: "void" args: */ +#define MACH_FASTTRAPS_SYS_load_msr 4 + +#define MACH_FASTTRAPS_SYS_MAXSYSCALL 16 +#define MACH_FASTTRAPS_SYS_NSYSENT 16 +#endif /* _MACH_FASTTRAPS_SYS_SYSCALL_H_ */ diff --git a/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscallargs.h b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscallargs.h new file mode 100644 index 0000000..ec67911 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscallargs.h @@ -0,0 +1,51 @@ +/* $NetBSD: mach_fasttraps_syscallargs.h,v 1.13 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call argument lists. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.8 2009/01/13 22:27:43 pooka Exp + */ + +#ifndef _MACH_FASTTRAPS_SYS_SYSCALLARGS_H_ +#define _MACH_FASTTRAPS_SYS_SYSCALLARGS_H_ + +#define MACH_FASTTRAPS_SYS_MAXSYSARGS 8 + +#undef syscallarg +#define syscallarg(x) \ + union { \ + register_t pad; \ + struct { x datum; } le; \ + struct { /* LINTED zero array dimension */ \ + int8_t pad[ /* CONSTCOND */ \ + (sizeof (register_t) < sizeof (x)) \ + ? 0 \ + : sizeof (register_t) - sizeof (x)]; \ + x datum; \ + } be; \ + } + +#undef check_syscall_args +#define check_syscall_args(call) \ + typedef char call##_check_args[sizeof (struct call##_args) \ + <= MACH_FASTTRAPS_SYS_MAXSYSARGS * sizeof (register_t) ? 1 : -1]; + +struct mach_sys_cthread_set_self_args { + syscallarg(mach_cproc_t) p; +}; +check_syscall_args(mach_sys_cthread_set_self) + +/* + * System call prototypes. + */ + +int mach_sys_cthread_set_self(struct lwp *, const struct mach_sys_cthread_set_self_args *, register_t *); + +int mach_sys_cthread_self(struct lwp *, const void *, register_t *); + +int mach_sys_processor_facilities_used(struct lwp *, const void *, register_t *); + +int mach_sys_load_msr(struct lwp *, const void *, register_t *); + +#endif /* _MACH_FASTTRAPS_SYS_SYSCALLARGS_H_ */ diff --git a/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscalls.c b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscalls.c new file mode 100644 index 0000000..21f4c35 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_syscalls.c @@ -0,0 +1,41 @@ +/* $NetBSD: mach_fasttraps_syscalls.c,v 1.14 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call names. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.8 2009/01/13 22:27:43 pooka Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_fasttraps_syscalls.c,v 1.14 2009/01/13 22:33:11 pooka Exp $"); + +#if defined(_KERNEL_OPT) +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* _KERNEL_OPT */ + +const char *const mach_fasttraps_syscallnames[] = { + /* 0 */ "#0 (unimplemented)", + /* 1 */ "cthread_set_self", + /* 2 */ "cthread_self", + /* 3 */ "processor_facilities_used", + /* 4 */ "load_msr", + /* 5 */ "#5 (unimplemented)", + /* 6 */ "#6 (unimplemented)", + /* 7 */ "#7 (unimplemented)", + /* 8 */ "#8 (unimplemented)", + /* 9 */ "#9 (unimplemented)", + /* 10 */ "#10 (unimplemented special_bluebox)", + /* 11 */ "#11 (unimplemented)", + /* 12 */ "#12 (unimplemented)", + /* 13 */ "#13 (unimplemented)", + /* 14 */ "#14 (unimplemented)", + /* 15 */ "#15 (unimplemented)", +}; diff --git a/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_sysent.c b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_sysent.c new file mode 100644 index 0000000..a5a59e6 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_sysent.c @@ -0,0 +1,60 @@ +/* $NetBSD: mach_fasttraps_sysent.c,v 1.14 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call switch table. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.8 2009/01/13 22:27:43 pooka Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_fasttraps_sysent.c,v 1.14 2009/01/13 22:33:11 pooka Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#define s(type) sizeof(type) +#define n(type) (sizeof(type)/sizeof (register_t)) +#define ns(type) n(type), s(type) + +struct sysent mach_fasttraps_sysent[] = { + { 0, 0, 0, + sys_nosys }, /* 0 = unimplemented */ + { ns(struct mach_sys_cthread_set_self_args), 0, + (sy_call_t *)mach_sys_cthread_set_self },/* 1 = cthread_set_self */ + { 0, 0, 0, + (sy_call_t *)mach_sys_cthread_self },/* 2 = cthread_self */ + { 0, 0, 0, + (sy_call_t *)mach_sys_processor_facilities_used },/* 3 = processor_facilities_used */ + { 0, 0, 0, + (sy_call_t *)mach_sys_load_msr }, /* 4 = load_msr */ + { 0, 0, 0, + sys_nosys }, /* 5 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 6 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 7 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 8 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 9 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 10 = unimplemented special_bluebox */ + { 0, 0, 0, + sys_nosys }, /* 11 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 12 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 13 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 14 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 15 = unimplemented */ +}; + diff --git a/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_thread.c b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_thread.c new file mode 100644 index 0000000..7b70585 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/mach_fasttraps_thread.c @@ -0,0 +1,83 @@ +/* $NetBSD: mach_fasttraps_thread.c,v 1.12 2008/04/28 20:23:45 martin Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_fasttraps_thread.c,v 1.12 2008/04/28 20:23:45 martin Exp $"); + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +int +mach_sys_cthread_set_self(struct lwp *l, const struct mach_sys_cthread_set_self_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_cproc_t) p; + } */ + struct mach_emuldata *med; + + l->l_private = (void *)SCARG(uap, p); + + med = l->l_proc->p_emuldata; + med->med_dirty_thid = 0; + + return 0; +} + +int +mach_sys_cthread_self(struct lwp *l, const void *v, register_t *retval) +{ + struct mach_emuldata *med; + + /* + * After a fork or exec, l_private is not initialized. + * We have no way of setting it before, so we keep track + * of it being uninitialized with med_dirty_thid. + * XXX This is probably not the most efficient way + */ + med = l->l_proc->p_emuldata; + if (med->med_dirty_thid != 0) { + l->l_private = NULL; + med->med_dirty_thid = 0; + } + + *retval = (register_t)l->l_private; + return 0; +} diff --git a/sys/compat/mach/arch/powerpc/fasttraps/syscalls.conf b/sys/compat/mach/arch/powerpc/fasttraps/syscalls.conf new file mode 100644 index 0000000..3697dff --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/syscalls.conf @@ -0,0 +1,13 @@ +# $NetBSD: syscalls.conf,v 1.1 2002/11/03 23:17:21 manu Exp $ + +sysnames="mach_fasttraps_syscalls.c" +sysnumhdr="mach_fasttraps_syscall.h" +syssw="mach_fasttraps_sysent.c" +sysarghdr="mach_fasttraps_syscallargs.h" +compatopts="" +libcompatopts="" + +switchname="mach_fasttraps_sysent" +namesname="mach_fasttraps_syscallnames" +constprefix="MACH_FASTTRAPS_SYS_" +nsysent=16 diff --git a/sys/compat/mach/arch/powerpc/fasttraps/syscalls.master b/sys/compat/mach/arch/powerpc/fasttraps/syscalls.master new file mode 100644 index 0000000..f22eed7 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/fasttraps/syscalls.master @@ -0,0 +1,61 @@ + $NetBSD: syscalls.master,v 1.8 2009/01/13 22:27:43 pooka Exp $ + +; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 + +; NetBSD COMPAT_MACH PowerPC-only fast traos calls name/number "master" file. +; This is used for the negative mach syscalls. +; (See syscalls.conf to see what it is processed into.) +; +; Fields: number type [type-dependent ...] +; number system call number, must be in order +; type one of STD, OBSOL, UNIMPL, NODEF, NOARGS, or one of +; the compatibility options defined in syscalls.conf. +; +; types: +; STD always included +; OBSOL obsolete, not included in system +; UNIMPL unimplemented, not included in system +; NODEF included, but don't define the syscall number +; NOARGS included, but don't define the syscall args structure +; +; The compat options are defined in the syscalls.conf file, and the +; compat option name is prefixed to the syscall name. Other than +; that, they're like NODEF (for 'compat' options), or STD (for +; 'libcompat' options). +; +; The type-dependent arguments are as follows: +; For STD, NODEF, NOARGS, and compat syscalls: +; { pseudo-proto } [alias] +; For other syscalls: +; [comment] +; +; #ifdef's, etc. may be included, and are copied to the output files. +; #include's are copied to the syscall names and switch definition files only. + +#include +#include +#include +#include +#include +#include + +#include +#include +%% + +0 UNIMPL +1 STD { void|mach_sys||cthread_set_self(mach_cproc_t p); } +2 STD { mach_cproc_t|mach_sys||cthread_self(void); } +3 STD { int|mach_sys||processor_facilities_used(void); } +4 STD { void|mach_sys||load_msr(void); } +5 UNIMPL +6 UNIMPL +7 UNIMPL +8 UNIMPL +9 UNIMPL +10 UNIMPL special_bluebox +11 UNIMPL +12 UNIMPL +13 UNIMPL +14 UNIMPL +15 UNIMPL diff --git a/sys/compat/mach/arch/powerpc/files.mach_powerpc b/sys/compat/mach/arch/powerpc/files.mach_powerpc new file mode 100644 index 0000000..08f3a1e --- /dev/null +++ b/sys/compat/mach/arch/powerpc/files.mach_powerpc @@ -0,0 +1,10 @@ +# $NetBSD: files.mach_powerpc,v 1.1 2002/11/03 23:17:19 manu Exp $ +# +# Config file description for PowerPC only calls Mach compat code. +# Included by ports that need it. + +file compat/mach/arch/powerpc/ppccalls/mach_ppccalls_sysent.c compat_mach + +file compat/mach/arch/powerpc/fasttraps/mach_fasttraps_sysent.c compat_mach +file compat/mach/arch/powerpc/fasttraps/mach_fasttraps_thread.c compat_mach +file compat/mach/arch/powerpc/fasttraps/mach_fasttraps_cpu.c compat_mach diff --git a/sys/compat/mach/arch/powerpc/ppccalls/Makefile b/sys/compat/mach/arch/powerpc/ppccalls/Makefile new file mode 100644 index 0000000..c3ec1a8 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.4 2005/12/11 12:20:22 christos Exp $ + +.include # for HOST_SH + +DEP= syscalls.conf syscalls.master ../../../../../kern/makesyscalls.sh +OBJS= mach_ppccalls_sysent.c mach_ppccalls_syscalls.c \ + mach_ppccalls_syscall.h mach_ppccalls_syscallargs.h + +${OBJS}: ${DEP} + ${HOST_SH} ../../../../../kern/makesyscalls.sh syscalls.conf syscalls.master + +all: ${OBJS} + +.include diff --git a/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscall.h b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscall.h new file mode 100644 index 0000000..6152851 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscall.h @@ -0,0 +1,17 @@ +/* $NetBSD: mach_ppccalls_syscall.h,v 1.8 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.5 2007/02/09 21:55:22 ad Exp + */ + +#ifndef _MACH_PPCCALLS_SYS_SYSCALL_H_ +#define _MACH_PPCCALLS_SYS_SYSCALL_H_ + +#define MACH_PPCCALLS_SYS_MAXSYSARGS 8 + +#define MACH_PPCCALLS_SYS_MAXSYSCALL 16 +#define MACH_PPCCALLS_SYS_NSYSENT 16 +#endif /* _MACH_PPCCALLS_SYS_SYSCALL_H_ */ diff --git a/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscallargs.h b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscallargs.h new file mode 100644 index 0000000..92d6275 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscallargs.h @@ -0,0 +1,38 @@ +/* $NetBSD: mach_ppccalls_syscallargs.h,v 1.8 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call argument lists. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.5 2007/02/09 21:55:22 ad Exp + */ + +#ifndef _MACH_PPCCALLS_SYS_SYSCALLARGS_H_ +#define _MACH_PPCCALLS_SYS_SYSCALLARGS_H_ + +#define MACH_PPCCALLS_SYS_MAXSYSARGS 8 + +#undef syscallarg +#define syscallarg(x) \ + union { \ + register_t pad; \ + struct { x datum; } le; \ + struct { /* LINTED zero array dimension */ \ + int8_t pad[ /* CONSTCOND */ \ + (sizeof (register_t) < sizeof (x)) \ + ? 0 \ + : sizeof (register_t) - sizeof (x)]; \ + x datum; \ + } be; \ + } + +#undef check_syscall_args +#define check_syscall_args(call) \ + typedef char call##_check_args[sizeof (struct call##_args) \ + <= MACH_PPCCALLS_SYS_MAXSYSARGS * sizeof (register_t) ? 1 : -1]; + +/* + * System call prototypes. + */ + +#endif /* _MACH_PPCCALLS_SYS_SYSCALLARGS_H_ */ diff --git a/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscalls.c b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscalls.c new file mode 100644 index 0000000..8f489c1 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_syscalls.c @@ -0,0 +1,42 @@ +/* $NetBSD: mach_ppccalls_syscalls.c,v 1.9 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call names. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.5 2007/02/09 21:55:22 ad Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_ppccalls_syscalls.c,v 1.9 2009/01/13 22:33:11 pooka Exp $"); + +#if defined(_KERNEL_OPT) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* _KERNEL_OPT */ + +const char *const mach_ppccalls_syscallnames[] = { + /* 0 */ "#0 (unimplemented diagcall)", + /* 1 */ "#1 (unimplemented vmm_get_version)", + /* 2 */ "#2 (unimplemented vmm_get_features)", + /* 3 */ "#3 (unimplemented vmm_init_context)", + /* 4 */ "#4 (unimplemented vmm_dispatch)", + /* 5 */ "#5 (unimplemented bb_enable_bluebox)", + /* 6 */ "#6 (unimplemented bb_disable_bluebox)", + /* 7 */ "#7 (unimplemented bb_settaskenv)", + /* 8 */ "#8 (unimplemented vmm_stop_vm)", + /* 9 */ "#9 (unimplemented dis)", + /* 10 */ "#10 (unimplemented)", + /* 11 */ "#11 (unimplemented)", + /* 12 */ "#12 (unimplemented)", + /* 13 */ "#13 (unimplemented)", + /* 14 */ "#14 (unimplemented)", + /* 15 */ "#15 (unimplemented)", +}; diff --git a/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_sysent.c b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_sysent.c new file mode 100644 index 0000000..21579d0 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/mach_ppccalls_sysent.c @@ -0,0 +1,61 @@ +/* $NetBSD: mach_ppccalls_sysent.c,v 1.9 2009/01/13 22:33:11 pooka Exp $ */ + +/* + * System call switch table. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.5 2007/02/09 21:55:22 ad Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_ppccalls_sysent.c,v 1.9 2009/01/13 22:33:11 pooka Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define s(type) sizeof(type) +#define n(type) (sizeof(type)/sizeof (register_t)) +#define ns(type) n(type), s(type) + +struct sysent mach_ppccalls_sysent[] = { + { 0, 0, 0, + sys_nosys }, /* 0 = unimplemented diagcall */ + { 0, 0, 0, + sys_nosys }, /* 1 = unimplemented vmm_get_version */ + { 0, 0, 0, + sys_nosys }, /* 2 = unimplemented vmm_get_features */ + { 0, 0, 0, + sys_nosys }, /* 3 = unimplemented vmm_init_context */ + { 0, 0, 0, + sys_nosys }, /* 4 = unimplemented vmm_dispatch */ + { 0, 0, 0, + sys_nosys }, /* 5 = unimplemented bb_enable_bluebox */ + { 0, 0, 0, + sys_nosys }, /* 6 = unimplemented bb_disable_bluebox */ + { 0, 0, 0, + sys_nosys }, /* 7 = unimplemented bb_settaskenv */ + { 0, 0, 0, + sys_nosys }, /* 8 = unimplemented vmm_stop_vm */ + { 0, 0, 0, + sys_nosys }, /* 9 = unimplemented dis */ + { 0, 0, 0, + sys_nosys }, /* 10 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 11 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 12 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 13 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 14 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 15 = unimplemented */ +}; + diff --git a/sys/compat/mach/arch/powerpc/ppccalls/syscalls.conf b/sys/compat/mach/arch/powerpc/ppccalls/syscalls.conf new file mode 100644 index 0000000..93215d0 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/syscalls.conf @@ -0,0 +1,13 @@ +# $NetBSD: syscalls.conf,v 1.1 2002/11/03 23:17:22 manu Exp $ + +sysnames="mach_ppccalls_syscalls.c" +sysnumhdr="mach_ppccalls_syscall.h" +syssw="mach_ppccalls_sysent.c" +sysarghdr="mach_ppccalls_syscallargs.h" +compatopts="" +libcompatopts="" + +switchname="mach_ppccalls_sysent" +namesname="mach_ppccalls_syscallnames" +constprefix="MACH_PPCCALLS_SYS_" +nsysent=16 diff --git a/sys/compat/mach/arch/powerpc/ppccalls/syscalls.master b/sys/compat/mach/arch/powerpc/ppccalls/syscalls.master new file mode 100644 index 0000000..4ec3cb9 --- /dev/null +++ b/sys/compat/mach/arch/powerpc/ppccalls/syscalls.master @@ -0,0 +1,62 @@ + $NetBSD: syscalls.master,v 1.5 2007/02/09 21:55:22 ad Exp $ + +; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 + +; NetBSD COMPAT_MACH PowerPC-only system call name/number "master" file. +; This is used for the negative mach syscalls. +; (See syscalls.conf to see what it is processed into.) +; +; Fields: number type [type-dependent ...] +; number system call number, must be in order +; type one of STD, OBSOL, UNIMPL, NODEF, NOARGS, or one of +; the compatibility options defined in syscalls.conf. +; +; types: +; STD always included +; OBSOL obsolete, not included in system +; UNIMPL unimplemented, not included in system +; NODEF included, but don't define the syscall number +; NOARGS included, but don't define the syscall args structure +; +; The compat options are defined in the syscalls.conf file, and the +; compat option name is prefixed to the syscall name. Other than +; that, they're like NODEF (for 'compat' options), or STD (for +; 'libcompat' options). +; +; The type-dependent arguments are as follows: +; For STD, NODEF, NOARGS, and compat syscalls: +; { pseudo-proto } [alias] +; For other syscalls: +; [comment] +; +; #ifdef's, etc. may be included, and are copied to the output files. +; #include's are copied to the syscall names and switch definition files only. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +%% + +0 UNIMPL diagcall +1 UNIMPL vmm_get_version +2 UNIMPL vmm_get_features +3 UNIMPL vmm_init_context +4 UNIMPL vmm_dispatch +5 UNIMPL bb_enable_bluebox +6 UNIMPL bb_disable_bluebox +7 UNIMPL bb_settaskenv +8 UNIMPL vmm_stop_vm +9 UNIMPL dis +10 UNIMPL +11 UNIMPL +12 UNIMPL +13 UNIMPL +14 UNIMPL +15 UNIMPL diff --git a/sys/compat/mach/files.mach b/sys/compat/mach/files.mach new file mode 100644 index 0000000..c5b8359 --- /dev/null +++ b/sys/compat/mach/files.mach @@ -0,0 +1,27 @@ +# $NetBSD: files.mach,v 1.16 2005/12/11 12:20:20 christos Exp $ +# +# Config file description for machine-independent Mach compat code. +# Included by ports that need it. + +# ports should define any machine-specific files they need in their +# own file lists. + +file compat/mach/mach_bootstrap.c compat_mach | compat_darwin +file compat/mach/mach_clock.c compat_mach | compat_darwin +file compat/mach/mach_errno.c compat_mach | compat_darwin +file compat/mach/mach_exception.c compat_mach | compat_darwin +file compat/mach/mach_exec.c compat_mach | compat_darwin +file compat/mach/mach_host.c compat_mach | compat_darwin +file compat/mach/mach_iokit.c compat_mach | compat_darwin +file compat/mach/mach_misc.c compat_mach | compat_darwin +file compat/mach/mach_message.c compat_mach | compat_darwin +file compat/mach/mach_notify.c compat_mach | compat_darwin +file compat/mach/mach_port.c compat_mach | compat_darwin +file compat/mach/mach_semaphore.c compat_mach | compat_darwin +file compat/mach/mach_services.c compat_mach | compat_darwin +file compat/mach/mach_syscalls.c compat_mach | compat_darwin +file compat/mach/mach_sysctl.c compat_mach | compat_darwin +file compat/mach/mach_sysent.c compat_mach | compat_darwin +file compat/mach/mach_task.c compat_mach | compat_darwin +file compat/mach/mach_thread.c compat_mach | compat_darwin +file compat/mach/mach_vm.c compat_mach | compat_darwin diff --git a/sys/compat/mach/mach_bootstrap.c b/sys/compat/mach/mach_bootstrap.c new file mode 100644 index 0000000..e40c488 --- /dev/null +++ b/sys/compat/mach/mach_bootstrap.c @@ -0,0 +1,81 @@ +/* $NetBSD: mach_bootstrap.c,v 1.14 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_bootstrap.c,v 1.14 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int +mach_bootstrap_look_up(struct mach_trap_args *args) +{ + mach_bootstrap_look_up_request_t *req = args->smsg; + mach_bootstrap_look_up_reply_t *rep = args->rmsg; + struct lwp *l = args->l; + size_t *msglen = args->rsize; + const char service_name[] = "lookup\021"; /* XXX Why */ + int service_name_len; + struct mach_right *mr; + size_t len; + + /* The trailer is word aligned */ + service_name_len = (sizeof(service_name) + 1) & ~0x7UL; + len = sizeof(*rep) - sizeof(rep->rep_service_name) + service_name_len; + + if (len > *msglen) + return mach_msg_error(args, EINVAL); + *msglen = len; + + mr = mach_right_get(NULL, l, MACH_PORT_TYPE_DEAD_NAME, 0); + + mach_set_header(rep, req, *msglen); + + rep->rep_count = 1; + rep->rep_bootstrap_port = mr->mr_name; + strncpy((char *)rep->rep_service_name, service_name, + service_name_len); + + mach_set_trailer(rep, *msglen); + + return 0; +} + diff --git a/sys/compat/mach/mach_bootstrap.h b/sys/compat/mach/mach_bootstrap.h new file mode 100644 index 0000000..b798ace --- /dev/null +++ b/sys/compat/mach/mach_bootstrap.h @@ -0,0 +1,52 @@ +/* $NetBSD: mach_bootstrap.h,v 1.5 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_BOOTSTRAP_H_ +#define _MACH_BOOTSTRAP_H_ + +/* bootstrap_look_up */ + +#define MACH_BOOTSTRAP_MAX_NAME_LEN 128 +typedef char mach_name_t[MACH_BOOTSTRAP_MAX_NAME_LEN]; + +typedef struct { + mach_msg_header_t req_msgh; +} mach_bootstrap_look_up_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_integer_t rep_count; + mach_port_t rep_bootstrap_port; + mach_name_t rep_service_name; + mach_msg_trailer_t rep_trailer; +} mach_bootstrap_look_up_reply_t; + +#endif /* _MACH_BOOTSTRAP_H_ */ diff --git a/sys/compat/mach/mach_clock.c b/sys/compat/mach/mach_clock.c new file mode 100644 index 0000000..d802315 --- /dev/null +++ b/sys/compat/mach/mach_clock.c @@ -0,0 +1,135 @@ +/* $NetBSD: mach_clock.c,v 1.19 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_clock.c,v 1.19 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int +mach_sys_clock_sleep_trap(struct lwp *l, const struct mach_sys_clock_sleep_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_clock_port_t) clock_name; + syscallarg(mach_sleep_type_t) sleep_type; + syscallarg(int) sleep_sec; + syscallarg(int) sleep_nsec; + syscallarg(mach_timespec_t *) wakeup_time; + } */ + struct timespec mts, cts, tts; + mach_timespec_t mcts; + int dontcare; + int error; + int ticks; + + mts.tv_sec = SCARG(uap, sleep_sec); + mts.tv_nsec = SCARG(uap, sleep_nsec); + + if (SCARG(uap, sleep_type) == MACH_TIME_ABSOLUTE) { + nanotime(&cts); + timespecsub(&mts, &cts, &tts); + } else { + tts.tv_sec = mts.tv_sec; + tts.tv_nsec = mts.tv_nsec; + } + + ticks = tts.tv_sec * hz; + ticks += (tts.tv_nsec * hz) / 100000000L; + + tsleep(&dontcare, PZERO|PCATCH, "sleep", ticks); + + if (SCARG(uap, wakeup_time) != NULL) { + nanotime(&cts); + mcts.tv_sec = cts.tv_sec; + mcts.tv_nsec = cts.tv_nsec; + error = copyout(&mcts, SCARG(uap, wakeup_time), sizeof(mcts)); + if (error != 0) + return error; + } + + return 0; +} + +int +mach_sys_timebase_info(struct lwp *l, const struct mach_sys_timebase_info_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_timebase_info_t) info; + } */ + int error; + struct mach_timebase_info info; + + /* XXX This is probably bus speed, fill it accurately */ + info.numer = 4000000000UL; + info.denom = 75189611UL; + + if ((error = copyout(&info, (void *)SCARG(uap, info), + sizeof(info))) != 0) + return error; + + return 0; +} + + + +int +mach_clock_get_time(struct mach_trap_args *args) +{ + mach_clock_get_time_request_t *req = args->smsg; + mach_clock_get_time_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct timeval tv; + + microtime(&tv); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_cur_time.tv_sec = tv.tv_sec; + rep->rep_cur_time.tv_nsec = tv.tv_usec * 1000; + + mach_set_trailer(rep, *msglen); + + return 0; +} diff --git a/sys/compat/mach/mach_clock.h b/sys/compat/mach/mach_clock.h new file mode 100644 index 0000000..ea3584e --- /dev/null +++ b/sys/compat/mach/mach_clock.h @@ -0,0 +1,64 @@ +/* $NetBSD: mach_clock.h,v 1.8 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_CLOCK_H_ +#define _MACH_CLOCK_H_ + +#include +#include +#include +#include + +#include +#include + +/* clock_get_time */ +#define MACH_TIME_ABSOLUTE 0x00 +#define MACH_TIME_RELATIVE 0x01 + +typedef struct { + unsigned int tv_sec; + int tv_nsec; +} mach_timespec_t; + +typedef struct { + mach_msg_header_t req_msgh; +} mach_clock_get_time_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_timespec_t rep_cur_time; + mach_msg_trailer_t rep_trailer; +} mach_clock_get_time_reply_t; + +#endif /* _MACH_CLOCK_H_ */ diff --git a/sys/compat/mach/mach_errno.c b/sys/compat/mach/mach_errno.c new file mode 100644 index 0000000..7e59e98 --- /dev/null +++ b/sys/compat/mach/mach_errno.c @@ -0,0 +1,176 @@ +/* $NetBSD: mach_errno.c,v 1.18 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_errno.c,v 1.18 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include + +#include +#include +#include + +int native_to_mach_errno[] = { + MACH_KERN_SUCCESS, /* 0 */ + MACH_KERN_PROTECTION_FAILURE, /* EPERM */ + MACH_KERN_FAILURE, /* ENOENT */ + MACH_KERN_FAILURE, /* ESRCH */ + MACH_KERN_FAILURE, /* EINTR */ + MACH_KERN_FAILURE, /* EIO */ /* 5 */ + MACH_KERN_FAILURE, /* ENXIO */ + MACH_KERN_FAILURE, /* E2BIG */ + MACH_KERN_FAILURE, /* ENOEXEC */ + MACH_KERN_FAILURE, /* EBADF */ + MACH_KERN_FAILURE, /* ECHILD */ /* 10 */ + MACH_KERN_FAILURE, /* EDEADLK */ + MACH_KERN_NO_SPACE, /* ENOMEM */ + MACH_KERN_FAILURE, /* EACCES */ + MACH_KERN_INVALID_ADDRESS, /* EFAULT */ + MACH_KERN_FAILURE, /* ENOTBLK */ /* 15 */ + MACH_KERN_FAILURE, /* EBUSY */ + MACH_KERN_FAILURE, /* EEXIST */ + MACH_KERN_FAILURE, /* EXDEV */ + MACH_KERN_FAILURE, /* ENODEV */ + MACH_KERN_FAILURE, /* ENOTDIR */ /* 20 */ + MACH_KERN_FAILURE, /* EISDIR */ + MACH_KERN_INVALID_ARGUMENT, /* EINVAL */ + MACH_KERN_FAILURE, /* ENFILE */ + MACH_KERN_FAILURE, /* EMFILE */ + MACH_KERN_FAILURE, /* ENOTTY */ /* 25 */ + MACH_KERN_FAILURE, /* ETXTBSY */ + MACH_KERN_FAILURE, /* EFBIG */ + MACH_KERN_FAILURE, /* ENOSPC */ + MACH_KERN_FAILURE, /* ESPIPE */ + MACH_KERN_FAILURE, /* EROFS */ /* 30 */ + MACH_KERN_FAILURE, /* EMLINK */ + MACH_KERN_FAILURE, /* EPIPE */ + MACH_KERN_FAILURE, /* EDOM */ + MACH_KERN_FAILURE, /* ERANGE */ + MACH_KERN_FAILURE, /* EAGAIN */ /* 35 */ + MACH_KERN_FAILURE, /* EWOULDBLOCK */ + MACH_KERN_FAILURE, /* EINPROGRESS */ + MACH_KERN_FAILURE, /* EALREADY */ + MACH_KERN_FAILURE, /* ENOTSOCK */ + MACH_KERN_FAILURE, /* EDESTADDRREQ */ /* 40 */ + MACH_KERN_FAILURE, /* EMSGSIZE */ + MACH_KERN_FAILURE, /* EPROTOTYPE */ + MACH_KERN_FAILURE, /* ENOPROTOOPT */ + MACH_KERN_FAILURE, /* ESOCKTNOSUPPORT */ + MACH_KERN_FAILURE, /* EOPNOTSUPP */ /* 45 */ + MACH_KERN_FAILURE, /* EPFNOSUPPORT */ + MACH_KERN_FAILURE, /* EAFNOSUPPORT */ + MACH_KERN_FAILURE, /* EADDRINUSE */ + MACH_KERN_FAILURE, /* EADDRNOTAVAIL */ + MACH_KERN_FAILURE, /* ENETDOWN */ /* 50 */ + MACH_KERN_FAILURE, /* ENETUNREACH */ + MACH_KERN_FAILURE, /* ENETRESET */ + MACH_KERN_FAILURE, /* ECONNABORTED */ + MACH_KERN_FAILURE, /* ECONNRESET */ + MACH_KERN_FAILURE, /* ENOBUFS */ /* 55 */ + MACH_KERN_FAILURE, /* EISCONN */ + MACH_KERN_FAILURE, /* ENOTCONN */ + MACH_KERN_FAILURE, /* ESHUTDOWN */ + MACH_KERN_FAILURE, /* ETOOMANYREFS */ + MACH_KERN_FAILURE, /* ETIMEDOUT */ /* 60 */ + MACH_KERN_FAILURE, /* ECONNREFUSED */ + MACH_KERN_FAILURE, /* ELOOP */ + MACH_KERN_FAILURE, /* ENAMETOOLONG */ + MACH_KERN_FAILURE, /* EHOSTDOWN */ + MACH_KERN_FAILURE, /* EHOSTUNREACH */ /* 65 */ + MACH_KERN_FAILURE, /* ENOTEMPTY */ + MACH_KERN_FAILURE, /* EPROCLIM */ + MACH_KERN_FAILURE, /* EUSERS */ + MACH_KERN_FAILURE, /* EDQUOT */ + MACH_KERN_FAILURE, /* ESTALE */ /* 70 */ + MACH_KERN_FAILURE, /* EREMOTE */ + MACH_KERN_FAILURE, /* EBADRPC */ + MACH_KERN_FAILURE, /* ERPCMISMATCH */ + MACH_KERN_FAILURE, /* EPROGUNAVAIL */ + MACH_KERN_FAILURE, /* EPROGMISMATCH */ /* 75 */ + MACH_KERN_FAILURE, /* EPROCUNAVAIL */ + MACH_KERN_FAILURE, /* ENOLCK */ + MACH_KERN_FAILURE, /* ENOSYS */ + MACH_KERN_FAILURE, /* EFTYPE */ + MACH_KERN_FAILURE, /* EAUTH */ /* 80 */ + MACH_KERN_FAILURE, /* ENEEDAUTH */ + MACH_KERN_FAILURE, /* EIDRM */ + MACH_KERN_FAILURE, /* ENOMSG */ + MACH_KERN_FAILURE, /* EOVERFLOW */ + MACH_KERN_FAILURE, /* EILSEQ */ /* 85 */ +}; + +int +mach_msg_error(struct mach_trap_args *args, int error) +{ + mach_msg_header_t *req = args->smsg; + mach_error_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = native_to_mach_errno[error]; + + mach_set_trailer(rep, *msglen); + +#ifdef DEBUG_MACH + if (error != 0) + printf("failure in kernel service %d (err %x, native %d)\n", + req->msgh_id, (int)rep->rep_retval, error); +#endif + return 0; +} + +int +mach_iokit_error(struct mach_trap_args *args, int error) +{ + mach_msg_header_t *req = args->smsg; + mach_error_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = error; + +#ifdef DEBUG_MACH + if (error != 0) + printf("failure in kernel service %d (Mach err %x)\n", + req->msgh_id, error); +#endif + mach_set_trailer(rep, *msglen); + + return 0; +} diff --git a/sys/compat/mach/mach_errno.h b/sys/compat/mach/mach_errno.h new file mode 100644 index 0000000..8a45e5c --- /dev/null +++ b/sys/compat/mach/mach_errno.h @@ -0,0 +1,106 @@ +/* $NetBSD: mach_errno.h,v 1.9 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_ERRNO_H_ +#define _MACH_ERRNO_H_ + +extern int native_to_mach_errno[]; + +#define MACH_KERN_SUCCESS 0 +#define MACH_KERN_INVALID_ADDRESS 1 +#define MACH_KERN_PROTECTION_FAILURE 2 +#define MACH_KERN_NO_SPACE 3 +#define MACH_KERN_INVALID_ARGUMENT 4 +#define MACH_KERN_FAILURE 5 +#define MACH_KERN_RESOURCE_SHORTAGE 6 +#define MACH_KERN_NOT_RECEIVER 7 +#define MACH_KERN_NO_ACCESS 8 +#define MACH_KERN_MEMORY_FAILURE 9 +#define MACH_KERN_MEMORY_ERROR 10 +#define MACH_KERN_ALREADY_IN_SET 11 +#define MACH_KERN_NOT_IN_SET 12 +#define MACH_KERN_NAME_EXISTS 13 +#define MACH_KERN_ABORTED 14 +#define MACH_KERN_INVALID_NAME 15 +#define MACH_KERN_INVALID_TASK 16 +#define MACH_KERN_INVALID_RIGHT 17 +#define MACH_KERN_INVALID_VALUE 18 +#define MACH_KERN_UREFS_OVERFLOW 19 +#define MACH_KERN_INVALID_CAPABILITY 20 +#define MACH_KERN_RIGHT_EXISTS 21 +#define MACH_KERN_INVALID_HOST 22 +#define MACH_KERN_MEMORY_PRESENT 23 +#define MACH_KERN_MEMORY_DATA_MOVED 24 +#define MACH_KERN_MEMORY_RESTART_COPY 25 +#define MACH_KERN_INVALID_PROCESSOR_SET 26 +#define MACH_KERN_POLICY_LIMIT 27 +#define MACH_KERN_INVALID_POLICY 28 +#define MACH_KERN_INVALID_OBJECT 29 +#define MACH_KERN_ALREADY_WAITING 30 +#define MACH_KERN_DEFAULT_SET 31 +#define MACH_KERN_EXCEPTION_PROTECTED 32 +#define MACH_KERN_INVALID_LEDGER 33 +#define MACH_KERN_INVALID_MEMORY_CONTROL 34 +#define MACH_KERN_INVALID_SECURITY 35 +#define MACH_KERN_NOT_DEPRESSED 36 +#define MACH_KERN_TERMINATED 37 +#define MACH_KERN_LOCK_SET_DESTROYED 38 +#define MACH_KERN_LOCK_UNSTABLE 39 +#define MACH_KERN_LOCK_OWNED 40 +#define MACH_KERN_LOCK_OWNED_SELF 41 +#define MACH_KERN_SEMAPHORE_DESTROYED 42 +#define MACH_KERN_RPC_SERVER_TERMINATED 43 +#define MACH_KERN_RPC_TERMINATE_ORPHAN 44 +#define MACH_KERN_RPC_CONTINUE_ORPHAN 45 +#define MACH_KERN_NOT_SUPPORTED 46 +#define MACH_KERN_NODE_DOWN 47 +#define MACH_KERN_NOT_WAITING 48 +#define MACH_KERN_OPERATION_TIMED_OUT 49 + +/* IOKit errors */ +#define MACH_IOKIT_ENOMEM 0xe00002bd +#define MACH_IOKIT_ENODEV 0xe00002c0 +#define MACH_IOKIT_EAGAIN 0xe00002be +#define MACH_IOKIT_EPERM 0xe00002c1 +#define MACH_IOKIT_EINVAL 0xe00002c2 +#define MACH_IOKIT_ENOENT 0xe00002f0 + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_error_reply_t; + +int mach_msg_error(struct mach_trap_args *, int); +int mach_iokit_error(struct mach_trap_args *, int); + +#endif /* _MACH_ERRNO_H_ */ diff --git a/sys/compat/mach/mach_exception.c b/sys/compat/mach/mach_exception.c new file mode 100644 index 0000000..907e122 --- /dev/null +++ b/sys/compat/mach/mach_exception.c @@ -0,0 +1,530 @@ +/* $NetBSD: mach_exception.c,v 1.14 2009/03/14 21:04:18 dsl Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.14 2009/03/14 21:04:18 dsl Exp $"); + +#include "opt_compat_darwin.h" + +#include +#include +#include +#include +#include + +#ifdef COMPAT_DARWIN +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void mach_siginfo_to_exception(const struct ksiginfo *, int *); + +/* + * Exception handler + * Mach does not use signals. But systems based on Mach (e.g.: Darwin), + * can use both Mach exceptions and UNIX signals. In order to allow the + * Mach layer to intercept the exception and inhibit UNIX signals, we have + * mach_trapsignal1 returning an error. If it returns 0, then the + * exception was intercepted at the Mach level, and no signal should + * be produced. Else, a signal might be sent. darwin_trapinfo calls + * mach_trapinfo1 and handle signals if it gets a non zero return value. + */ +void +mach_trapsignal(struct lwp *l, struct ksiginfo *ksi) +{ + if (mach_trapsignal1(l, ksi) != 0) + trapsignal(l, ksi); + return; +} + +int +mach_trapsignal1(struct lwp *l, struct ksiginfo *ksi) +{ + struct proc *p = l->l_proc; + struct mach_emuldata *med; + int exc_no; + int code[2]; + + /* Don't inhinbit non maskable signals */ + if (sigprop[ksi->ksi_signo] & SA_CANTMASK) + return EINVAL; + + med = (struct mach_emuldata *)p->p_emuldata; + + switch (ksi->ksi_signo) { + case SIGILL: + exc_no = MACH_EXC_BAD_INSTRUCTION; + break; + case SIGFPE: + exc_no = MACH_EXC_ARITHMETIC; + break; + case SIGSEGV: + case SIGBUS: + exc_no = MACH_EXC_BAD_ACCESS; + break; + case SIGTRAP: + exc_no = MACH_EXC_BREAKPOINT; + break; + default: /* SIGCHLD, SIGPOLL */ + return EINVAL; + break; + } + + mach_siginfo_to_exception(ksi, code); + + return mach_exception(l, exc_no, code); +} + +int +mach_exception(struct lwp *exc_l, int exc, int *code) + /* exc_l: currently running lwp */ +{ + int behavior, flavor; + mach_msg_header_t *msgh; + size_t msglen; + struct mach_right *exc_mr; + struct mach_emuldata *exc_med; + struct mach_lwp_emuldata *exc_mle; + struct mach_emuldata *catcher_med; + struct mach_right *kernel_mr; + struct lwp *catcher_l; /* The lwp catching the exception */ + struct mach_right *exc_task; + struct mach_right *exc_thread; + struct mach_port *exc_port; + struct mach_exc_info *mei; + int error = 0; + +#ifdef DIAGNOSTIC + if (exc_l == NULL) { + printf("mach_exception: exc_l = %p\n", exc_l); + return ESRCH; + } +#endif +#ifdef DEBUG_MACH + printf("mach_exception: %d.%d, exc %d, code (%d, %d)\n", + exc_l->l_proc->p_pid, exc_l->l_lid, exc, code[0], code[1]); +#endif + + /* + * It's extremely useful to have the ability of catching + * the process at the time it dies. + */ + if (mach_exception_hang) { + struct proc *p = exc_l->l_proc; + + sigminusset(&contsigmask, &exc_l->l_sigpendset->sp_set); + lwp_lock(exc_l); + p->p_pptr->p_nstopchild++; + p->p_stat = SSTOP; + exc_l->l_stat = LSSTOP; + p->p_nrlwps--; + KERNEL_UNLOCK_ALL(exc_l, &exc_l->l_biglocks); + mi_switch(exc_l); + KERNEL_LOCK(exc_l->l_biglocks, exc_l); + } + + /* + * No exception if there is no exception port or if it has no receiver + */ + exc_mle = exc_l->l_emuldata; + exc_med = exc_l->l_proc->p_emuldata; + if ((exc_port = exc_med->med_exc[exc]) == NULL) + return EINVAL; + + MACH_PORT_REF(exc_port); + if (exc_port->mp_recv == NULL) { + error = EINVAL; + goto out; + } + +#ifdef DEBUG_MACH + printf("catcher is %d.%d, state %d\n", + exc_port->mp_recv->mr_lwp->l_proc->p_pid, + exc_port->mp_recv->mr_lwp->l_lid, + exc_port->mp_recv->mr_lwp->l_proc->p_stat); +#endif + /* + * Don't send exceptions to dying processes + */ + if (P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc)) { + error = ESRCH; + goto out; + } + + /* + * XXX Avoid a nasty deadlock because process in TX state + * (traced and suspended) are invulnerable to kill -9. + * + * The scenario: + * - the parent gets Child's signals though Mach exceptions + * - the parent is killed. Before calling the emulation hook + * mach_exit(), it will wait for the child + * - the child receives SIGHUP, which is turned into a Mach + * exception. The child sleeps awaiting for the parent + * to tell it to continue. + * For some reason I do not understand, it goes in the + * suspended state instead of the sleeping state. + * - Parents waits for the child, child is suspended, we + * are stuck. + * + * By preventing exception to traced processes with + * a dying parent, a signal is sent instead of the + * notification, this fixes the problem. + */ + if ((exc_l->l_proc->p_slflag & PSL_TRACED) && + (exc_l->l_proc->p_pptr->p_sflag & PS_WEXIT)) { +#ifdef DEBUG_MACH + printf("mach_exception: deadlock avoided\n"); +#endif + error = EINVAL; + goto out; + } + + if (exc_port->mp_datatype != MACH_MP_EXC_INFO) { +#ifdef DIAGNOSTIC + printf("mach_exception: unexpected datatype"); +#endif + error = EINVAL; + goto out; + } + mei = exc_port->mp_data; + behavior = mei->mei_behavior; + flavor = mei->mei_flavor; + + /* + * We want the port names in the target process, that is, + * the process with receive right for exc_port. + */ + catcher_l = exc_port->mp_recv->mr_lwp; + catcher_med = catcher_l->l_proc->p_emuldata; + exc_mr = mach_right_get(exc_port, catcher_l, MACH_PORT_TYPE_SEND, 0); + kernel_mr = mach_right_get(catcher_med->med_kernel, + catcher_l, MACH_PORT_TYPE_SEND, 0); + + exc_task = mach_right_get(exc_med->med_kernel, + catcher_l, MACH_PORT_TYPE_SEND, 0); + exc_thread = mach_right_get(exc_mle->mle_kernel, + catcher_l, MACH_PORT_TYPE_SEND, 0); + + switch (behavior) { + case MACH_EXCEPTION_DEFAULT: { + mach_exception_raise_request_t *req; + + req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO); + msglen = sizeof(*req); + msgh = (mach_msg_header_t *)req; + + req->req_msgh.msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND) | + MACH_MSGH_REMOTE_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + req->req_msgh.msgh_size = + sizeof(*req) - sizeof(req->req_trailer); + req->req_msgh.msgh_remote_port = kernel_mr->mr_name; + req->req_msgh.msgh_local_port = exc_mr->mr_name; + req->req_msgh.msgh_id = MACH_EXC_RAISE_MSGID; + + mach_add_port_desc(req, exc_thread->mr_name); + mach_add_port_desc(req, exc_task->mr_name); + + req->req_exc = exc; + req->req_codecount = 2; + memcpy(&req->req_code[0], code, sizeof(req->req_code)); + + mach_set_trailer(req, msglen); + + break; + } + + case MACH_EXCEPTION_STATE: { + mach_exception_raise_state_request_t *req; + int dc; + + req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO); + msglen = sizeof(*req); + msgh = (mach_msg_header_t *)req; + + req->req_msgh.msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND) | + MACH_MSGH_REMOTE_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + req->req_msgh.msgh_size = + sizeof(*req) - sizeof(req->req_trailer); + req->req_msgh.msgh_remote_port = kernel_mr->mr_name; + req->req_msgh.msgh_local_port = exc_mr->mr_name; + req->req_msgh.msgh_id = MACH_EXCEPTION_STATE; + req->req_exc = exc; + req->req_codecount = 2; + memcpy(&req->req_code[0], code, sizeof(req->req_code)); + req->req_flavor = flavor; + mach_thread_get_state_machdep(exc_l, + flavor, req->req_state, &dc); + + msglen = msglen - + sizeof(req->req_state) + + (dc * sizeof(req->req_state[0])); + mach_set_trailer(req, msglen); + + break; + } + + case MACH_EXCEPTION_STATE_IDENTITY: { + mach_exception_raise_state_identity_request_t *req; + int dc; + + req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO); + msglen = sizeof(*req); + msgh = (mach_msg_header_t *)req; + + req->req_msgh.msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND) | + MACH_MSGH_REMOTE_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + req->req_msgh.msgh_size = + sizeof(*req) - sizeof(req->req_trailer); + req->req_msgh.msgh_remote_port = kernel_mr->mr_name; + req->req_msgh.msgh_local_port = exc_mr->mr_name; + req->req_msgh.msgh_id = MACH_EXC_RAISE_STATE_IDENTITY_MSGID; + req->req_body.msgh_descriptor_count = 2; + + mach_add_port_desc(req, exc_thread->mr_name); + mach_add_port_desc(req, exc_task->mr_name); + + req->req_exc = exc; + req->req_codecount = 2; + memcpy(&req->req_code[0], code, sizeof(req->req_code)); + req->req_flavor = flavor; + mach_thread_get_state_machdep(exc_l, + flavor, req->req_state, &dc); + + msglen = msglen - + sizeof(req->req_state) + + (dc * sizeof(req->req_state[0])); + + mach_set_trailer(req, msglen); + + break; + } + + default: + printf("unknown exception bevahior %d\n", behavior); + error = EINVAL; + goto out; + break; + } + + mach_set_trailer(msgh, msglen); + + /* + * Once an exception is sent on the exception port, + * no new exception will be taken until the catcher + * acknowledge the first one. + */ + rw_enter(&catcher_med->med_exclock, RW_WRITER); + + /* + * If the catcher died, we are done. + */ + if (((exc_port = exc_med->med_exc[exc]) == NULL) || + (exc_port->mp_recv == NULL) || + (P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc))) { + error = ESRCH; + goto out; + } + + (void)mach_message_get(msgh, msglen, exc_port, NULL); + wakeup(exc_port->mp_recv->mr_sethead); + + /* + * The thread that caused the exception is now + * supposed to wait for a reply to its message. + */ +#ifdef DEBUG_MACH + printf("mach_exception: %d.%d sleep on catcher_med->med_exclock = %p\n", + exc_l->l_proc->p_pid, exc_l->l_lid, &catcher_med->med_exclock); +#endif + error = tsleep(&catcher_med->med_exclock, PZERO, "mach_exc", 0); +#ifdef DEBUG_MACH + printf("mach_exception: %d.%d resumed, error = %d\n", + exc_l->l_proc->p_pid, exc_l->l_lid, error); +#endif + + /* + * Unlock the catcher's exception handler + */ + rw_exit(&catcher_med->med_exclock); + +out: + MACH_PORT_UNREF(exc_port); + return error; +} + +static void +mach_siginfo_to_exception(const struct ksiginfo *ksi, int *code) +{ + code[1] = (long)ksi->ksi_addr; + switch (ksi->ksi_signo) { + case SIGBUS: + switch (ksi->ksi_code) { + case BUS_ADRALN: + code[0] = MACH_BUS_ADRALN; + break; + default: + printf("untranslated siginfo signo %d, code %d\n", + ksi->ksi_signo, ksi->ksi_code); + break; + } + break; + + case SIGSEGV: + switch (ksi->ksi_code) { + case SEGV_MAPERR: + code[0] = MACH_SEGV_MAPERR; + break; + case SEGV_ACCERR: + code[0] = MACH_SEGV_ACCERR; + break; + default: + printf("untranslated siginfo signo %d, code %d\n", + ksi->ksi_signo, ksi->ksi_code); + break; + } + break; + + case SIGTRAP: + switch (ksi->ksi_code) { + case TRAP_BRKPT: + code[0] = MACH_TRAP_BRKPT; + code[1] = (long)ksi->ksi_addr; + break; + default: + printf("untranslated siginfo signo %d, code %d\n", + ksi->ksi_signo, ksi->ksi_code); + break; + } + break; + + case SIGILL: + switch (ksi->ksi_code) { + case ILL_ILLOPC: + case ILL_ILLOPN: + case ILL_ILLADR: + code[0] = MACH_ILL_ILLOPC; + break; + case ILL_PRVOPC: + case ILL_PRVREG: + code[0] = MACH_ILL_PRVOPC; + break; + case ILL_ILLTRP: + code[0] = MACH_ILL_ILLTRP; + break; + default: + printf("untranslated siginfo signo %d, code %d\n", + ksi->ksi_signo, ksi->ksi_code); + break; + } + break; + + default: + printf("untranslated siginfo signo %d, code %d\n", + ksi->ksi_signo, ksi->ksi_code); + break; + } +} + +int +mach_exception_raise(struct mach_trap_args *args) +{ + struct lwp *l = args->l; + mach_exception_raise_reply_t *rep; + struct mach_emuldata *med; + + /* + * No typo here: the reply is in the sent message. + * The kernel is acting as a client that gets the + * reply message to its exception message. + */ + rep = args->smsg; + + /* + * This message is sent by the process catching the + * exception to release the process that raised the exception. + * We wake it up if the return value is 0 (no error), else + * we should ignore this message. + */ +#ifdef DEBUG_MACH + printf("mach_excpetion_raise: retval = %ld\n", (long)rep->rep_retval); +#endif + if (rep->rep_retval != 0) + return 0; + + med = l->l_proc->p_emuldata; + + /* + * Check for unexpected exception acknowledge, whereas + * the kernel sent no exception message. + */ + if (!rw_lock_held(&med->med_exclock)) { +#ifdef DEBUG_MACH + printf("spurious mach_exception_raise\n"); +#endif + return mach_msg_error(args, EINVAL); + } + + /* + * Wakeup the thread that raised the exception. + */ +#ifdef DEBUG_MACH + printf("mach_exception_raise: wakeup at %p\n", &med->med_exclock); +#endif + wakeup(&med->med_exclock); + + return 0; +} + +int +mach_exception_raise_state(struct mach_trap_args *args) +{ + return mach_exception_raise(args); +} + +int +mach_exception_raise_state_identity(struct mach_trap_args *args) +{ + return mach_exception_raise(args); +} diff --git a/sys/compat/mach/mach_exception.h b/sys/compat/mach/mach_exception.h new file mode 100644 index 0000000..de1e630 --- /dev/null +++ b/sys/compat/mach/mach_exception.h @@ -0,0 +1,160 @@ +/* $NetBSD: mach_exception.h,v 1.8 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_EXCEPTION_H_ +#define _MACH_EXCEPTION_H_ + +/* really should be in mach_signal.h or siginfo.h */ +#define MACH_BUS_ADRALN 1 + +#define MACH_SEGV_MAPERR 1 +#define MACH_SEGV_ACCERR 2 + +#define MACH_TRAP_BRKPT 1 + +#define MACH_ILL_ILLOPC 1 +#define MACH_ILL_ILLTRP 2 +#define MACH_ILL_PRVOPC 3 + +#define MACH_EXC_BAD_ACCESS 1 +#define MACH_EXC_BAD_INSTRUCTION 2 +#define MACH_EXC_ARITHMETIC 3 +#define MACH_EXC_EMULATION 4 +#define MACH_EXC_SOFTWARE 5 +#define MACH_EXC_BREAKPOINT 6 +#define MACH_EXC_SYSCALL 7 +#define MACH_EXC_MACH_SYSCALL 8 +#define MACH_EXC_RPC_ALERT 9 +#define MACH_EXC_MAX MACH_EXC_RPC_ALERT + +#define MACH_EXC_MASK_BAD_ACCESS (1 << MACH_EXC_BAD_ACCESS) +#define MACH_EXC_MASK_BAD_INSTRUCTION (1 << MACH_EXC_BAD_INSTRUCTION) +#define MACH_EXC_MASK_ARITHMETIC (1 << MACH_EXC_ARITHMETIC) +#define MACH_EXC_MASK_EMULATION (1 << MACH_EXC_EMULATION) +#define MACH_EXC_MASK_SOFTWARE (1 << MACH_EXC_SOFTWARE) +#define MACH_EXC_MASK_BREAKPOINT (1 << MACH_EXC_BREAKPOINT) +#define MACH_EXC_MASK_SYSCALL (1 << MACH_EXC_SYSCALL) +#define MACH_EXC_MASK_MACH_SYSCALL (1 << MACH_EXC_MACH_SYSCALL) +#define MACH_EXC_MASK_RPC_ALERT (1 << MACH_EXC_RPC_ALERT) + +/* + * Exception codes. Values < 0x10000 are machine dependent, and + * are defined in sys//include/mach_machdep.h. + */ +#define MACH_EXC_UNIX_BAD_SYSCALL 0x10000 /* unused ? */ +#define MACH_EXC_UNIX_BAD_PIPE 0x10001 /* unused ? */ +#define MACH_EXC_UNIX_ABORT 0x10002 /* unused ? */ +#define MACH_SOFT_SIGNAL 0x10003 + +/* Exception behaviors and associated messages Id */ + +#define MACH_EXCEPTION_DEFAULT 1 +#define MACH_EXCEPTION_STATE 2 +#define MACH_EXCEPTION_STATE_IDENTITY 3 + +#define MACH_EXC_RAISE_MSGID 2401 +#define MACH_EXC_RAISE_STATE_MSGID 2402 +#define MACH_EXC_RAISE_STATE_IDENTITY_MSGID 2403 + +/* exception_raise. The kernel is the client, not the server */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_thread; + mach_msg_port_descriptor_t req_task; + mach_ndr_record_t req_ndr; + mach_exception_type_t req_exc; + mach_msg_type_number_t req_codecount; + mach_integer_t req_code[2]; + mach_msg_trailer_t req_trailer; +} mach_exception_raise_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; +} mach_exception_raise_reply_t; + +/* exception_raise_state. The kernel is the client, not the server */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_exception_type_t req_exc; + mach_msg_type_number_t req_codecount; + mach_integer_t req_code[2]; + int req_flavor; + mach_msg_type_number_t req_statecount; + mach_natural_t req_state[144]; + mach_msg_trailer_t req_trailer; +} mach_exception_raise_state_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; +} mach_exception_raise_state_reply_t; + +/* exception_raise_state_identity. The kernel is the client, not the server */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_thread; + mach_msg_port_descriptor_t req_task; + mach_ndr_record_t req_ndr; + mach_exception_type_t req_exc; + mach_msg_type_number_t req_codecount; + mach_integer_t req_code[2]; + int req_flavor; + mach_msg_type_number_t req_statecount; + mach_natural_t req_state[144]; + mach_msg_trailer_t req_trailer; +} mach_exception_raise_state_identity_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; +} mach_exception_raise_state_identity_reply_t; + +struct mach_exc_info { + int mei_flavor; + int mei_behavior; +}; + +void mach_trapsignal(struct lwp *, struct ksiginfo *); +int mach_trapsignal1(struct lwp *, struct ksiginfo *); +int mach_exception(struct lwp *, int, int *); + +#endif /* _MACH_EXCEPTION_H_ */ + diff --git a/sys/compat/mach/mach_exec.c b/sys/compat/mach/mach_exec.c new file mode 100644 index 0000000..ac46629 --- /dev/null +++ b/sys/compat/mach/mach_exec.c @@ -0,0 +1,458 @@ +/* $NetBSD: mach_exec.c,v 1.74 2010/07/25 11:25:57 jym Exp $ */ + +/*- + * Copyright (c) 2001-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas and Emmanuel Dreyfus. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.74 2010/07/25 11:25:57 jym Exp $"); + +#include "opt_syscall_debug.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +static int mach_cold = 1; /* Have we initialized COMPAT_MACH structures? */ +static void mach_init(void); + +extern struct sysent sysent[]; +extern const char * const mach_syscallnames[]; +#ifndef __HAVE_SYSCALL_INTERN +void syscall(void); +#else +void mach_syscall_intern(struct proc *); +#endif + +#ifdef COMPAT_16 +extern char sigcode[], esigcode[]; +struct uvm_object *emul_mach_object; +#endif + +struct emul emul_mach = { + .e_name = "mach", + .e_path = "/emul/mach", +#ifndef __HAVE_MINIMAL_EMUL + .e_flags = 0, + .e_errno = NULL, + .e_nosys = SYS_syscall, + .e_nsysent = SYS_NSYSENT, +#endif + .e_sysent = sysent, +#ifdef SYSCALL_DEBUG + .e_syscallnames = mach_syscallnames, +#else + .e_syscallnames = NULL, +#endif + .e_sendsig = sendsig, + .e_trapsignal = mach_trapsignal, + .e_tracesig = NULL, +#ifdef COMPAT_16 + .e_sigcode = sigcode, + .e_esigcode = esigcode, + .e_sigobject = &emul_mach_object, +#else + .e_sigcode = NULL, + .e_esigcode = NULL, + .e_sigobject = NULL, +#endif + .e_setregs = setregs, + .e_proc_exec = mach_e_proc_exec, + .e_proc_fork = mach_e_proc_fork, + .e_proc_exit = mach_e_proc_exit, + .e_lwp_fork = mach_e_lwp_fork, + .e_lwp_exit = mach_e_lwp_exit, +#ifdef __HAVE_SYSCALL_INTERN + .e_syscall_intern = mach_syscall_intern, +#else + .e_syscall_intern = syscall, +#endif + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL +}; + +/* + * Copy arguments onto the stack in the normal way, but add some + * extra information in case of dynamic binding. + * XXX This needs a cleanup: it is not used anymore by the Darwin + * emulation, and it probably contains Darwin specific bits. + */ +int +exec_mach_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) +{ + struct exec_macho_emul_arg *emea; + struct exec_macho_object_header *macho_hdr; + size_t len; + size_t zero = 0; + int error; + + *stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL); + + emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg; + macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr; + if ((error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr))) != 0) + return error; + + *stackp += sizeof(macho_hdr); + + if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) { + DPRINTF(("mach: copyargs failed\n")); + return error; + } + + if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0) + return error; + *stackp += sizeof(zero); + + if ((error = copyoutstr(emea->filename, + *stackp, MAXPATHLEN, &len)) != 0) { + DPRINTF(("mach: copyout path failed\n")); + return error; + } + *stackp += len + 1; + + /* We don't need this anymore */ + free(pack->ep_emul_arg, M_TEMP); + pack->ep_emul_arg = NULL; + + len = len % sizeof(zero); + if (len) { + if ((error = copyout(&zero, *stackp, len)) != 0) + return error; + *stackp += len; + } + + if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0) + return error; + *stackp += sizeof(zero); + + return 0; +} + +int +exec_mach_probe(const char **path) +{ + *path = emul_mach.e_path; + return 0; +} + +void +mach_e_proc_exec(struct proc *p, struct exec_package *epp) +{ + mach_e_proc_init(p); + + if (p->p_emul != epp->ep_esch->es_emul) { + struct lwp *l = LIST_FIRST(&p->p_lwps); + KASSERT(l != NULL); + mach_e_lwp_fork(NULL, l); + } + + return; +} + +void +mach_e_proc_fork(struct proc *p2, struct lwp *l1, int forkflags) +{ + mach_e_proc_fork1(p2, l1, 1); + return; +} + +void +mach_e_proc_fork1(struct proc *p2, struct lwp *l1, int allocate) +{ + struct mach_emuldata *med1; + struct mach_emuldata *med2; + int i; + + /* + * For Darwin binaries, p2->p_emuldata has already been + * allocated, no need to throw it away and allocate it again. + */ + if (allocate) + p2->p_emuldata = NULL; + + mach_e_proc_init(p2); + + med1 = p2->p_emuldata; + med2 = l1->l_proc->p_emuldata; + + /* + * Exception ports are inherited between forks, + * but we need to double their reference counts, + * since the ports are referenced by rights in the + * parent and in the child. + * + * XXX we need to convert all the parent's rights + * to the child namespace. This will make the + * following fixup obsolete. + */ + for (i = 0; i <= MACH_EXC_MAX; i++) { + med1->med_exc[i] = med2->med_exc[i]; + if (med1->med_exc[i] != NULL) + med1->med_exc[i]->mp_refcount *= 2; + } + + return; +} + +void +mach_e_proc_init(struct proc *p) +{ + struct mach_emuldata *med; + struct mach_right *mr; + + /* + * Initialize various things if needed. + * XXX Not the best place for this. + */ + if (mach_cold == 1) + mach_init(); + + /* + * For Darwin binaries, p->p_emuldata is always allocated: + * from the previous program if it had the same emulation, + * or from darwin_e_proc_exec(). In the latter situation, + * everything has been set to zero. + */ + if (!p->p_emuldata) { +#ifdef DIAGNOSTIC + if (p->p_emul != &emul_mach) + printf("mach_emuldata allocated for non Mach binary\n"); +#endif + p->p_emuldata = malloc(sizeof(struct mach_emuldata), + M_EMULDATA, M_WAITOK | M_ZERO); + } + + med = (struct mach_emuldata *)p->p_emuldata; + + /* + * p->p_emudata has med_inited set if we inherited it from + * the program that called exec(). In that situation, we + * must free anything that will not be used anymore. + */ + if (med->med_inited != 0) { + rw_enter(&med->med_rightlock, RW_WRITER); + while ((mr = LIST_FIRST(&med->med_right)) != NULL) + mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS); + rw_exit(&med->med_rightlock); + + /* + * Do not touch special ports. Some other process (eg: gdb) + * might have grabbed them to control the process, and the + * controller intend to keep in control even after exec(). + */ + } else { + /* + * p->p_emuldata is uninitialized. Go ahead and initialize it. + */ + LIST_INIT(&med->med_right); + rw_init(&med->med_rightlock); + rw_init(&med->med_exclock); + + /* + * For debugging purpose, it's convenient to have each process + * using distinct port names, so we prefix the first port name + * by the PID. Darwin does not do that, but we can remove it + * when we want, it will not hurt. + */ + med->med_nextright = p->p_pid << 16; + + /* + * Initialize special ports. Bootstrap port is shared + * among all Mach processes in our implementation. + */ + med->med_kernel = mach_port_get(); + med->med_host = mach_port_get(); + + med->med_kernel->mp_flags |= MACH_MP_INKERNEL; + med->med_host->mp_flags |= MACH_MP_INKERNEL; + + med->med_kernel->mp_data = (void *)p; + med->med_host->mp_data = (void *)p; + + med->med_kernel->mp_datatype = MACH_MP_PROC; + med->med_host->mp_datatype = MACH_MP_PROC; + + MACH_PORT_REF(med->med_kernel); + MACH_PORT_REF(med->med_host); + + med->med_bootstrap = mach_bootstrap_port; + MACH_PORT_REF(med->med_bootstrap); + } + + /* + * Exception ports are inherited accross exec() calls. + * If the structure is initialized, the ports are just + * here, so leave them untouched. If the structure is + * uninitalized, the ports are all set to zero, which + * is the default, so do not touch them either. + */ + + med->med_dirty_thid = 1; + med->med_suspend = 0; + med->med_inited = 1; + + return; +} + +void +mach_e_proc_exit(struct proc *p) +{ + struct mach_emuldata *med; + struct mach_right *mr; + struct lwp *l; + int i; + + /* There is only one lwp remaining... */ + l = LIST_FIRST(&p->p_lwps); + KASSERT(l != NULL); + mach_e_lwp_exit(l); + + med = (struct mach_emuldata *)p->p_emuldata; + + rw_enter(&med->med_rightlock, RW_WRITER); + while ((mr = LIST_FIRST(&med->med_right)) != NULL) + mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS); + rw_exit(&med->med_rightlock); + + MACH_PORT_UNREF(med->med_bootstrap); + + /* + * If the lock on this task exception handler is held, + * release it now as it will never be released by the + * exception handler. + */ + if (rw_lock_held(&med->med_exclock)) + wakeup(&med->med_exclock); + + /* + * If the kernel and host port are still referenced, remove + * the pointer to this process' struct proc, as it will + * become invalid once the process will exit. + */ + med->med_kernel->mp_datatype = MACH_MP_NONE; + med->med_kernel->mp_data = NULL; + MACH_PORT_UNREF(med->med_kernel); + + med->med_host->mp_datatype = MACH_MP_NONE; + med->med_host->mp_data = NULL; + MACH_PORT_UNREF(med->med_host); + + for (i = 0; i <= MACH_EXC_MAX; i++) + if (med->med_exc[i] != NULL) + MACH_PORT_UNREF(med->med_exc[i]); + + rw_destroy(&med->med_exclock); + rw_destroy(&med->med_rightlock); + free(med, M_EMULDATA); + p->p_emuldata = NULL; + + return; +} + +void +mach_e_lwp_fork(struct lwp *l1, struct lwp *l2) +{ + struct mach_lwp_emuldata *mle; + + mle = malloc(sizeof(*mle), M_EMULDATA, M_WAITOK); + l2->l_emuldata = mle; + + mle->mle_kernel = mach_port_get(); + MACH_PORT_REF(mle->mle_kernel); + + mle->mle_kernel->mp_flags |= MACH_MP_INKERNEL; + mle->mle_kernel->mp_datatype = MACH_MP_LWP; + mle->mle_kernel->mp_data = (void *)l2; + +#if 0 + /* Nothing to copy from parent thread for now */ + if (l1 != NULL); +#endif + + return; +} + +void +mach_e_lwp_exit(struct lwp *l) +{ + struct mach_lwp_emuldata *mle; + + mach_semaphore_cleanup(l); + +#ifdef DIAGNOSTIC + if (l->l_emuldata == NULL) { + printf("lwp_emuldata already freed\n"); + return; + } +#endif + mle = l->l_emuldata; + + mle->mle_kernel->mp_data = NULL; + mle->mle_kernel->mp_datatype = MACH_MP_NONE; + MACH_PORT_UNREF(mle->mle_kernel); + + free(mle, M_EMULDATA); + l->l_emuldata = NULL; + + return; +} + +static void +mach_init(void) +{ + mach_semaphore_init(); + mach_message_init(); + mach_port_init(); + + mach_cold = 0; + + return; +} diff --git a/sys/compat/mach/mach_exec.h b/sys/compat/mach/mach_exec.h new file mode 100644 index 0000000..06a8914 --- /dev/null +++ b/sys/compat/mach/mach_exec.h @@ -0,0 +1,78 @@ +/* $NetBSD: mach_exec.h,v 1.35 2011/03/05 23:51:47 joerg Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_EXEC_H_ +#define _MACH_EXEC_H_ + +#include + +#include +#include +#include +#include + + +struct mach_emuldata { + int med_inited; /* Is this structure initialized? */ + int med_thpri; /* Saved priority */ + LIST_HEAD(med_right, mach_right) med_right; + krwlock_t med_rightlock; /* process right list and lock */ + mach_port_t med_nextright; /* next unused right */ + + struct mach_port *med_bootstrap;/* task bootstrap port */ + struct mach_port *med_kernel; /* task kernel port */ + struct mach_port *med_host; /* task host port */ + struct mach_port *med_exc[MACH_EXC_MAX + 1]; /* Exception ports */ + + int med_dirty_thid; /* Thread id not yet initialized */ + int med_suspend; /* Suspend semaphore */ + krwlock_t med_exclock; /* Process exception handler lock */ +}; + +struct mach_lwp_emuldata { + struct mach_port *mle_kernel; /* Thread's kernel port */ +}; + +struct ps_strings; +int exec_mach_copyargs(struct lwp *, struct exec_package *, + struct ps_strings *, char **, void *); +int exec_mach_probe(const char **); +void mach_e_proc_init(struct proc *); +void mach_e_proc_exit(struct proc *); +void mach_e_proc_exec(struct proc *, struct exec_package *); +void mach_e_proc_fork(struct proc *, struct lwp *, int); +void mach_e_proc_fork1(struct proc *, struct lwp *, int); +void mach_e_lwp_fork(struct lwp *, struct lwp *); +void mach_e_lwp_exit(struct lwp *); + +extern struct emul emul_mach; + +#endif /* !_MACH_EXEC_H_ */ diff --git a/sys/compat/mach/mach_host.c b/sys/compat/mach/mach_host.c new file mode 100644 index 0000000..767348c --- /dev/null +++ b/sys/compat/mach/mach_host.c @@ -0,0 +1,241 @@ +/* $NetBSD: mach_host.c,v 1.31 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_host.c,v 1.31 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +int +mach_host_info(struct mach_trap_args *args) +{ + mach_host_info_request_t *req = args->smsg; + mach_host_info_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + mach_host_info_reply_simple_t *reps; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + switch(req->req_flavor) { + case MACH_HOST_BASIC_INFO: { + struct mach_host_basic_info *info + = (struct mach_host_basic_info *)&rep->rep_data[0]; + + rep->rep_msgh.msgh_size = sizeof(*reps) + - sizeof(rep->rep_trailer) + sizeof(*info); + rep->rep_count = sizeof(*info) / sizeof(mach_integer_t); + mach_host_basic_info(info); + break; + } + + case MACH_HOST_PRIORITY_INFO: { + struct mach_host_priority_info *info + = (struct mach_host_priority_info *)&rep->rep_data[0]; + + rep->rep_msgh.msgh_size = sizeof(*reps) + - sizeof(rep->rep_trailer) + sizeof(*info); + rep->rep_count = sizeof(*info) / sizeof(mach_integer_t); + mach_host_priority_info(info); + break; + } + + case MACH_HOST_SEMAPHORE_TRAPS: + case MACH_HOST_MACH_MSG_TRAP: + reps = (mach_host_info_reply_simple_t *)rep; + reps->rep_msgh.msgh_size = + sizeof(*reps) - sizeof(reps->rep_trailer); + *msglen = sizeof(*reps); + break; + + case MACH_HOST_SCHED_INFO: { + struct mach_host_sched_info *info + = (struct mach_host_sched_info *)&rep->rep_data[0]; + + rep->rep_msgh.msgh_size = sizeof(*reps) + - sizeof(rep->rep_trailer) + sizeof(*info); + rep->rep_count = sizeof(*info) / sizeof(mach_integer_t); + + info->min_timeout = 1000 / hz; /* XXX timout in ms */ + info->min_quantum = 1000 / hz; /* quantum in ms */ + + break; + } + + case MACH_HOST_RESOURCE_SIZES: + uprintf("mach_host_info() Unimplemented host_info flavor %d\n", + req->req_flavor); + default: + uprintf("Unknown host_info flavor %d\n", req->req_flavor); + rep->rep_retval = native_to_mach_errno[EINVAL]; + break; + } + + mach_set_trailer(rep, *msglen); + + return 0; +} + + +int +mach_host_page_size(struct mach_trap_args *args) +{ + mach_host_page_size_request_t *req = args->smsg; + mach_host_page_size_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_page_size = PAGE_SIZE; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_host_get_clock_service(struct mach_trap_args *args) +{ + mach_host_get_clock_service_request_t *req = args->smsg; + mach_host_get_clock_service_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_right *mr; + + mr = mach_right_get(mach_clock_port, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +void +mach_host_priority_info(struct mach_host_priority_info *info) +{ + /* XXX One day, try to fill this correctly */ + info->kernel_priority = 0x50; + info->system_priority = 0x50; + info->server_priority = 0x40; + info->user_priority = 0x1f; + info->depress_priority = 0x00; + info->idle_priority = 0x00; + info->minimum_priority = 0x00; + info->maximum_priority = 0x4f; + + return; +} + +int +mach_host_get_io_master(struct mach_trap_args *args) +{ + mach_host_get_io_master_request_t *req = args->smsg; + mach_host_get_io_master_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_right *mr; + + mr = mach_right_get(mach_io_master_port, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_processor_set_default(struct mach_trap_args *args) +{ + mach_processor_set_default_request_t *req = args->smsg; + mach_processor_set_default_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_right *mr; + struct mach_port *mp; + + mp = mach_port_get(); + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_host_processor_set_priv(struct mach_trap_args *args) +{ + mach_host_processor_set_priv_request_t *req = args->smsg; + mach_host_processor_set_priv_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_right *smr; + struct mach_port *smp; + + mn = req->req_set.name; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EINVAL); + + smp = mach_port_get(); + smr = mach_right_get(smp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, smr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} diff --git a/sys/compat/mach/mach_host.h b/sys/compat/mach/mach_host.h new file mode 100644 index 0000000..ed57c90 --- /dev/null +++ b/sys/compat/mach/mach_host.h @@ -0,0 +1,184 @@ +/* $NetBSD: mach_host.h,v 1.17 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_HOST_H_ +#define _MACH_HOST_H_ + +#include +#include +#include +#include + +#include +#include + +/* host_info */ + +typedef mach_integer_t mach_host_flavor_t; + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_host_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_host_info_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_count; + mach_integer_t rep_data[12]; + mach_msg_trailer_t rep_trailer; +} mach_host_info_reply_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_count; + mach_msg_trailer_t rep_trailer; +} mach_host_info_reply_simple_t; + +#define MACH_HOST_BASIC_INFO 1 +#define MACH_HOST_SCHED_INFO 3 +#define MACH_HOST_RESOURCE_SIZES 4 +#define MACH_HOST_PRIORITY_INFO 5 +#define MACH_HOST_SEMAPHORE_TRAPS 7 +#define MACH_HOST_MACH_MSG_TRAP 8 + +struct mach_host_basic_info { + mach_integer_t max_cpus; + mach_integer_t avail_cpus; + mach_vm_size_t memory_size; + mach_cpu_type_t cpu_type; + mach_cpu_subtype_t cpu_subtype; +}; + +struct mach_host_sched_info { + mach_integer_t min_timeout; + mach_integer_t min_quantum; +}; + +struct mach_kernel_resource_sizes { + mach_vm_size_t task; + mach_vm_size_t thread; + mach_vm_size_t port; + mach_vm_size_t memory_region; + mach_vm_size_t memory_object; +}; + +struct mach_host_priority_info { + mach_integer_t kernel_priority; + mach_integer_t system_priority; + mach_integer_t server_priority; + mach_integer_t user_priority; + mach_integer_t depress_priority; + mach_integer_t idle_priority; + mach_integer_t minimum_priority; + mach_integer_t maximum_priority; +}; + +/* host_page_size */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_host_page_size_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_vm_size_t rep_page_size; + mach_msg_trailer_t rep_trailer; +} mach_host_page_size_reply_t; + +/* host_get_clock_service */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_clock_id_t req_clock_id; +} mach_host_get_clock_service_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_clock_serv; + mach_msg_trailer_t rep_trailer; +} mach_host_get_clock_service_reply_t; + +/* host_get_io_master */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_host_get_io_master_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_iomaster; + mach_msg_trailer_t rep_trailer; +} mach_host_get_io_master_reply_t; + +/* processor_set_default */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_processor_set_default_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_defaultset; + mach_msg_trailer_t rep_trailer; +} mach_processor_set_default_reply_t; + +/* host_processor_set_priv */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_set; +} mach_host_processor_set_priv_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_ctlset; + mach_msg_trailer_t rep_trailer; +} mach_host_processor_set_priv_reply_t; + +/* These are machine dependent functions */ +void mach_host_basic_info(struct mach_host_basic_info *); +void mach_host_priority_info(struct mach_host_priority_info *); + +#endif /* _MACH_HOST_H_ */ diff --git a/sys/compat/mach/mach_iokit.c b/sys/compat/mach/mach_iokit.c new file mode 100644 index 0000000..502ea2b --- /dev/null +++ b/sys/compat/mach/mach_iokit.c @@ -0,0 +1,1211 @@ +/* $NetBSD: mach_iokit.c,v 1.36 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_compat_darwin.h" +#include +__KERNEL_RCSID(0, "$NetBSD: mach_iokit.c,v 1.36 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef COMPAT_DARWIN +#include +#endif + +struct mach_iokit_devclass mach_ioroot_devclass = { + "(unknwon)", + { NULL }, + "", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Root", + NULL, +}; + +struct mach_iokit_devclass *mach_iokit_devclasses[] = { + &mach_ioroot_devclass, +#ifdef COMPAT_DARWIN + DARWIN_IOKIT_DEVCLASSES +#endif + NULL, +}; + + +static int mach_fill_child_iterator(struct mach_device_iterator *, int, int, + struct mach_iokit_devclass *); +static int mach_fill_parent_iterator(struct mach_device_iterator *, int, int, + struct mach_iokit_devclass *); + +int +mach_io_service_get_matching_services(struct mach_trap_args *args) +{ + mach_io_service_get_matching_services_request_t *req = args->smsg; + mach_io_service_get_matching_services_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + struct mach_device_iterator *mdi; + size_t size; + int end_offset; + int i; + + /* Sanity check req_size */ + end_offset = req->req_size; + if (MACH_REQMSG_OVERFLOW(args, req->req_string[end_offset])) + return mach_msg_error(args, EINVAL); + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + mp->mp_data = NULL; + i = 0; + while ((mid = mach_iokit_devclasses[i++]) != NULL) { + if (memcmp(req->req_string, mid->mid_string, + req->req_size) == 0) { + mp->mp_datatype = MACH_MP_DEVICE_ITERATOR; + + size = sizeof(*mdi) + + sizeof(struct mach_device_iterator *); + mdi = malloc(size, M_EMULDATA, M_WAITOK); + mdi->mdi_devices[0] = mid; + mdi->mdi_devices[1] = NULL; + mdi->mdi_current = 0; + + mp->mp_data = mdi; + break; + } + } + + if (mp->mp_data == NULL) + return mach_iokit_error(args, MACH_IOKIT_ENOENT); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_iterator_next(struct mach_trap_args *args) +{ + mach_io_iterator_next_request_t *req = args->smsg; + mach_io_iterator_next_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + struct mach_device_iterator *mdi; + mach_port_t mn; + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + mdi = mr->mr_port->mp_data; + + /* Is there something coming next? */ + if (mdi->mdi_devices[mdi->mdi_current] == NULL) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS; + mp->mp_data = mdi->mdi_devices[mdi->mdi_current++]; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_service_open(struct mach_trap_args *args) +{ + mach_io_service_open_request_t *req = args->smsg; + mach_io_service_open_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + mach_port_t mn; + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS; + mp->mp_data = mr->mr_port->mp_data; + } + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_connect_method_scalari_scalaro(struct mach_trap_args *args) +{ + mach_io_connect_method_scalari_scalaro_request_t *req = args->smsg; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + int end_offset, outcount; + + /* + * Sanity check req_incount + * the +1 gives us the last field of the message, req_outcount + */ + end_offset = req->req_incount + + (sizeof(req->req_outcount) / sizeof(req->req_in[0])); + if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset])) + return mach_msg_error(args, EINVAL); + + /* Sanity check req->req_outcount */ + outcount = req->req_in[req->req_incount]; + if (outcount > 16) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mid = mr->mr_port->mp_data; + if (mid->mid_connect_method_scalari_scalaro == NULL) + printf("no connect_method_scalari_scalaro method " + "for darwin_iokit_class %s\n", mid->mid_name); + else + return (mid->mid_connect_method_scalari_scalaro)(args); + } + + return mach_iokit_error(args, MACH_IOKIT_ENODEV); +} + +int +mach_io_connect_get_service(struct mach_trap_args *args) +{ + mach_io_connect_get_service_request_t *req = args->smsg; + mach_io_connect_get_service_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + mach_port_t mn; + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS; + mp->mp_data = mr->mr_port->mp_data; + } + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + /* + * XXX Bump the refcount to workaround an emulation bug + * that causes Windowserver to release the port too early. + */ + mr->mr_refcount++; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_create_iterator(struct mach_trap_args *args) +{ + mach_io_registry_entry_create_iterator_request_t *req = args->smsg; + mach_io_registry_entry_create_iterator_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + struct mach_device_iterator *mdi; + struct mach_iokit_devclass **midp; + int maxdev, index; + size_t size; + int end_offset; + + /* + * req_planeoffset is not used. + * Sanity check req_planecount + */ + end_offset = req->req_planecount + + (sizeof(req->req_options) / sizeof(req->req_plane[0])); + if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset])) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data; + + mp = mach_port_get(); + mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED); + mp->mp_datatype = MACH_MP_DEVICE_ITERATOR; + + maxdev = sizeof(mach_iokit_devclasses); + size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *)); + mdi = malloc(size, M_EMULDATA, M_WAITOK); + mp->mp_data = mdi; + + if (req->req_options & MACH_IOKIT_PARENT_ITERATOR) + index = mach_fill_parent_iterator(mdi, maxdev, 0, mid); + else + index = mach_fill_child_iterator(mdi, maxdev, 0, mid); + + /* XXX This is untested */ + if (req->req_options & MACH_IOKIT_RECURSIVE_ITERATOR) { + for (midp = mdi->mdi_devices; *midp != NULL; midp++) { + if (req->req_options & MACH_IOKIT_PARENT_ITERATOR) + index = mach_fill_parent_iterator(mdi, + maxdev, index, *midp); + else + index = mach_fill_child_iterator(mdi, + maxdev, index, *midp); + } + } + + mdi->mdi_current = 0; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + +#ifdef DEBUG_MACH + printf("io_registry_entry_create_iterator\n"); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_object_conforms_to(struct mach_trap_args *args) +{ + mach_io_object_conforms_to_request_t *req = args->smsg; + mach_io_object_conforms_to_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + int end_offset; + + /* + * req_classnameoffset is not used. + * Sanity check req_classnamecount. + */ + end_offset = req->req_classnamecount; + if (MACH_REQMSG_OVERFLOW(args, req->req_classname[end_offset])) + return mach_msg_error(args, EINVAL); + +#ifdef DEBUG_DARWIN + uprintf("Unimplemented mach_io_object_conforms_to\n"); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_conforms = 1; /* XXX */ + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_service_add_interest_notification(struct mach_trap_args *args) +{ + mach_io_service_add_interest_notification_request_t *req = args->smsg; + mach_io_service_add_interest_notification_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + int end_offset, refcount_offset; + int item_size, refitem_size, refcount; + + /* + * req_typeofinterestoffset is not used. + * Sanity checks: first check refcount is not + * outside the message. NB: it is word aligned + */ + refcount_offset = (req->req_typeofinterestcount & ~0x3UL) + 4; + if (MACH_REQMSG_OVERFLOW(args, + req->req_typeofinterest[refcount_offset])) + return mach_msg_error(args, EINVAL); + refcount = req->req_typeofinterest[refcount_offset]; + + /* + * Sanity check typeofinterestcount and refcount + */ + item_size = sizeof(req->req_typeofinterest[0]); + refitem_size = sizeof(req->req_ref[0]); + end_offset = req->req_typeofinterestcount + + (sizeof(refcount) / item_size) + + (refcount * refitem_size / item_size); + if (MACH_REQMSG_OVERFLOW(args, req->req_typeofinterest[end_offset])) + return mach_msg_error(args, EINVAL); + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + +#ifdef DEBUG_DARWIN + uprintf("Unimplemented mach_io_service_add_interest_notification\n"); +#endif + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_connect_set_notification_port(struct mach_trap_args *args) +{ + mach_io_connect_set_notification_port_request_t *req = args->smsg; + mach_io_connect_set_notification_port_reply_t *rep = args->rmsg; + struct lwp *l = args->l; + size_t *msglen = args->rsize; + mach_port_t mnn, mn; + struct mach_right *mrn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + +#ifdef DEBUG_DARWIN + printf("mach_io_connect_set_notification_port\n"); +#endif + mnn = req->req_port.name; + if ((mrn = mach_right_check(mnn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EINVAL); + + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_msg_error(args, EINVAL); + +#ifdef DEBUG_DARWIN + printf("notification on right %p, name %x\n", mrn, mrn->mr_name); +#endif + mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data; + mid->mid_notify = mrn; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_get_root_entry(struct mach_trap_args *args) +{ + mach_io_registry_get_root_entry_request_t *req = args->smsg; + mach_io_registry_get_root_entry_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS; + mp->mp_data = &mach_ioroot_devclass; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_child_iterator(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_child_iterator_request_t *req = args->smsg; + mach_io_registry_entry_get_child_iterator_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + mach_port_t mn; + struct mach_iokit_devclass *mid; + struct mach_device_iterator *mdi; + int maxdev; + size_t size; + int end_offset; + + /* + * req_planeoffset is not used. + * Sanity check req_planecount. + */ + end_offset = req->req_planecount; + if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset])) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + mid = (struct mach_iokit_devclass *)mr->mr_port->mp_data; + + mp = mach_port_get(); + mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED); + mp->mp_datatype = MACH_MP_DEVICE_ITERATOR; + + maxdev = sizeof(mach_iokit_devclasses); + size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *)); + mdi = malloc(size, M_EMULDATA, M_WAITOK); + mp->mp_data = mdi; + + (void)mach_fill_child_iterator(mdi, maxdev, 0, mid); + mdi->mdi_current = 0; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_name_in_plane(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_name_in_plane_request_t *req = args->smsg; + mach_io_registry_entry_get_name_in_plane_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_right *mr; + mach_port_t mn; + struct mach_iokit_devclass *mid; + int end_offset; + + /* + * req_planeoffset is not used. + * Sanity check req_planecount. + */ + end_offset = req->req_planecount; + if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset])) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + mid = mr->mr_port->mp_data; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_namecount = strlen(mid->mid_name); + if (rep->rep_namecount >= 128) + rep->rep_namecount = 128; + memcpy(&rep->rep_name, mid->mid_name, rep->rep_namecount); + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_object_get_class(struct mach_trap_args *args) +{ + mach_io_object_get_class_request_t *req = args->smsg; + mach_io_object_get_class_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + char classname[] = "unknownClass"; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + /* XXX Just return a dummy name for now */ + rep->rep_namecount = strlen(classname); + if (rep->rep_namecount >= 128) + rep->rep_namecount = 128; + memcpy(&rep->rep_name, classname, rep->rep_namecount); + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_location_in_plane(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_location_in_plane_request_t *req = + args->smsg; + mach_io_registry_entry_get_location_in_plane_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + char location[] = ""; + int end_offset; + + /* + * req_nameoffset is not used. + * Sanity check req_namecount. + */ + end_offset = req->req_namecount; + if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset])) + return mach_msg_error(args, EINVAL); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + /* XXX Just return a dummy name for now */ + rep->rep_locationcount = sizeof(location); + memcpy(&rep->rep_location, location, sizeof(location)); + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_properties(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_properties_request_t *req = args->smsg; + mach_io_registry_entry_get_properties_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + int error; + void *uaddr; + size_t size; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + mid = mr->mr_port->mp_data; + if (mid->mid_properties == NULL) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + size = strlen(mid->mid_properties) + 1; /* Include trailing zero */ + + if ((error = mach_ool_copyout(l, + mid->mid_properties, &uaddr, size, MACH_OOL_TRACE)) != 0) { +#ifdef DEBUG_MACH + printf("pid %d.%d: copyout iokit properties failed\n", + l->l_proc->p_pid, l->l_lid); +#endif + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_ool_desc(rep, uaddr, size); + + rep->rep_count = size; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_property(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_property_request_t *req = args->smsg; + mach_io_registry_entry_get_property_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + int error; + void *uaddr; + size_t size; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + struct mach_iokit_property *mip; + int end_offset; + + /* + * req_property_nameoffset is not used. + * Sanity check req_property_namecount. + */ + end_offset = req->req_property_namecount; + if (MACH_REQMSG_OVERFLOW(args, req->req_property_name[end_offset])) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + /* Find the port */ + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + /* Find the devclass information */ + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + mid = mr->mr_port->mp_data; + if (mid->mid_properties_array == NULL) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + /* Lookup the property name */ + for (mip = mid->mid_properties_array; mip->mip_name; mip++) + if (memcmp(mip->mip_name, req->req_property_name, + req->req_property_namecount) == 0) + break; + + if (mip->mip_value == NULL) + return mach_iokit_error(args, MACH_IOKIT_ENOENT); + size = strlen(mip->mip_value) + 1; /* Include trailing zero */ + + /* And copyout its associated value */ + if ((error = mach_ool_copyout(l, + mip->mip_value, &uaddr, size, MACH_OOL_TRACE)) != 0) { +#ifdef DEBUG_MACH + printf("pid %d.%d: copyout iokit property failed\n", + l->l_proc->p_pid, l->l_lid); +#endif + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_ool_desc(rep, uaddr, size); + + rep->rep_properties_count = size; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_path(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_path_request_t *req = args->smsg; + mach_io_registry_entry_get_path_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + char location[] = ":/GossamerPE/pci@80000000/AppleGracklePCI/" + "ATY,264LT-G@11/.Display_Video_ATI_mach64-01018002/" + "display0/AppleBacklightDisplay"; + char *cp; + size_t len, plen; + int end_offset; + + /* + * req_offset is not used. + * Sanity check req_count. + */ + end_offset = req->req_count; + if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset])) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + /* XXX Just return a dummy name for now */ + len = req->req_count + strlen(location) - 1; + + /* Sanity check for len */ + if (len > 512) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + plen = (len & ~0x3UL) + 4; /* Round to an int */ + + *msglen = sizeof(*rep) + (plen - 512); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + rep->rep_count = len; + + cp = &rep->rep_path[0]; + memcpy(cp, &req->req_plane, req->req_count); + cp += (req->req_count - 1); /* overwrite trailing \0 */ + memcpy(cp, location, strlen(location)); + cp += strlen(location); + *cp = '\0'; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_connect_map_memory(struct mach_trap_args *args) +{ + mach_io_connect_map_memory_request_t *req = args->smsg; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mid = mr->mr_port->mp_data; + if (mid->mid_connect_map_memory == NULL) + printf("no connect_map_memory method " + "for darwin_iokit_class %s\n", mid->mid_name); + else + return (mid->mid_connect_map_memory)(args); + } + + return mach_iokit_error(args, MACH_IOKIT_ENODEV); +} + +int +mach_io_iterator_reset(struct mach_trap_args *args) +{ + mach_io_iterator_reset_request_t *req = args->smsg; + mach_io_iterator_reset_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_device_iterator *mdi; + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype != MACH_MP_DEVICE_ITERATOR) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + + mdi = mr->mr_port->mp_data; + mdi->mdi_current = 0; + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_connect_method_scalari_structo(struct mach_trap_args *args) +{ + mach_io_connect_method_scalari_structo_request_t *req = args->smsg; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + int end_offset; + + /* Sanity check req_incount */ + end_offset = req->req_incount + + (sizeof(req->req_outcount) / sizeof(req->req_in[0])); + if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset])) + return mach_msg_error(args, EINVAL); + + /* Sanity check req_outcount */ + if (req->req_outcount > 4096) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mid = mr->mr_port->mp_data; + if (mid->mid_connect_method_scalari_structo == NULL) + printf("no connect_method_scalari_structo method " + "for darwin_iokit_class %s\n", mid->mid_name); + else + return (mid->mid_connect_method_scalari_structo)(args); + } + + return mach_iokit_error(args, MACH_IOKIT_ENODEV); +} + +int +mach_io_connect_method_structi_structo(struct mach_trap_args *args) +{ + mach_io_connect_method_structi_structo_request_t *req = args->smsg; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + int end_offset; + int outcount; + + /* Sanity check req_incount */ + end_offset = req->req_incount + + (sizeof(req->req_outcount) / sizeof(req->req_in[0])); + if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset])) + return mach_msg_error(args, EINVAL); + + /* Sanity check outcount. It is word aligned */ + outcount = req->req_in[(req->req_incount & ~0x3UL) + 4]; + if (outcount > 4096) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mid = mr->mr_port->mp_data; + if (mid->mid_connect_method_structi_structo == NULL) + printf("no connect_method_structi_structo method " + "for darwin_iokit_class %s\n", mid->mid_name); + else + return (mid->mid_connect_method_structi_structo)(args); + } + + return mach_iokit_error(args, MACH_IOKIT_ENODEV); +} + +int +mach_io_connect_set_properties(struct mach_trap_args *args) +{ + mach_io_connect_set_properties_request_t *req = args->smsg; + mach_io_connect_set_properties_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + +#ifdef DEBUG_MACH + uprintf("Unimplemented mach_io_connect_set_properties\n"); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_service_close(struct mach_trap_args *args) +{ + mach_io_service_close_request_t *req = args->smsg; + mach_io_service_close_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + +#ifdef DEBUG_MACH + uprintf("Unimplemented mach_io_service_close\n"); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_connect_add_client(struct mach_trap_args *args) +{ + mach_io_connect_add_client_request_t *req = args->smsg; + mach_io_connect_add_client_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + +#ifdef DEBUG_MACH + uprintf("Unimplemented mach_io_connect_add_client\n"); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_connect_method_scalari_structi(struct mach_trap_args *args) +{ + mach_io_connect_method_scalari_structi_request_t *req = args->smsg; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + int end_offset; + int scalar_size, struct_size, instructcount; + + /* Sanity check req_incount and get instructcount */ + if (MACH_REQMSG_OVERFLOW(args, req->req_in[req->req_incount])) + return mach_msg_error(args, EINVAL); + instructcount = req->req_in[req->req_incount]; + + /* Sanity check instructcount */ + scalar_size = sizeof(req->req_in[0]); + struct_size = sizeof(req->req_instruct[0]); + end_offset = req->req_incount + + (sizeof(instructcount) / scalar_size) + + (instructcount * struct_size / scalar_size); + if (MACH_REQMSG_OVERFLOW(args, req->req_in[end_offset])) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype == MACH_MP_IOKIT_DEVCLASS) { + mid = mr->mr_port->mp_data; + if (mid->mid_connect_method_scalari_structi == NULL) + printf("no connect_method_scalari_structi method " + "for darwin_iokit_class %s\n", mid->mid_name); + else + return (mid->mid_connect_method_scalari_structi)(args); + } + + return mach_iokit_error(args, MACH_IOKIT_ENODEV); +} + +int +mach_io_registry_entry_from_path(struct mach_trap_args *args) +{ + mach_io_registry_entry_from_path_request_t *req = args->smsg; + mach_io_registry_entry_from_path_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + int i, len; + int end_offset; + + /* + * req_pathoffset is not used. + * Sanity check req_pathcount. + */ + end_offset = req->req_pathcount; + if (MACH_REQMSG_OVERFLOW(args, req->req_path[end_offset])) + return mach_msg_error(args, EINVAL); + +#ifdef DEBUG_MACH + printf("mach_io_registry_entry_from_path: path = %s\n", req->req_path); +#endif + + mp = mach_port_get(); + mp->mp_flags |= MACH_MP_INKERNEL; + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + i = 0; + while ((mid = mach_iokit_devclasses[i++]) != NULL) { + len = strlen(mid->mid_name); +#ifdef DEBUG_MACH + printf("trying \"%s\" vs \"%s\"\n", + &req->req_path[req->req_pathcount - 1 - len], + mid->mid_name); +#endif + if (memcmp(&req->req_path[req->req_pathcount - 1 - len], + mid->mid_name, len) == 0) { + mp->mp_datatype = MACH_MP_IOKIT_DEVCLASS; + mp->mp_data = mid; + break; + } + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_io_registry_entry_get_parent_iterator(struct mach_trap_args *args) +{ + mach_io_registry_entry_get_parent_iterator_request_t *req = args->smsg; + mach_io_registry_entry_get_parent_iterator_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_port *mp; + struct mach_right *mr; + struct mach_iokit_devclass *mid; + struct mach_device_iterator *mdi; + mach_port_t mn; + int maxdev; + size_t size; + int end_offset; + + /* + * req_offset is unused + * Sanity check req_count + */ + end_offset = req->req_count; + if (MACH_REQMSG_OVERFLOW(args, req->req_plane[end_offset])) + return mach_msg_error(args, EINVAL); + +#ifdef DEBUG_MACH + printf("mach_io_registry_entry_get_parent_iterator: plane = %s\n", + req->req_plane); +#endif + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_iokit_error(args, MACH_IOKIT_EPERM); + + if (mr->mr_port->mp_datatype != MACH_MP_IOKIT_DEVCLASS) + return mach_iokit_error(args, MACH_IOKIT_EINVAL); + mid = mr->mr_port->mp_data; + + mp = mach_port_get(); + mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED); + mp->mp_datatype = MACH_MP_DEVICE_ITERATOR; + + maxdev = sizeof(mach_iokit_devclasses); + size = sizeof(*mdi) + (maxdev * sizeof(struct mach_iokit_devclass *)); + mdi = malloc(size, M_EMULDATA, M_WAITOK); + mp->mp_data = mdi; + + (void)mach_fill_parent_iterator(mdi, maxdev, 0, mid); + mdi->mdi_current = 0; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +void +mach_iokit_cleanup_notify(struct mach_right *mr) +{ + int i; + struct mach_iokit_devclass *mid; + + i = 0; + while ((mid = mach_iokit_devclasses[i++]) != NULL) + if (mid->mid_notify == mr) + mid->mid_notify = NULL; + + return; +} + +static int +mach_fill_child_iterator(struct mach_device_iterator *mdi, int size, int index, struct mach_iokit_devclass *mid) +{ + struct mach_iokit_devclass **midp; + struct mach_iokit_devclass **midq; + + for (midp = mach_iokit_devclasses; *midp != NULL; midp++) { + for (midq = (*midp)->mid_parent; *midq != NULL; midq++) { + if (*midq == mid) { + mdi->mdi_devices[index++] = *midp; + break; + } + } +#ifdef DIAGNOSTIC + if (index >= size) { + printf("mach_device_iterator overflow\n"); + break; + } +#endif + } + mdi->mdi_devices[index] = NULL; + + return index; +} + +static int +mach_fill_parent_iterator(struct mach_device_iterator *mdi, int size, int index, struct mach_iokit_devclass *mid) +{ + struct mach_iokit_devclass **midp; + + for (midp = mid->mid_parent; *midp != NULL; midp++) { + mdi->mdi_devices[index++] = *midp; +#ifdef DIAGNOSTIC + if (index >= size) { + printf("mach_device_iterator overflow\n"); + break; + } +#endif + } + mdi->mdi_devices[index] = NULL; + + return index; +} diff --git a/sys/compat/mach/mach_iokit.h b/sys/compat/mach/mach_iokit.h new file mode 100644 index 0000000..2981964 --- /dev/null +++ b/sys/compat/mach/mach_iokit.h @@ -0,0 +1,547 @@ +/* $NetBSD: mach_iokit.h,v 1.26 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_IOKIT_H_ +#define _MACH_IOKIT_H_ + +typedef struct mach_io_object *mach_io_object_t; + +/* mach_io_service_get_matching_services */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_io_object_t req_io_master; + mach_msg_size_t req_size; + char req_string[0]; +} mach_io_service_get_matching_services_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_match; + mach_msg_trailer_t rep_trailer; +} mach_io_service_get_matching_services_reply_t; + +/* mach_io_iterator_next */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_io_iterator_next_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_object; + mach_msg_trailer_t rep_trailer; +} mach_io_iterator_next_reply_t; + +/* mach_io_service_open */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_owningtask; + mach_ndr_record_t req_ndr; + int mach_connect_type; +} mach_io_service_open_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_connect; + mach_msg_trailer_t rep_trailer; +} mach_io_service_open_reply_t; + +/* mach_io_connect_method_scalari_scalaro */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + int req_selector; + mach_msg_type_number_t req_incount; + int req_in[0]; + mach_msg_type_number_t req_outcount; +} mach_io_connect_method_scalari_scalaro_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_outcount; + int rep_out[16]; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_method_scalari_scalaro_reply_t; + +/* io_connect_get_service */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_io_connect_get_service_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_service; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_get_service_reply_t; + +/* io_registry_entry_get_property */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_property_nameoffset; + mach_msg_type_number_t req_property_namecount; + char req_property_name[0]; +} mach_io_registry_entry_get_property_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_ool_descriptor_t rep_properties; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_properties_count; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_property_reply_t; + +/* io_registry_entry_create_iterator */ + +#define MACH_IOKIT_RECURSIVE_ITERATOR 1 +#define MACH_IOKIT_PARENT_ITERATOR 2 +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_planeoffset; + mach_msg_type_number_t req_planecount; + char req_plane[0]; + int req_options; +} mach_io_registry_entry_create_iterator_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_iterator; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_create_iterator_reply_t; + +/* io_object_conforms_to */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_classnameoffset; + mach_msg_type_number_t req_classnamecount; + char req_classname[0]; +} mach_io_object_conforms_to_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_boolean_t rep_conforms; + mach_msg_trailer_t rep_trailer; +} mach_io_object_conforms_to_reply_t; + +/* io_service_add_interest_notification */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_wake_port; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_typeofinterestoffset; + mach_msg_type_number_t req_typeofinterestcount; + char req_typeofinterest[0]; + mach_msg_type_number_t req_refcount; + mach_natural_t req_ref[0]; +} mach_io_service_add_interest_notification_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_notification; + mach_msg_trailer_t rep_trailer; +} mach_io_service_add_interest_notification_reply_t; + +/* io_connect_set_notification_port */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_port; + mach_ndr_record_t req_ndr; + int req_notification_type; + int req_reference; +} mach_io_connect_set_notification_port_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_set_notification_port_reply_t; + +/* io_registry_get_root_entry */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_io_registry_get_root_entry_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_root; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_get_root_entry_reply_t; + +/* io_registry_entry_get_child_iterator */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_planeoffset; + mach_msg_type_number_t req_planecount; + char req_plane[0]; +} mach_io_registry_entry_get_child_iterator_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_iterator; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_child_iterator_reply_t; + +/* io_registry_entry_get_name_in_plane */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_planeoffset; + mach_msg_type_number_t req_planecount; + char req_plane[0]; +} mach_io_registry_entry_get_name_in_plane_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_nameoffset; + mach_msg_type_number_t rep_namecount; + char rep_name[128]; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_name_in_plane_reply_t; + +/* io_object_get_class */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_io_object_get_class_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_nameoffset; + mach_msg_type_number_t rep_namecount; + char rep_name[128]; + mach_msg_trailer_t rep_trailer; +} mach_io_object_get_class_reply_t; + +/* io_registry_entry_get_location_in_plane */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_nameoffset; + mach_msg_type_number_t req_namecount; + char req_plane[0]; +} mach_io_registry_entry_get_location_in_plane_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_locationoffset; + mach_msg_type_number_t rep_locationcount; + char rep_location[128]; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_location_in_plane_reply_t; + +/* io_registry_entry_get_properties */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_io_registry_entry_get_properties_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_ool_descriptor_t rep_properties; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_count; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_properties_reply_t; + +/* io_registry_entry_get_path */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_offset; + mach_msg_type_number_t req_count; + char req_plane[0]; +} mach_io_registry_entry_get_path_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_offset; + mach_msg_type_number_t rep_count; + char rep_path[512]; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_path_reply_t; + +/* io_connect_map_memory */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_task; + mach_ndr_record_t req_ndr; + int req_memtype; + mach_vm_address_t req_addr; + mach_vm_size_t req_len; + int req_flags; +} mach_io_connect_map_memory_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_vm_address_t rep_addr; + mach_vm_size_t rep_len; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_map_memory_reply_t; + +/* io_iterator_reset */ + +typedef struct { + mach_msg_header_t req_msgh; +#if 0 /* Is it optional? Darwin don't include them */ + mach_ndr_record_t req_ndr; + int req_flags; +#endif +} mach_io_iterator_reset_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_io_iterator_reset_reply_t; + +/* io_connect_set_properties */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_ool_descriptor_t req_properties; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_count; +} mach_io_connect_set_properties_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_natural_t rep_result; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_set_properties_reply_t; + +/* io_connect_method_scalari_structo */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + int req_selector; + mach_msg_type_number_t req_incount; + int req_in[0]; + mach_msg_type_number_t req_outcount; +} mach_io_connect_method_scalari_structo_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_outcount; + char rep_out[4096]; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_method_scalari_structo_reply_t; + +/* io_connect_method_structi_structo */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + int req_selector; + mach_msg_type_number_t req_incount; + char req_in[0]; + mach_msg_type_number_t req_outcount; +} mach_io_connect_method_structi_structo_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_outcount; + char rep_out[4096]; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_method_structi_structo_reply_t; + +/* io_service_close */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_io_service_close_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_io_service_close_reply_t; + +/* io_connect_add_client */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_connect; +} mach_io_connect_add_client_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_add_client_reply_t; + +/* io_connect_method_scalari_structi */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + int req_selector; + mach_msg_type_number_t req_incount; + int req_in[0]; + mach_msg_type_number_t req_instructcount; + char req_instruct[0]; +} mach_io_connect_method_scalari_structi_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_io_connect_method_scalari_structi_reply_t; + +/* io_registry_entry_from_path */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_pathoffset; + mach_msg_type_number_t req_pathcount; + char req_path[0]; +} mach_io_registry_entry_from_path_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_entry; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_from_path_reply_t; + +/* io_registry_entry_get_parent_iterator */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_msg_type_number_t req_offset; + mach_msg_type_number_t req_count; + char req_plane[0]; +} mach_io_registry_entry_get_parent_iterator_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_iterator; + mach_msg_trailer_t rep_trailer; +} mach_io_registry_entry_get_parent_iterator_reply_t; + + +/* Kernel-private structures */ + +extern struct mach_iokit_devclass *mach_iokit_devclasses[]; + +struct mach_iokit_property { + const char *mip_name; + const char *mip_value; +}; + +struct mach_device_iterator { + int mdi_current; + struct mach_iokit_devclass *mdi_devices[1]; +}; + +/* Make this dynamic if it ever gets useful */ +#define MACH_IOKIT_MAX_PARENTS 8 +struct mach_iokit_devclass { + const char *mid_string; + struct mach_iokit_devclass *mid_parent[MACH_IOKIT_MAX_PARENTS]; + const char *mid_properties; + struct mach_iokit_property *mid_properties_array; + int (*mid_connect_method_scalari_scalaro)(struct mach_trap_args *); + int (*mid_connect_method_scalari_structo)(struct mach_trap_args *); + int (*mid_connect_method_structi_structo)(struct mach_trap_args *); + int (*mid_connect_method_scalari_structi)(struct mach_trap_args *); + int (*mid_connect_map_memory)(struct mach_trap_args *); + const char *mid_name; + struct mach_right *mid_notify; +}; + +extern struct mach_iokit_devclass mach_ioroot_devclass; + +void mach_iokit_cleanup_notify(struct mach_right *); + +#endif /* _MACH_IOKIT_H_ */ diff --git a/sys/compat/mach/mach_message.c b/sys/compat/mach/mach_message.c new file mode 100644 index 0000000..c7e60a7 --- /dev/null +++ b/sys/compat/mach/mach_message.c @@ -0,0 +1,1230 @@ +/* $NetBSD: mach_message.c,v 1.59 2009/03/18 16:00:17 cegger Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.59 2009/03/18 16:00:17 cegger Exp $"); + +#include "opt_compat_mach.h" /* For COMPAT_MACH in */ +#include "opt_compat_darwin.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef COMPAT_DARWIN +#include +#endif + +/* Mach message pool */ +static struct pool mach_message_pool; + +static inline + int mach_msg_send(struct lwp *, mach_msg_header_t *, int *, size_t); +static inline int mach_msg_recv(struct lwp *, mach_msg_header_t *, + int, size_t, unsigned int, mach_port_t); +static inline + struct lwp *mach_get_target_task(struct lwp *, struct mach_port *); +static inline void mach_drop_rights(struct mach_right *, int); +static inline + void mach_trade_rights(struct lwp *, struct lwp *, mach_port_t *, int); +static inline + int mach_trade_rights_complex(struct lwp *, struct mach_message *); + +int +mach_sys_msg_overwrite_trap(struct lwp *l, const struct mach_sys_msg_overwrite_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_msg_header_t *) msg; + syscallarg(mach_msg_option_t) option; + syscallarg(mach_msg_size_t) send_size; + syscallarg(mach_msg_size_t) rcv_size; + syscallarg(mach_port_name_t) rcv_name; + syscallarg(mach_msg_timeout_t) timeout; + syscallarg(mach_port_name_t) notify; + syscallarg(mach_msg_header_t *) rcv_msg; + syscallarg(mach_msg_size_t) scatter_list_size; + } */ + size_t send_size, recv_size; + mach_msg_header_t *msg; + int opt; + + *retval = MACH_MSG_SUCCESS; + send_size = SCARG(uap, send_size); + recv_size = SCARG(uap, rcv_size); + opt = SCARG(uap, option); + + /* XXX not safe enough: lots of big messages will kill us */ + if (send_size > MACH_MAX_MSG_LEN) { + *retval = MACH_SEND_TOO_LARGE; + return 0; + } + if (recv_size > MACH_MAX_MSG_LEN) { + *retval = MACH_RCV_TOO_LARGE; + return 0; + } + + /* + * Two options: receive or send. If both are + * set, we must send, and then receive. If + * send fail, then we skip recieve. + */ + msg = SCARG(uap, msg); + if (opt & MACH_SEND_MSG) + *retval = mach_msg_send(l, msg, &opt, send_size); + + if ((opt & MACH_RCV_MSG) && (*retval == MACH_MSG_SUCCESS)) { + /* + * Find a buffer for the reply. + */ + if (SCARG(uap, rcv_msg) != NULL) + msg = SCARG(uap, rcv_msg); + else if (SCARG(uap, msg) != NULL) + msg = SCARG(uap, msg); + else { + *retval = MACH_RCV_INVALID_DATA; + return 0; + } + + *retval = mach_msg_recv(l, msg, opt, recv_size, + SCARG(uap, timeout), SCARG(uap, rcv_name)); + } + + return 0; +} + +/* + * Send a Mach message. This returns a Mach message error code. + */ +static inline int +mach_msg_send(struct lwp *l, mach_msg_header_t *msg, int *option, size_t send_size) +{ + struct mach_emuldata *med; + struct mach_port *mp; + struct proc *p = l->l_proc; + mach_msg_header_t *sm; + struct mach_service *srv; + mach_port_t ln; + mach_port_t rn; + struct mach_right *lr = NULL; + struct mach_right *rr; + int rights; + int bits; + int ret; + size_t reply_size; + int error = 0; + + if (msg == NULL) + return MACH_SEND_INVALID_DATA; + + /* + * Allocate memory for the message and its reply, + * and copy the whole message in the kernel. + */ + sm = malloc(send_size, M_EMULDATA, M_WAITOK); + if ((error = copyin(msg, sm, send_size)) != 0) { + ret = MACH_SEND_INVALID_DATA; + goto out1; + } + + /* Dump the Mach message */ + ktrmmsg((char *)sm, send_size); + + /* + * Handle rights in the message + */ + ln = sm->msgh_local_port; + rn = sm->msgh_remote_port; + + lr = mach_right_check(ln, l, MACH_PORT_TYPE_ALL_RIGHTS); + rr = mach_right_check(rn, l, MACH_PORT_TYPE_ALL_RIGHTS); + if ((rr == NULL) || (rr->mr_port == NULL)) { +#ifdef DEBUG_MACH + printf("msg id %d: invalid dest\n", sm->msgh_id); +#endif + ret = MACH_SEND_INVALID_DEST; + goto out1; + } + + /* + * Check that the process has a send right on + * the remote port. + */ + rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_SEND_ONCE); + if (mach_right_check(rn, l, rights) == NULL) { + ret = MACH_SEND_INVALID_RIGHT; + goto out1; + } + + /* + * If the remote port is a special port (host, kernel, + * clock, or io_master), the message will be handled + * by the kernel. + */ + med = (struct mach_emuldata *)p->p_emuldata; + mp = rr->mr_port; + if (mp->mp_flags & MACH_MP_INKERNEL) { + struct mach_trap_args args; + mach_msg_header_t *rm; + size_t min_reqlen, max_replen; + + /* + * Look for the function that will handle it, + * using the message id. + */ + for (srv = mach_services_table; srv->srv_id; srv++) + if (srv->srv_id == sm->msgh_id) + break; + + /* + * If no match, give up, and display a warning. + */ + if (srv->srv_handler == NULL) { + uprintf("No mach server for id = %d\n", + sm->msgh_id); + ret = MACH_SEND_INVALID_DEST; + goto out1; + } + min_reqlen = srv->srv_reqlen; + max_replen = srv->srv_replen; + + /* + * Special case when the kernel behaves as + * the client: replies to exceptions and + * notifications. There will be no reply, + * as we already receive a reply. + * - request and reply are swapped + * - there will be no reply, so set lr to NULL. + * - skip the lr == NULL tests + * XXX This is inelegant. + */ + if ((sm->msgh_id >= 2501) && (sm->msgh_id <= 2503)) { + min_reqlen = srv->srv_replen; + max_replen = srv->srv_reqlen; + lr = NULL; + goto skip_null_lr; + } + + /* + * Check that the local port is valid, else + * we will not be able to send the reply + */ + if ((lr == NULL) || + (lr->mr_port == NULL) || + (lr->mr_port->mp_recv == NULL)) { +#ifdef DEBUG_MACH + printf("msg id %d: invalid src\n", sm->msgh_id); +#endif + ret = MACH_SEND_INVALID_REPLY; + goto out1; + } +skip_null_lr: + + /* + * Sanity check message length. We do not want the + * server to: + * 1) use kernel memory located after + * the end of the request message. + */ + if (send_size < min_reqlen) { +#ifdef DEBUG_MACH + printf("mach server %s: smsg overflow: " + "send = %d, min = %d\n", + srv->srv_name, send_size, min_reqlen); +#endif + ret = MACH_SEND_MSG_TOO_SMALL; + goto out1; + } + + /* + * 2) Overwrite kernel memory after the end of the + * reply message buffer. This check is the + * responsibility of the server. + */ + + + /* + * Invoke the server. We give it the opportunity + * to shorten recv_size if there is less data in + * the reply than what the sender expected. + * If lr is NULL, this is a no reply operation. + */ + reply_size = max_replen; + if (lr != NULL) + rm = malloc(reply_size, M_EMULDATA, M_WAITOK | M_ZERO); + else + rm = NULL; + + args.l = l; + args.tl = mach_get_target_task(l, mp); + args.smsg = sm; + args.rmsg = rm; + args.rsize = &reply_size; + args.ssize = send_size; + if ((ret = (*srv->srv_handler)(&args)) != 0) + goto out1; + + /* + * No-reply opration: everything is done. + * Change option so that we skip the + * receive stage. + */ + if (lr == NULL) { + *option &= ~MACH_RCV_MSG; + return MACH_MSG_SUCCESS; + } + +#ifdef DIAGNOSTIC + /* + * Catch potential bug in the server (sanity + * check #2): did it output a larger message + * then the one that was allocated? + */ + if ((*option & MACH_RCV_MSG) && (reply_size > max_replen)) { + uprintf("mach_msg: reply too big in %s\n", + srv->srv_name); + } +#endif + + /* + * Queue the reply. + */ + mp = lr->mr_port; + (void)mach_message_get(rm, reply_size, mp, NULL); +#ifdef DEBUG_MACH_MSG + printf("pid %d: message queued on port %p (%d) [%p]\n", + p->p_pid, mp, rm->msgh_id, + mp->mp_recv->mr_sethead); + if (sm->msgh_id == 404) + printf("*** msg to bootstrap. port = %p, " + "recv = %p [%p]\n", mach_bootstrap_port, + mach_bootstrap_port->mp_recv, + mach_bootstrap_port->mp_recv->mr_sethead); +#endif + wakeup(mp->mp_recv->mr_sethead); + ret = MACH_MSG_SUCCESS; +out1: + free(sm, M_EMULDATA); + + return ret; + } + + /* + * The message is not to be handled by the kernel. + * Check that there is a valid receiver, and + * queue the message in the remote port. + */ + mp = rr->mr_port; /* (mp != NULL) already checked */ + if (mp->mp_recv == NULL) { +#ifdef DEBUG_MACH + printf("msg id %d: invalid dst\n", sm->msgh_id); +#endif + free(sm, M_EMULDATA); + return MACH_SEND_INVALID_DEST; + } + + (void)mach_message_get(sm, send_size, mp, l); +#ifdef DEBUG_MACH_MSG + printf("pid %d: message queued on port %p (%d) [%p]\n", + p->p_pid, mp, sm->msgh_id, + mp->mp_recv->mr_sethead); +#endif + /* + * Drop any right carried by the message. + */ + if (lr != NULL) { + bits = MACH_MSGH_LOCAL_BITS(sm->msgh_bits); + mach_drop_rights(lr, bits); + } + + if (rr != NULL) { + bits = MACH_MSGH_REMOTE_BITS(sm->msgh_bits); + mach_drop_rights(rr, bits); + } + + /* + * Wakeup any process awaiting for this message. + */ + wakeup(mp->mp_recv->mr_sethead); + + return MACH_MSG_SUCCESS; +} + +/* + * Receive a Mach message. This returns a Mach message error code. + */ +static inline int +mach_msg_recv(struct lwp *l, mach_msg_header_t *urm, int option, size_t recv_size, unsigned int timeout, mach_port_t mn) +{ + struct mach_port *mp; +#if defined(DEBUG_MACH_MSG) || defined(KTRACE) + struct proc *p = l->l_proc; +#endif + struct mach_message *mm; + mach_port_t tmp; + struct mach_right *cmr; + struct mach_right *mr; + int bits; + int ret; + int error = 0; + + mp = NULL; + + if (option & MACH_RCV_TIMEOUT) + timeout = timeout * hz / 1000; + else + timeout = 0; + + /* + * Check for receive right on the port. + */ + mr = mach_right_check(mn, l, MACH_PORT_TYPE_RECEIVE); + if (mr == NULL) { + + /* + * Is it a port set? + */ + mr = mach_right_check(mn, l, MACH_PORT_TYPE_PORT_SET); + if (mr == NULL) + return MACH_RCV_INVALID_NAME; + + /* + * This is a port set. For each port in the + * port set, check we have receive right, and + * and check if we have some message. + */ + LIST_FOREACH(cmr, &mr->mr_set, mr_setlist) { + if ((mach_right_check(cmr->mr_name, l, + MACH_PORT_TYPE_RECEIVE)) == NULL) + return MACH_RCV_INVALID_NAME; + + mp = cmr->mr_port; +#ifdef DEBUG_MACH + if (mp->mp_recv != cmr) + uprintf("mach_msg_trap: bad receive " + "port/right\n"); +#endif + if (mp->mp_count != 0) + break; + } + + /* + * If cmr is NULL then we found no message on + * any port. Sleep on the port set until we get + * some or until we get a timeout. + */ + if (cmr == NULL) { +#ifdef DEBUG_MACH_MSG + printf("pid %d: wait on port %p [%p]\n", + p->p_pid, mp, mr->mr_sethead); +#endif + error = tsleep(mr->mr_sethead, PZERO|PCATCH, + "mach_msg", timeout); + if ((error == ERESTART) || (error == EINTR)) + return MACH_RCV_INTERRUPTED; + + /* + * Check we did not loose the receive right + * while we were sleeping. + */ + if ((mach_right_check(mn, l, + MACH_PORT_TYPE_PORT_SET)) == NULL) + return MACH_RCV_PORT_DIED; + + /* + * Is there any pending message for + * a port in the port set? + */ + LIST_FOREACH(cmr, &mr->mr_set, mr_setlist) { + mp = cmr->mr_port; + if (mp->mp_count != 0) + break; + } + + if (cmr == NULL) + return MACH_RCV_TIMED_OUT; + } + + /* + * We found a port with a pending message. + */ + mp = cmr->mr_port; + + } else { + /* + * This is a receive on a simple port (no port set). + * If there is no message queued on the port, + * block until we get some. + */ + mp = mr->mr_port; + +#ifdef DEBUG_MACH + if (mp->mp_recv != mr) + uprintf("mach_msg_trap: bad receive " + "port/right\n"); +#endif +#ifdef DEBUG_MACH_MSG + printf("pid %d: wait on port %p [%p]\n", + p->p_pid, mp, mr->mr_sethead); +#endif + if (mp->mp_count == 0) { + error = tsleep(mr->mr_sethead, PZERO|PCATCH, + "mach_msg", timeout); + if ((error == ERESTART) || (error == EINTR)) + return MACH_RCV_INTERRUPTED; + + /* + * Check we did not lose the receive right + * while we were sleeping. + */ + if ((mach_right_check(mn, l, + MACH_PORT_TYPE_RECEIVE)) == NULL) + return MACH_RCV_PORT_DIED; + + if (mp->mp_count == 0) + return MACH_RCV_TIMED_OUT; + } + } + + /* + * Dequeue the message. + * XXX Do we really need to lock here? There could be + * only one reader process, so mm will not disapear + * except if there is a port refcount error in our code. + */ + rw_enter(&mp->mp_msglock, RW_READER); + mm = TAILQ_FIRST(&mp->mp_msglist); +#ifdef DEBUG_MACH_MSG + printf("pid %d: dequeue message on port %p (id %d)\n", + p->p_pid, mp, mm->mm_msg->msgh_id); +#endif + + ret = MACH_MSG_SUCCESS; + if (mm->mm_size > recv_size) { + struct mach_short_reply sr; + + ret = MACH_RCV_TOO_LARGE; + /* + * If MACH_RCV_LARGE was not set, destroy the message. + */ + if ((option & MACH_RCV_LARGE) == 0) { + free(mm->mm_msg, M_EMULDATA); + mach_message_put_shlocked(mm); + goto unlock; + } + + /* + * If MACH_RCV_TOO_LARGE is set, then return + * a message with just header and trailer. The + * size in the header should correspond to the + * whole message, so just copy the whole header. + */ + memcpy(&sr, mm->mm_msg, sizeof(mach_msg_header_t)); + mach_set_trailer(&sr, sizeof(sr)); + + if ((error = copyout(&sr, urm, sizeof(sr))) != 0) { + ret = MACH_RCV_INVALID_DATA; + goto unlock; + } + + /* Dump the Mach message */ + ktrmmsg((char *)&sr, sizeof(sr)); + goto unlock; + } + + /* + * Get rights carried by the message if it is not a + * reply from the kernel. + * XXX mm->mm_l could contain stall data. Reference + * the thread's kernel port instead? + */ + if (mm->mm_l != NULL) { + mach_port_t *mnp; +#ifdef DEBUG_MACH + printf("mach_msg: non kernel-reply message\n"); +#endif + /* + * Turn local and remote port names into + * names in the local process namespace. + */ + bits = MACH_MSGH_LOCAL_BITS(mm->mm_msg->msgh_bits); + mnp = &mm->mm_msg->msgh_local_port; + mach_trade_rights(l, mm->mm_l, mnp, bits); + + bits = MACH_MSGH_REMOTE_BITS(mm->mm_msg->msgh_bits); + mnp = &mm->mm_msg->msgh_remote_port; + mach_trade_rights(l, mm->mm_l, mnp, bits); + + /* + * The same operation must be done to all + * port descriptors carried with the message. + */ + if ((mm->mm_msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) && + ((ret = mach_trade_rights_complex(l, mm)) != 0)) + goto unlock; + + /* + * swap local and remote ports, and + * corresponding bits as well. + */ + bits = (bits & 0xffff0000) | + ((bits & 0xff00) >> 8) | + ((bits & 0x00ff) << 8); + tmp = mm->mm_msg->msgh_remote_port; + mm->mm_msg->msgh_remote_port = + mm->mm_msg->msgh_local_port; + mm->mm_msg->msgh_local_port = tmp; + } + + /* + * Copy the message to userland. + */ + if ((error = copyout(mm->mm_msg, urm, mm->mm_size)) != 0) { + ret = MACH_RCV_INVALID_DATA; + goto unlock; + } + + /* Dump the Mach message */ + ktrmmsg((char *)mm->mm_msg, mm->mm_size); + + free(mm->mm_msg, M_EMULDATA); + mach_message_put_shlocked(mm); /* decrease mp_count */ +unlock: + rw_exit(&mp->mp_msglock); + + return ret; +} + + +int +mach_sys_msg_trap(struct lwp *l, const struct mach_sys_msg_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_msg_header_t *) msg; + syscallarg(mach_msg_option_t) option; + syscallarg(mach_msg_size_t) send_size; + syscallarg(mach_msg_size_t) rcv_size; + syscallarg(mach_port_name_t) rcv_name; + syscallarg(mach_msg_timeout_t) timeout; + syscallarg(mach_port_name_t) notify; + } */ + struct mach_sys_msg_overwrite_trap_args cup; + + SCARG(&cup, msg) = SCARG(uap, msg); + SCARG(&cup, option) = SCARG(uap, option); + SCARG(&cup, send_size) = SCARG(uap, send_size); + SCARG(&cup, rcv_size) = SCARG(uap, rcv_size); + SCARG(&cup, rcv_name) = SCARG(uap, rcv_name); + SCARG(&cup, timeout) = SCARG(uap, timeout); + SCARG(&cup, notify) = SCARG(uap, notify); + SCARG(&cup, rcv_msg) = NULL; + SCARG(&cup, scatter_list_size) = 0; + + return mach_sys_msg_overwrite_trap(l, &cup, retval); +} + +static inline struct lwp * +mach_get_target_task(struct lwp *l, struct mach_port *mp) +{ + struct proc *tp; + struct lwp *tl; + + switch (mp->mp_datatype) { + case MACH_MP_PROC: + tp = (struct proc *)mp->mp_data; + tl = LIST_FIRST(&tp->p_lwps); + KASSERT(tl != NULL); + break; + + case MACH_MP_LWP: + tl = (struct lwp *)mp->mp_data; + break; + + default: + tl = l; + break; + } + + return tl; +} + +static inline void +mach_drop_rights(struct mach_right *mr, int bits) +{ + int rights; + + switch (bits) { + case MACH_MSG_TYPE_MOVE_SEND: + rights = MACH_PORT_TYPE_SEND; + break; + case MACH_MSG_TYPE_MOVE_SEND_ONCE: + rights = MACH_PORT_TYPE_SEND_ONCE; + break; + case MACH_MSG_TYPE_MOVE_RECEIVE: + /* Recv. right is lost when msg is received */ + case MACH_MSG_TYPE_MAKE_SEND: + case MACH_MSG_TYPE_COPY_SEND: + case MACH_MSG_TYPE_MAKE_SEND_ONCE: + default: + rights = 0; + break; + } + + if (rights != 0) + mach_right_put(mr, rights); + + return; +} + +/* + * When a messages is transmitted from one process to another, + * we need to make sure the port names are in the receiver process + * namespace. + */ +static inline void +mach_trade_rights(struct lwp *ll, struct lwp *rl, mach_port_t *mnp, int bits) + /* ll: local lwp (receiver, current lwp) */ + /* rl: remote lwp (sender) */ + /* mnp: pointer to the port name */ + /* bits: right bits */ +{ + int lr; /* local right type (to be added) */ + int rr; /* remote right type */ + struct mach_right *lmr; /* right in the local process */ + struct mach_right *rmr; /* right in the remote process */ + + switch (bits) { + case MACH_MSG_TYPE_MAKE_SEND: + rr = MACH_PORT_TYPE_RECEIVE; + lr = MACH_PORT_TYPE_SEND; + break; + + case MACH_MSG_TYPE_COPY_SEND: + case MACH_MSG_TYPE_MOVE_SEND: + rr = MACH_PORT_TYPE_SEND; + lr = MACH_PORT_TYPE_SEND; + break; + + case MACH_MSG_TYPE_MAKE_SEND_ONCE: + rr = MACH_PORT_TYPE_RECEIVE; + lr = MACH_PORT_TYPE_SEND_ONCE; + break; + + case MACH_MSG_TYPE_MOVE_SEND_ONCE: + rr = MACH_PORT_TYPE_SEND_ONCE; + lr = MACH_PORT_TYPE_SEND_ONCE; + break; + + case MACH_MSG_TYPE_MOVE_RECEIVE: + rr = MACH_PORT_TYPE_RECEIVE; + lr = MACH_PORT_TYPE_RECEIVE; + break; + + default: + rr = 0; + lr = 0; + break; + } + + /* Get the right in the remote process (sender) */ + rmr = NULL; + if (lr != 0) + rmr = mach_right_check(*mnp, rl, rr); + + /* Translate it into a right in the local process (receiver) */ + if (rmr != NULL) { + lmr = mach_right_get(rmr->mr_port, ll, lr, 0); + *mnp = lmr->mr_name; + } else { + *mnp = 0; + } + + return; +} + +/* + * Turn rights carried by complex messages into rights in + * the local namespace. Returns a Mach messsage error + * XXX Nothing is there yet to remove the rights from the + * sender namespace, it should be done at send time and it + * is not done yet. + */ +static inline int +mach_trade_rights_complex(struct lwp *l, struct mach_message *mm) +{ + struct mach_complex_msg *mcm; + unsigned int i, count; + unsigned long begin, end; + + /* + * Sanity check the descriptor count. + * Note that all descriptor types + * have the same size, hence it is + * safe to not take the descriptor + * type into account here. + */ + mcm = (struct mach_complex_msg *)mm->mm_msg; + count = mcm->mcm_body.msgh_descriptor_count; + begin = (u_long)mcm; + end = (u_long)&mcm->mcm_desc.gen[count]; + + if ((end - begin) > mm->mm_size) { +#ifdef DEBUG_MACH + printf("msg id %d: invalid count\n", mm->mm_msg->msgh_id); +#endif + return MACH_SEND_INVALID_DATA; + } + + for (i = 0; i < count; i++) { + switch (mcm->mcm_desc.gen[i].type) { + case MACH_MSG_PORT_DESCRIPTOR: + mach_trade_rights(l, mm->mm_l, + &mcm->mcm_desc.port[i].name, + mcm->mcm_desc.port[i].disposition); + break; + + case MACH_MSG_OOL_PORTS_DESCRIPTOR: { /* XXX untested */ + struct lwp *rl; /* remote LWP */ + void *lumnp; /* local user address */ + void *rumnp; /* remote user address */ + int disp; /* disposition*/ + size_t size; /* data size */ + int mcount; /* descriptor count */ + mach_port_t *kmnp; + void *kaddr; + int error; + int j; + + rl = mm->mm_l; + disp = mcm->mcm_desc.ool_ports[i].disposition; + rumnp = mcm->mcm_desc.ool_ports[i].address; + mcount = mcm->mcm_desc.ool_ports[i].count; + size = mcount * sizeof(*kmnp); + kaddr = NULL; + lumnp = NULL; + + /* This allocates kmnp */ + error = mach_ool_copyin(rl, rumnp, &kaddr, size, 0); + if (error != 0) + return MACH_SEND_INVALID_DATA; + + kmnp = (mach_port_t *)kaddr; + for (j = 0; j < mcount; j++) + mach_trade_rights(l, mm->mm_l, &kmnp[j], disp); + + /* This frees kmnp */ + if ((error = mach_ool_copyout(l, kmnp, &lumnp, + size, MACH_OOL_FREE|MACH_OOL_TRACE)) != 0) + return MACH_SEND_INVALID_DATA; + + mcm->mcm_desc.ool_ports[i].address = lumnp; + break; + } + + case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: +#ifdef DEBUG_MACH + printf("MACH_MSG_OOL_VOLATILE_DESCRIPTOR\n"); +#endif + /* FALLTHROUGH */ + case MACH_MSG_OOL_DESCRIPTOR: { /* XXX untested */ + struct lwp *rl; /* remote LWP */ + void *ludata; /* local user address */ + void *rudata; /* remote user address */ + size_t size; /* data size */ + void *kdata; + int error; + + rl = mm->mm_l; + rudata = mcm->mcm_desc.ool[i].address; + size = mcm->mcm_desc.ool[i].size; + kdata = NULL; + ludata = NULL; + + /* + * XXX This is inefficient for large chunk of OOL + * memory. Think about remapping COW when possible. + */ + + /* This allocates kdata */ + error = mach_ool_copyin(rl, rudata, &kdata, size, 0); + if (error != 0) + return MACH_SEND_INVALID_DATA; + + /* This frees kdata */ + if ((error = mach_ool_copyout(l, kdata, &ludata, + size, MACH_OOL_FREE|MACH_OOL_TRACE)) != 0) + return MACH_SEND_INVALID_DATA; + + mcm->mcm_desc.ool_ports[i].address = ludata; + break; + } + default: +#ifdef DEBUG_MACH + printf("unknown descriptor type %d\n", + mcm->mcm_desc.gen[i].type); +#endif + break; + } + } + + return MACH_MSG_SUCCESS; +} + +inline int +mach_ool_copyin(struct lwp *l, const void *uaddr, void **kaddr, size_t size, int flags) +{ + int error; + void *kbuf; + struct proc *p = l->l_proc; + + /* + * Sanity check OOL size to avoid DoS on malloc: useless once + * we remap data instead of copying it. In the meantime, + * disabled since it makes some OOL transfer fail. + */ +#if 0 + if (size > MACH_MAX_OOL_LEN) + return ENOMEM; +#endif + + if (*kaddr == NULL) + kbuf = malloc(size, M_EMULDATA, M_WAITOK); + else + kbuf = *kaddr; + + if ((error = copyin_proc(p, uaddr, kbuf, size)) != 0) { + if (*kaddr == NULL) + free(kbuf, M_EMULDATA); + return error; + } + + if (size > PAGE_SIZE) + size = PAGE_SIZE; + if ((flags & MACH_OOL_TRACE)) + ktrmool(kaddr, size, uaddr); + + *kaddr = kbuf; + return 0; +} + +inline int +mach_ool_copyout(struct lwp *l, const void *kaddr, void **uaddr, size_t size, int flags) +{ + vaddr_t ubuf; + int error = 0; + struct proc *p = l->l_proc; + + /* + * Sanity check OOL size to avoid DoS on malloc: useless once + * we remap data instead of copying it. In the meantime, + * disabled since it makes some OOL transfer fail. + */ +#if 0 + if (size > MACH_MAX_OOL_LEN) { + error = ENOMEM; + goto out; + } +#endif + + if (*uaddr == NULL) + ubuf = (vaddr_t)vm_map_min(&p->p_vmspace->vm_map); + else + ubuf = (vaddr_t)*uaddr; + + /* Never map anything at address zero: this is a red zone */ + if (ubuf == (vaddr_t)NULL) + ubuf += PAGE_SIZE; + + if ((error = uvm_map(&p->p_vmspace->vm_map, &ubuf, + round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL, + UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0) + goto out; + + if ((error = copyout_proc(p, kaddr, (void *)ubuf, size)) != 0) + goto out; + + if (size > PAGE_SIZE) + size = PAGE_SIZE; + if ((flags & MACH_OOL_TRACE)) + ktrmool(kaddr, size, (void *)ubuf); + +out: + if (flags & MACH_OOL_FREE) + free(__UNCONST(kaddr), M_EMULDATA); /*XXXUNCONST*/ + + if (error == 0) + *uaddr = (void *)ubuf; + return error; +} + + +inline void +mach_set_trailer(void *msgh, size_t size) +{ + mach_msg_trailer_t *trailer; + char *msg = (char *)msgh; + + trailer = (mach_msg_trailer_t *)&msg[size - sizeof(*trailer)]; + trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; + trailer->msgh_trailer_size = sizeof(*trailer); + + return; +} + +inline void +mach_set_header(void *rep, void *req, size_t size) +{ + mach_msg_header_t *rephdr = rep; + mach_msg_header_t *reqhdr = req; + + rephdr->msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + rephdr->msgh_size = size - sizeof(mach_msg_trailer_t); + rephdr->msgh_local_port = reqhdr->msgh_local_port; + rephdr->msgh_remote_port = 0; + rephdr->msgh_id = reqhdr->msgh_id + 100; + + return; +} + +inline void +mach_add_port_desc(void *msg, mach_port_name_t name) +{ + struct mach_complex_msg *mcm = msg; + int i; + + if ((mcm->mcm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) { + mcm->mcm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX; + mcm->mcm_body.msgh_descriptor_count = 0; + } + + i = mcm->mcm_body.msgh_descriptor_count; + + mcm->mcm_desc.port[i].name = name; + mcm->mcm_desc.port[i].disposition = MACH_MSG_TYPE_MOVE_SEND; + mcm->mcm_desc.port[i].type = MACH_MSG_PORT_DESCRIPTOR; + + mcm->mcm_body.msgh_descriptor_count++; + return; +} + +inline void +mach_add_ool_ports_desc(void *msg, void *addr, int count) +{ + struct mach_complex_msg *mcm = msg; + int i; + + if ((mcm->mcm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) { + mcm->mcm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX; + mcm->mcm_body.msgh_descriptor_count = 0; + } + + i = mcm->mcm_body.msgh_descriptor_count; + + mcm->mcm_desc.ool_ports[i].address = addr; + mcm->mcm_desc.ool_ports[i].count = count; + mcm->mcm_desc.ool_ports[i].copy = MACH_MSG_ALLOCATE; + mcm->mcm_desc.ool_ports[i].disposition = MACH_MSG_TYPE_MOVE_SEND; + mcm->mcm_desc.ool_ports[i].type = MACH_MSG_OOL_PORTS_DESCRIPTOR; + + mcm->mcm_body.msgh_descriptor_count++; + return; +} + +inline void mach_add_ool_desc(msg, addr, size) + void *msg; + void *addr; + size_t size; +{ + struct mach_complex_msg *mcm = msg; + int i; + + if ((mcm->mcm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) { + mcm->mcm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX; + mcm->mcm_body.msgh_descriptor_count = 0; + } + + i = mcm->mcm_body.msgh_descriptor_count; + + mcm->mcm_desc.ool[i].address = addr; + mcm->mcm_desc.ool[i].size = size; + mcm->mcm_desc.ool[i].deallocate = 0; + mcm->mcm_desc.ool[i].copy = MACH_MSG_ALLOCATE; + mcm->mcm_desc.ool[i].type = MACH_MSG_OOL_DESCRIPTOR; + + mcm->mcm_body.msgh_descriptor_count++; + return; +} + +void +mach_message_init(void) +{ + pool_init(&mach_message_pool, sizeof (struct mach_message), + 0, 0, 0, "mach_message_pool", NULL, IPL_NONE); + return; +} + +struct mach_message * +mach_message_get(mach_msg_header_t *msgh, size_t size, struct mach_port *mp, struct lwp *l) +{ + struct mach_message *mm; + + mm = (struct mach_message *)pool_get(&mach_message_pool, PR_WAITOK); + memset(mm, 0, sizeof(*mm)); + mm->mm_msg = msgh; + mm->mm_size = size; + mm->mm_port = mp; + mm->mm_l = l; + + rw_enter(&mp->mp_msglock, RW_WRITER); + TAILQ_INSERT_TAIL(&mp->mp_msglist, mm, mm_list); + mp->mp_count++; + rw_exit(&mp->mp_msglock); + + return mm; +} + +void +mach_message_put(struct mach_message *mm) +{ + struct mach_port *mp; + + mp = mm->mm_port; + + rw_enter(&mp->mp_msglock, RW_WRITER); + mach_message_put_exclocked(mm); + rw_exit(&mp->mp_msglock); + + return; +} + +void +mach_message_put_shlocked(struct mach_message *mm) +{ + struct mach_port *mp; + + mp = mm->mm_port; + + if (!rw_tryupgrade(&mp->mp_msglock)) { + /* XXX */ + rw_exit(&mp->mp_msglock); + rw_enter(&mp->mp_msglock, RW_WRITER); + } + mach_message_put_exclocked(mm); + rw_downgrade(&mp->mp_msglock); + + return; +} + +void +mach_message_put_exclocked(struct mach_message *mm) +{ + struct mach_port *mp; + + mp = mm->mm_port; + + TAILQ_REMOVE(&mp->mp_msglist, mm, mm_list); + mp->mp_count--; + + pool_put(&mach_message_pool, mm); + + return; +} + +#ifdef DEBUG_MACH +void +mach_debug_message(void) +{ + struct lwp *l; + struct mach_emuldata *med; + struct mach_right *mr; + struct mach_right *mrs; + struct mach_port *mp; + struct mach_message *mm; + + LIST_FOREACH(l, &alllwp, l_list) { + if ((l->l_proc->p_emul != &emul_mach) && +#ifdef COMPAT_DARWIN + (l->l_proc->p_emul != &emul_darwin) && +#endif + 1) + continue; + + med = l->l_proc->p_emuldata; + LIST_FOREACH(mr, &med->med_right, mr_list) + if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) { + mp = mr->mr_port; + if (mp == NULL) + continue; + + printf("port %p(%d) ", mp, mp->mp_count); + + TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list) + printf("%d ", mm->mm_msg->msgh_id); + + printf("\n"); + continue; + } + /* Port set... */ + LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) { + mp = mrs->mr_port; + if (mp == NULL) + continue; + + printf("port %p(%d) ", mp, mp->mp_count); + + TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list) + printf("%d ", mm->mm_msg->msgh_id); + + printf("\n"); + } + } + return; +} + +#endif /* DEBUG_MACH */ diff --git a/sys/compat/mach/mach_message.h b/sys/compat/mach/mach_message.h new file mode 100644 index 0000000..570a336 --- /dev/null +++ b/sys/compat/mach/mach_message.h @@ -0,0 +1,276 @@ +/* $NetBSD: mach_message.h,v 1.30 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2001-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas and Emmanuel Dreyfus. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_MESSAGE_H_ +#define _MACH_MESSAGE_H_ + +typedef unsigned int mach_msg_bits_t; +typedef unsigned int mach_msg_size_t; +typedef unsigned int mach_msg_id_t; +typedef unsigned int mach_msg_timeout_t; +typedef unsigned int mach_msg_option_t; +typedef unsigned int mach_msg_type_name_t; +typedef unsigned int mach_msg_type_number_t; + +/* + * Options + */ +#define MACH_MSG_OPTION_NONE 0x00000000 +#define MACH_SEND_MSG 0x00000001 +#define MACH_RCV_MSG 0x00000002 +#define MACH_RCV_LARGE 0x00000004 +#define MACH_SEND_TIMEOUT 0x00000010 +#define MACH_SEND_INTERRUPT 0x00000040 +#define MACH_SEND_CANCEL 0x00000080 +#define MACH_RCV_TIMEOUT 0x00000100 +#define MACH_RCV_NOTIFY 0x00000200 +#define MACH_RCV_INTERRUPT 0x00000400 +#define MACH_RCV_OVERWRITE 0x00001000 +#define MACH_SEND_ALWAYS 0x00010000 +#define MACH_SEND_TRAILER 0x00020000 + +/* mach_msg error codes */ +#define MACH_MSG_SUCCESS 0x00000000 +#define MACH_MSG_MASK 0x00003e00 +#define MACH_MSG_IPC_SPACE 0x00002000 +#define MACH_MSG_VM_SPACE 0x00001000 +#define MACH_MSG_IPC_KERNEL 0x00000800 +#define MACH_MSG_VM_KERNEL 0x00000400 +#define MACH_SEND_MSG 0x00000001 +#define MACH_SEND_TIMEOUT 0x00000010 +#define MACH_SEND_INTERRUPT 0x00000040 +#define MACH_SEND_CANCEL 0x00000080 +#define MACH_SEND_ALWAYS 0x00010000 +#define MACH_SEND_TRAILER 0x00020000 +#define MACH_SEND_IN_PROGRESS 0x10000001 +#define MACH_SEND_INVALID_DATA 0x10000002 +#define MACH_SEND_INVALID_DEST 0x10000003 +#define MACH_SEND_TIMED_OUT 0x10000004 +#define MACH_SEND_INTERRUPTED 0x10000007 +#define MACH_SEND_MSG_TOO_SMALL 0x10000008 +#define MACH_SEND_INVALID_REPLY 0x10000009 +#define MACH_SEND_INVALID_RIGHT 0x1000000a +#define MACH_SEND_INVALID_NOTIFY 0x1000000b +#define MACH_SEND_INVALID_MEMORY 0x1000000c +#define MACH_SEND_NO_BUFFER 0x1000000d +#define MACH_SEND_TOO_LARGE 0x1000000e +#define MACH_SEND_INVALID_TYPE 0x1000000f +#define MACH_SEND_INVALID_HEADER 0x10000010 +#define MACH_SEND_INVALID_TRAILER 0x10000011 +#define MACH_SEND_INVALID_RT_OOL_SIZE 0x10000015 +#define MACH_RCV_IN_PROGRESS 0x10004001 +#define MACH_RCV_INVALID_NAME 0x10004002 +#define MACH_RCV_TIMED_OUT 0x10004003 +#define MACH_RCV_TOO_LARGE 0x10004004 +#define MACH_RCV_INTERRUPTED 0x10004005 +#define MACH_RCV_PORT_CHANGED 0x10004006 +#define MACH_RCV_INVALID_NOTIFY 0x10004007 +#define MACH_RCV_INVALID_DATA 0x10004008 +#define MACH_RCV_PORT_DIED 0x10004009 +#define MACH_RCV_IN_SET 0x1000400a +#define MACH_RCV_HEADER_ERROR 0x1000400b +#define MACH_RCV_BODY_ERROR 0x1000400c +#define MACH_RCV_INVALID_TYPE 0x1000400d +#define MACH_RCV_SCATTER_SMALL 0x1000400e +#define MACH_RCV_INVALID_TRAILER 0x1000400f +#define MACH_RCV_IN_PROGRESS_TIMED 0x10004011 + +#define MACH_MSG_OPTION_BITS "\177\20" \ + "b\00send_msg\0b\01rcv_msg\0" \ + "b\02rcv_large\0b\03invalid[0x8]\0" \ + "b\04send_timeout\0b05invalid[0x20]\0" \ + "b\06send_interrupt\0b\05send_cancel\0" \ + "b\06rcv_timeout\0b\07rcv_notify\0" \ + "b\10rcv_interrupt\0b\11invalid[0x800]\0" \ + "b\12rcv_overwrite\0b\13invalid[0x2000]\0" \ + "b\14invalid[0x4000]\0b\15invalid[0x8000]\0" \ + "b\16send_always\0b\17send_trailer\0" + +#define MACH_MSGH_BITS_REMOTE_MASK 0x000000ff +#define MACH_MSGH_BITS_LOCAL_MASK 0x0000ff00 +#define MACH_MSGH_BITS_COMPLEX 0x80000000 +#define MACH_MSGH_LOCAL_BITS(bits) (((bits) >> 8) & 0xff) +#define MACH_MSGH_REMOTE_BITS(bits) ((bits) & 0xff) +#define MACH_MSGH_REPLY_LOCAL_BITS(bits) (((bits) << 8) & 0xff00) + +#define MACH_MSG_TYPE_MOVE_RECEIVE 16 +#define MACH_MSG_TYPE_MOVE_SEND 17 +#define MACH_MSG_TYPE_MOVE_SEND_ONCE 18 +#define MACH_MSG_TYPE_COPY_SEND 19 +#define MACH_MSG_TYPE_MAKE_SEND 20 +#define MACH_MSG_TYPE_MAKE_SEND_ONCE 21 +#define MACH_MSG_TYPE_COPY_RECEIVE 22 + +typedef unsigned int mach_msg_copy_options_t; + +#define MACH_MSG_PHYSICAL_COPY 0 +#define MACH_MSG_VIRTUAL_COPY 1 +#define MACH_MSG_ALLOCATE 2 +#define MACH_MSG_OVERWRITE 3 +#define MACH_MSG_KALLOC_COPY_T 4 +#define MACH_MSG_PAGE_LIST_COPY_T 5 + +typedef unsigned int mach_msg_descriptor_type_t; + +#define MACH_MSG_PORT_DESCRIPTOR 0 +#define MACH_MSG_OOL_DESCRIPTOR 1 +#define MACH_MSG_OOL_PORTS_DESCRIPTOR 2 +#define MACH_MSG_OOL_VOLATILE_DESCRIPTOR 3 + +#define MACH_MAX_MSG_LEN 65536 + +typedef struct { + mach_msg_bits_t msgh_bits; + mach_msg_size_t msgh_size; + mach_port_t msgh_remote_port; + mach_port_t msgh_local_port; + mach_msg_size_t msgh_reserved; + mach_msg_id_t msgh_id; +} mach_msg_header_t; + +#define MACH_MSG_TRAILER_FORMAT_0 0 +typedef u_int32_t mach_msg_trailer_type_t; +typedef u_int32_t mach_msg_trailer_size_t; +typedef struct { + mach_msg_trailer_type_t msgh_trailer_type; + mach_msg_trailer_size_t msgh_trailer_size; +} mach_msg_trailer_t; + +typedef struct { + void* pad1; + mach_msg_size_t pad2; + unsigned int pad3 : 24; + mach_msg_descriptor_type_t type : 8; +} mach_msg_type_descriptor_t; + +typedef struct { + mach_port_t name; + mach_msg_size_t pad1; + unsigned int pad2 : 16; + mach_msg_type_name_t disposition : 8; + mach_msg_descriptor_type_t type : 8; +} mach_msg_port_descriptor_t; + +typedef struct { + void * address; + mach_msg_size_t count; + mach_boolean_t deallocate: 8; + mach_msg_copy_options_t copy: 8; + mach_msg_type_name_t disposition : 8; + mach_msg_descriptor_type_t type : 8; +} mach_msg_ool_ports_descriptor_t; + +typedef struct { + void * address; + mach_msg_size_t size; + mach_boolean_t deallocate : 8; + mach_msg_copy_options_t copy : 8; + unsigned int pad1 : 8; + mach_msg_descriptor_type_t type : 8; +} mach_msg_ool_descriptor_t; + +typedef struct { + mach_msg_size_t msgh_descriptor_count; +} mach_msg_body_t; + +#define MACH_REQMSG_OVERFLOW(args, test) \ + (((u_long)&test - (u_long)args->smsg) > args->ssize) + +struct mach_short_reply { + mach_msg_header_t sr_header; + mach_msg_trailer_t sr_trailer; +}; + +struct mach_complex_msg { + mach_msg_header_t mcm_header; + mach_msg_body_t mcm_body; + union { + mach_msg_type_descriptor_t gen[1]; + mach_msg_port_descriptor_t port[1]; + mach_msg_ool_ports_descriptor_t ool_ports[1]; + mach_msg_ool_descriptor_t ool[1]; + } mcm_desc; +}; + +/* Kernel-private structures */ + +struct mach_trap_args { + struct lwp *l; /* Current task (doing the Mach system call) */ + struct lwp *tl; /* Target task */ + void *smsg; /* Sent message */ + void *rmsg; /* Reply message */ + size_t ssize; /* Sent message size */ + size_t *rsize; /* Reply message maximum size, may be lowered */ +}; + +struct mach_service { + int srv_id; + int (*srv_handler)(struct mach_trap_args *); + const char *srv_name; + size_t srv_reqlen; /* Minimum length of the request message */ + size_t srv_replen; /* Maximum length of the reply message */ +}; +extern struct mach_service mach_services_table[]; + + +/* In-kernel Mach messages description */ +struct mach_message { + mach_msg_header_t *mm_msg; /* In-kernel copy of the message */ + size_t mm_size; /* Message size */ + TAILQ_ENTRY(mach_message) mm_list; + /* List of pending messages */ + struct mach_port *mm_port; /* The port on which msg is queued */ + struct lwp *mm_l; /* The thread that sent it */ +}; + +/* Flags for mach_ool_copy{in|out} */ +#define MACH_OOL_NONE 0x0 +#define MACH_OOL_FREE 0x1 /* Free kernel buffer after copyout */ +#define MACH_OOL_TRACE 0x2 /* ktrace OOL data */ + +__inline int mach_ool_copyin(struct lwp *, const void *, void **, size_t, int); +__inline int mach_ool_copyout(struct lwp *, const void *, void **, size_t, int); +__inline void mach_set_trailer(void *, size_t); +__inline void mach_set_header(void *, void *, size_t); +__inline void mach_add_port_desc(void *, mach_port_name_t); +__inline void mach_add_ool_ports_desc(void *, void *, int); +__inline void mach_add_ool_desc(void *, void *, size_t); +void mach_message_init(void); +struct mach_message *mach_message_get(mach_msg_header_t *, + size_t, struct mach_port *, struct lwp *); +void mach_message_put(struct mach_message *); +void mach_message_put_shlocked(struct mach_message *); +void mach_message_put_exclocked(struct mach_message *); +#ifdef DEBUG_MACH +void mach_debug_message(void); +#endif + +#endif /* !_MACH_MESSAGE_H_ */ diff --git a/sys/compat/mach/mach_misc.c b/sys/compat/mach/mach_misc.c new file mode 100644 index 0000000..84f9c83 --- /dev/null +++ b/sys/compat/mach/mach_misc.c @@ -0,0 +1,217 @@ +/* $NetBSD: mach_misc.c,v 1.28 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MACH compatibility module. + * + * We actually don't implement anything here yet! + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_misc.c,v 1.28 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + + +int +mach_sys_semaphore_timedwait_trap(struct lwp *l, const struct mach_sys_semaphore_timedwait_trap_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_semaphore_timedwait_trap(0x%x, %d, %d);\n", + SCARG(uap, wait_name), SCARG(uap, sec), SCARG(uap, nsec))); + return 0; +} + + +int +mach_sys_semaphore_timedwait_signal_trap(struct lwp *l, const struct mach_sys_semaphore_timedwait_signal_trap_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(( + "mach_sys_semaphore_timedwait_signal_trap(0x%x, 0x%x, %d, %d);\n", + SCARG(uap, wait_name), SCARG(uap, signal_name), SCARG(uap, sec), + SCARG(uap, nsec))); + return 0; +} + + +int +mach_sys_init_process(struct lwp *l, const void *v, register_t *retval) +{ + *retval = 0; + DPRINTF(("mach_sys_init_process();\n")); + return 0; +} + + +int +mach_sys_pid_for_task(struct lwp *l, const struct mach_sys_pid_for_task_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_pid_for_task(0x%x, %p);\n", + SCARG(uap, t), SCARG(uap, x))); + return 0; +} + + +int +mach_sys_macx_swapon(struct lwp *l, const struct mach_sys_macx_swapon_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_macx_swapon(%p, %d, %d, %d);\n", + SCARG(uap, name), SCARG(uap, flags), SCARG(uap, size), + SCARG(uap, priority))); + return 0; +} + +int +mach_sys_macx_swapoff(struct lwp *l, const struct mach_sys_macx_swapoff_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_macx_swapoff(%p, %d);\n", + SCARG(uap, name), SCARG(uap, flags))); + return 0; +} + +int +mach_sys_macx_triggers(struct lwp *l, const struct mach_sys_macx_triggers_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_macx_triggers(%d, %d, %d, 0x%x);\n", + SCARG(uap, hi_water), SCARG(uap, low_water), SCARG(uap, flags), + SCARG(uap, alert_port))); + return 0; +} + + +int +mach_sys_wait_until(struct lwp *l, const struct mach_sys_wait_until_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_wait_until(%lld);\n", + SCARG(uap, deadline))); + return 0; +} + + +int +mach_sys_timer_create(struct lwp *l, const void *v, register_t *retval) +{ + *retval = 0; + DPRINTF(("mach_sys_timer_create();\n")); + return 0; +} + + +int +mach_sys_timer_destroy(struct lwp *l, const struct mach_sys_timer_destroy_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_timer_destroy(0x%x);\n", SCARG(uap, name))); + return 0; +} + + +int +mach_sys_timer_arm(struct lwp *l, const struct mach_sys_timer_arm_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_timer_arm(0x%x, %d);\n", + SCARG(uap, name), SCARG(uap, expire_time))); + return 0; +} + + +int +mach_sys_timer_cancel(struct lwp *l, const struct mach_sys_timer_cancel_args *uap, register_t *retval) +{ + + *retval = 0; + DPRINTF(("mach_sys_timer_cancel(0x%x, %p);\n", + SCARG(uap, name), SCARG(uap, result_time))); + return 0; +} + + +int +mach_sys_get_time_base_info(struct lwp *l, const void *v, register_t *retval) +{ + *retval = 0; + DPRINTF(("mach_sys_get_time_base_info();\n")); + return 0; +} diff --git a/sys/compat/mach/mach_notify.c b/sys/compat/mach/mach_notify.c new file mode 100644 index 0000000..3f5f8fb --- /dev/null +++ b/sys/compat/mach/mach_notify.c @@ -0,0 +1,182 @@ +/* $NetBSD: mach_notify.c,v 1.20 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_notify.c,v 1.20 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void +mach_notify_port_destroyed(struct lwp *l, struct mach_right *mr) +{ + struct mach_port *mp; + mach_notify_port_destroyed_request_t *req; + + if (mr->mr_notify_destroyed == NULL) + return; + + mp = mr->mr_notify_destroyed->mr_port; + +#ifdef DIAGNOSTIC + if ((mp == NULL) || (mp->mp_recv == NULL)) { + printf("mach_notify_port_destroyed: bad port or receiver\n"); + return; + } +#endif + + MACH_PORT_REF(mp); + + req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO); + + req->req_msgh.msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + req->req_msgh.msgh_size = sizeof(*req) - sizeof(req->req_trailer); + req->req_msgh.msgh_local_port = mr->mr_notify_destroyed->mr_name; + req->req_msgh.msgh_id = MACH_NOTIFY_DESTROYED_MSGID; + req->req_body.msgh_descriptor_count = 1; + req->req_rights.name = mr->mr_name; + + mach_set_trailer(req, sizeof(*req)); + + (void)mach_message_get((mach_msg_header_t *)req, sizeof(*req), mp, l); +#ifdef DEBUG_MACH_MSG + printf("pid %d: message queued on port %p (%d) [%p]\n", + l->l_proc->p_pid, mp, req->req_msgh.msgh_id, + mp->mp_recv->mr_sethead); +#endif + wakeup(mp->mp_recv->mr_sethead); + + MACH_PORT_UNREF(mp); + + return; +} + +void +mach_notify_port_no_senders(struct lwp *l, struct mach_right *mr) +{ + struct mach_port *mp; + mach_notify_port_no_senders_request_t *req; + + if ((mr->mr_notify_no_senders == NULL) || + (mr->mr_notify_no_senders->mr_port == NULL)) + return; + mp = mr->mr_notify_no_senders->mr_port; + +#ifdef DIAGNOSTIC + if ((mp == NULL) || + (mp->mp_recv == NULL) || + (mp->mp_datatype != MACH_MP_NOTIFY_SYNC)) { + printf("mach_notify_port_no_senders: bad port or reciever\n"); + return; + } +#endif + MACH_PORT_REF(mp); + if ((int)mp->mp_data >= mr->mr_refcount) + goto out; + + req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO); + + req->req_msgh.msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + req->req_msgh.msgh_size = sizeof(*req) - sizeof(req->req_trailer); + req->req_msgh.msgh_local_port = mr->mr_notify_no_senders->mr_name; + req->req_msgh.msgh_id = MACH_NOTIFY_NO_SENDERS_MSGID; + req->req_mscount = mr->mr_refcount; + + mach_set_trailer(req, sizeof(*req)); + + (void)mach_message_get((mach_msg_header_t *)req, sizeof(*req), mp, l); +#ifdef DEBUG_MACH_MSG + printf("pid %d: message queued on port %p (%d) [%p]\n", + l->l_proc->p_pid, mp, req->req_msgh.msgh_id, + mp->mp_recv->mr_sethead); +#endif + wakeup(mp->mp_recv->mr_sethead); + +out: + MACH_PORT_UNREF(mp); + return; +} + +void +mach_notify_port_dead_name(struct lwp *l, struct mach_right *mr) +{ + struct mach_port *mp; + mach_notify_port_dead_name_request_t *req; + + if ((mr->mr_notify_dead_name == NULL) || + (mr->mr_notify_dead_name->mr_port == NULL)) + return; + mp = mr->mr_notify_dead_name->mr_port; + +#ifdef DIAGNOSTIC + if ((mp == NULL) || (mp->mp_recv)) { + printf("mach_notify_port_dead_name: bad port or reciever\n"); + return; + } +#endif + MACH_PORT_REF(mp); + + req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO); + + req->req_msgh.msgh_bits = + MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE); + req->req_msgh.msgh_size = sizeof(*req) - sizeof(req->req_trailer); + req->req_msgh.msgh_local_port = mr->mr_notify_dead_name->mr_name; + req->req_msgh.msgh_id = MACH_NOTIFY_DEAD_NAME_MSGID; + req->req_name = mr->mr_name; + + mach_set_trailer(req, sizeof(*req)); + + mr->mr_refcount++; + + (void)mach_message_get((mach_msg_header_t *)req, sizeof(*req), mp, l); +#ifdef DEBUG_MACH_MSG + printf("pid %d: message queued on port %p (%d) [%p]\n", + l->l_proc->p_pid, mp, req->req_msgh.msgh_id, + mp->mp_recv->mr_sethead); +#endif + wakeup(mp->mp_recv->mr_sethead); + MACH_PORT_UNREF(mp); + + return; +} diff --git a/sys/compat/mach/mach_notify.h b/sys/compat/mach/mach_notify.h new file mode 100644 index 0000000..06b2bd4 --- /dev/null +++ b/sys/compat/mach/mach_notify.h @@ -0,0 +1,79 @@ +/* $NetBSD: mach_notify.h,v 1.10 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_NOTIFICATION_H_ +#define _MACH_NOTIFICATION_H_ + +#define MACH_NOTIFY_DELETED_MSGID 65 +#define MACH_NOTIFY_DESTROYED_MSGID 69 +#define MACH_NOTIFY_NO_SENDERS_MSGID 70 +#define MACH_NOTIFY_SEND_ONCE_MSGID 71 +#define MACH_NOTIFY_DEAD_NAME_MSGID 72 + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_msg_trailer_t req_trailer; +} mach_notify_port_deleted_request_t; + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_rights; + mach_msg_trailer_t req_trailer; +} mach_notify_port_destroyed_request_t; + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_mscount_t req_mscount; + mach_msg_trailer_t req_trailer; +} mach_notify_port_no_senders_request_t; + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_trailer_t req_trailer; +} mach_notify_send_once_request_t; + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_msg_trailer_t req_trailer; +} mach_notify_port_dead_name_request_t; + +void mach_notify_port_destroyed(struct lwp *, struct mach_right *); +void mach_notify_port_no_senders(struct lwp *, struct mach_right *); +void mach_notify_port_dead_name(struct lwp *, struct mach_right *); + +#endif /* _MACH_NOTIFICATION_H_ */ + diff --git a/sys/compat/mach/mach_port.c b/sys/compat/mach/mach_port.c new file mode 100644 index 0000000..a891600 --- /dev/null +++ b/sys/compat/mach/mach_port.c @@ -0,0 +1,1004 @@ +/* $NetBSD: mach_port.c,v 1.66 2009/03/18 16:00:17 cegger Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_compat_darwin.h" + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.66 2009/03/18 16:00:17 cegger Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef COMPAT_DARWIN +#include +#endif + +/* Right and port pools, list of all rights and its lock */ +static struct pool mach_port_pool; +static struct pool mach_right_pool; + +struct mach_port *mach_bootstrap_port; +struct mach_port *mach_clock_port; +struct mach_port *mach_io_master_port; +struct mach_port *mach_saved_bootstrap_port; + +int +mach_sys_reply_port(struct lwp *l, const void *v, register_t *retval) +{ + struct mach_right *mr; + + mr = mach_right_get(mach_port_get(), l, MACH_PORT_TYPE_RECEIVE, 0); + *retval = (register_t)mr->mr_name; + + return 0; +} + +int +mach_sys_thread_self_trap(struct lwp *l, const void *v, register_t *retval) +{ + struct mach_lwp_emuldata *mle; + struct mach_right *mr; + + mle = l->l_emuldata; + mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0); + *retval = (register_t)mr->mr_name; + + return 0; +} + + +int +mach_sys_task_self_trap(struct lwp *l, const void *v, register_t *retval) +{ + struct mach_emuldata *med; + struct mach_right *mr; + + med = (struct mach_emuldata *)l->l_proc->p_emuldata; + mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0); + *retval = (register_t)mr->mr_name; + + return 0; +} + + +int +mach_sys_host_self_trap(struct lwp *l, const void *v, register_t *retval) +{ + struct mach_emuldata *med; + struct mach_right *mr; + + med = (struct mach_emuldata *)l->l_proc->p_emuldata; + mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0); + *retval = (register_t)mr->mr_name; + + return 0; +} + +int +mach_port_deallocate(struct mach_trap_args *args) +{ + mach_port_deallocate_request_t *req = args->smsg; + mach_port_deallocate_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + + mn = req->req_name; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_REF_RIGHTS)) != NULL) + mach_right_put(mr, MACH_PORT_TYPE_REF_RIGHTS); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_destroy(struct mach_trap_args *args) +{ + mach_port_destroy_request_t *req = args->smsg; + mach_port_destroy_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + +#ifdef DEBUG_MACH + printf("mach_port_destroy mn = %x\n", req->req_name); +#endif + mn = req->req_name; + if ((mr = mach_right_check(mn, + l, MACH_PORT_TYPE_ALL_RIGHTS)) != NULL) { + MACH_PORT_UNREF(mr->mr_port); + mr->mr_port = NULL; + mach_right_put(mr, MACH_PORT_TYPE_ALL_RIGHTS); + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_allocate(struct mach_trap_args *args) +{ + mach_port_allocate_request_t *req = args->smsg; + mach_port_allocate_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_right *mr; + struct mach_port *mp; + + switch (req->req_right) { + case MACH_PORT_RIGHT_RECEIVE: + mp = mach_port_get(); + mr = mach_right_get(mp, l, MACH_PORT_TYPE_RECEIVE, 0); + break; + + case MACH_PORT_RIGHT_DEAD_NAME: + mr = mach_right_get(NULL, l, MACH_PORT_TYPE_DEAD_NAME, 0); + break; + + case MACH_PORT_RIGHT_PORT_SET: + mr = mach_right_get(NULL, l, MACH_PORT_TYPE_PORT_SET, 0); + break; + + default: + uprintf("mach_port_allocate: unknown right %x\n", + req->req_right); + return mach_msg_error(args, EINVAL); + break; + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + rep->rep_name = (mach_port_name_t)mr->mr_name; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_insert_right(struct mach_trap_args *args) +{ + mach_port_insert_right_request_t *req = args->smsg; + mach_port_insert_right_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t name; + mach_port_t right; + struct mach_right *mr; + struct mach_right *nmr; + + name = req->req_name; + right = req->req_poly.name; + nmr = NULL; + + mr = mach_right_check(right, l, MACH_PORT_TYPE_ALL_RIGHTS); + if (mr == NULL) + return mach_msg_error(args, EPERM); + + switch (req->req_poly.disposition) { + case MACH_MSG_TYPE_MAKE_SEND: + case MACH_MSG_TYPE_MOVE_SEND: + case MACH_MSG_TYPE_COPY_SEND: + nmr = mach_right_get(mr->mr_port, + l, MACH_PORT_TYPE_SEND, name); + break; + + case MACH_MSG_TYPE_MAKE_SEND_ONCE: + case MACH_MSG_TYPE_MOVE_SEND_ONCE: + nmr = mach_right_get(mr->mr_port, + l, MACH_PORT_TYPE_SEND_ONCE, name); + break; + + case MACH_MSG_TYPE_MOVE_RECEIVE: + nmr = mach_right_get(mr->mr_port, + l, MACH_PORT_TYPE_RECEIVE, name); + break; + + default: + uprintf("mach_port_insert_right: unknown right %x\n", + req->req_poly.disposition); + break; + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_type(struct mach_trap_args *args) +{ + mach_port_type_request_t *req = args->smsg; + mach_port_type_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + + mn = req->req_name; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EPERM); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + rep->rep_ptype = mr->mr_type; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_set_attributes(struct mach_trap_args *args) +{ + mach_port_set_attributes_request_t *req = args->smsg; + mach_port_set_attributes_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + int end_offset; + + /* Sanity check req->req_count */ + end_offset = req->req_count; + if (MACH_REQMSG_OVERFLOW(args, req->req_port_info[end_offset])) + return mach_msg_error(args, EINVAL); + + switch(req->req_flavor) { + case MACH_PORT_LIMITS_INFO: + case MACH_PORT_RECEIVE_STATUS: + case MACH_PORT_DNREQUESTS_SIZE: + break; + default: + uprintf("mach_port_set_attributes: unknown flavor %d\n", + req->req_flavor); + break; + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_get_attributes(struct mach_trap_args *args) +{ + mach_port_get_attributes_request_t *req = args->smsg; + mach_port_get_attributes_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + + /* Sanity check req_count */ + if (req->req_count > 10) + return mach_msg_error(args, EINVAL); + + mn = req->req_msgh.msgh_remote_port; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EPERM); + + switch (req->req_flavor) { + case MACH_PORT_LIMITS_INFO: { + struct mach_port_limits *mpl; + + if (req->req_count < (sizeof(*mpl) / sizeof(rep->rep_info[0]))) + return mach_msg_error(args, EINVAL); + + mpl = (struct mach_port_limits *)&rep->rep_info[0]; + mpl->mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT; /* XXX fake limit */ + + rep->rep_count = sizeof(*mpl); + + break; + } + + case MACH_PORT_RECEIVE_STATUS: { + struct mach_port_status *mps; + struct mach_port *mp; + + if (req->req_count < (sizeof(*mps) / sizeof(rep->rep_info[0]))) + return mach_msg_error(args, EINVAL); + + mps = (struct mach_port_status *)&rep->rep_info[0]; + memset(mps, 0, sizeof(*mps)); + + if (mr->mr_sethead != NULL) + mps->mps_pset = mr->mr_sethead->mr_name; + mps->mps_seqno = 0; /* XXX */ + mps->mps_qlimit = MACH_PORT_QLIMIT_DEFAULT; /* XXX fake limit */ + if ((mp = mr->mr_port) != NULL) { + mps->mps_mscount = mp->mp_refcount; /* XXX */ + mps->mps_msgcount = mp->mp_count; + } else { + mps->mps_mscount = 0; + mps->mps_msgcount = 0; + } + mps->mps_sorights = 0; /* XXX */ + mps->mps_srights = 0; /* XXX */ + if (mr->mr_notify_destroyed != NULL) + mps->mps_pdrequest = 1; + if (mr->mr_notify_no_senders != NULL) + mps->mps_nsrequest = 1; + mps->mps_flags = 0; /* XXX */ + + rep->rep_count = sizeof(*mps); + break; + } + + default: + printf("mach_port_get_attributes: unknown flavor %d\n", + req->req_flavor); + return mach_msg_error(args, EINVAL); + + break; + }; + + *msglen = sizeof(*rep) - 10 + rep->rep_count; + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +/* XXX insert a recv right into a port set without removing it from another */ +int +mach_port_insert_member(struct mach_trap_args *args) +{ + mach_port_insert_member_request_t *req = args->smsg; + mach_port_insert_member_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + + uprintf("Unimplemented mach_port_insert_member\n"); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_move_member(struct mach_trap_args *args) +{ + mach_port_move_member_request_t *req = args->smsg; + mach_port_move_member_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_emuldata *med = l->l_proc->p_emuldata; + mach_port_t member = req->req_member; + mach_port_t after = req->req_after; + struct mach_right *mrr; + struct mach_right *mrs; + + mrr = mach_right_check(member, l, MACH_PORT_TYPE_RECEIVE); + if (mrr == NULL) + return mach_msg_error(args, EPERM); + + mrs = mach_right_check(after, l, MACH_PORT_TYPE_PORT_SET); + if (mrs == NULL) + return mach_msg_error(args, EPERM); + + rw_enter(&med->med_rightlock, RW_WRITER); + + /* Remove it from an existing port set */ + if (mrr->mr_sethead != mrr) + LIST_REMOVE(mrr, mr_setlist); + + /* Insert it into the new port set */ + LIST_INSERT_HEAD(&mrs->mr_set, mrr, mr_setlist); + mrr->mr_sethead = mrs; + + rw_exit(&med->med_rightlock); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_request_notification(struct mach_trap_args *args) +{ + mach_port_request_notification_request_t *req = args->smsg; + mach_port_request_notification_reply_t *rep = args->rmsg; + struct lwp *l = args->l; + size_t *msglen = args->rsize; + mach_port_t mn; + struct mach_right *nmr; + struct mach_right *tmr; + struct mach_right *oldnmr; + mach_port_t oldmn; + +#ifdef DEBUG_MACH + printf("mach_port_request_notification, notify = %08x, target = %08x\n", + req->req_notify.name, mn = req->req_name); +#endif + mn = req->req_notify.name; + if ((nmr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EINVAL); + + mn = req->req_name; + if ((tmr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EINVAL); + +#ifdef DEBUG_MACH + if (nmr->mr_port == NULL) { + printf("Notification right without a port\n"); + printf("mr->mr_port = %p, mr = %08x\n", nmr->mr_port, nmr->mr_name); + return mach_msg_error(args, EINVAL); + } +#endif + + + oldnmr = NULL; + switch(req->req_msgid) { + case MACH_NOTIFY_DESTROYED_MSGID: + oldnmr = tmr->mr_notify_destroyed; + tmr->mr_notify_destroyed = mach_right_get(nmr->mr_port, + l, MACH_PORT_TYPE_SEND_ONCE, req->req_notify.name); + break; + + case MACH_NOTIFY_NO_SENDERS_MSGID: + oldnmr = tmr->mr_notify_no_senders; + tmr->mr_notify_no_senders = mach_right_get(nmr->mr_port, + l, MACH_PORT_TYPE_SEND_ONCE, req->req_notify.name); + tmr->mr_notify_no_senders->mr_port->mp_datatype = + MACH_MP_NOTIFY_SYNC; + tmr->mr_notify_no_senders->mr_port->mp_data = (void *) + req->req_count; + break; + + case MACH_NOTIFY_DEAD_NAME_MSGID: + oldnmr = tmr->mr_notify_dead_name; + tmr->mr_notify_dead_name = mach_right_get(nmr->mr_port, + l, MACH_PORT_TYPE_SEND_ONCE, req->req_notify.name); + break; + + case MACH_NOTIFY_SEND_ONCE_MSGID: + case MACH_NOTIFY_DELETED_MSGID: + default: +#ifdef DEBUG_MACH + printf("unsupported notify request %d\n", req->req_msgid); + return mach_msg_error(args, EINVAL); +#endif + break; + } + + if (oldnmr != NULL) { + oldnmr->mr_refcount++; + oldmn = oldnmr->mr_name; + } else { + oldmn = (mach_port_t)MACH_PORT_NULL; + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, oldmn); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_get_refs(struct mach_trap_args *args) +{ + mach_port_get_refs_request_t *req = args->smsg; + mach_port_get_refs_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + mach_port_right_t right = req->req_right; + + mn = req->req_name; + if ((mr = mach_right_check(mn, l, right)) == NULL) + return mach_msg_error(args, EINVAL); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + rep->rep_refs = mr->mr_refcount; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_port_mod_refs(struct mach_trap_args *args) +{ + mach_port_mod_refs_request_t *req = args->smsg; + mach_port_mod_refs_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; +#if 0 + struct lwp *l = args->l; + mach_port_t mn; + struct mach_right *mr; + mach_port_right_t right = req->req_right; + + mn = req->req_name; + if ((mr = mach_right_check(mn, l, right)) == NULL) + return mach_msg_error(args, EINVAL); + + /* + * Changing the refcount is likely to cause crashes, + * as we will free a right which might still be referenced + * within the kernel. Add a user refcount field? + */ + mr->mr_refcount += req->req_delta; + if (mr->mr_refcount <= 0) + mach_right_put(mr, right); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +void +mach_port_init(void) +{ + pool_init(&mach_port_pool, sizeof (struct mach_port), + 0, 0, 0, "mach_port_pool", NULL, IPL_NONE); + pool_init(&mach_right_pool, sizeof (struct mach_right), + 0, 0, 0, "mach_right_pool", NULL, IPL_NONE); + + mach_bootstrap_port = mach_port_get(); + mach_clock_port = mach_port_get(); + mach_io_master_port = mach_port_get(); + + mach_bootstrap_port->mp_flags |= MACH_MP_INKERNEL; + mach_clock_port->mp_flags |= MACH_MP_INKERNEL; + mach_io_master_port->mp_flags |= MACH_MP_INKERNEL; + + mach_saved_bootstrap_port = mach_bootstrap_port; + + return; +} + +struct mach_port * +mach_port_get(void) +{ + struct mach_port *mp; + + mp = (struct mach_port *)pool_get(&mach_port_pool, PR_WAITOK); + memset(mp, 0, sizeof(*mp)); + mp->mp_recv = NULL; + mp->mp_count = 0; + mp->mp_flags = 0; + mp->mp_datatype = MACH_MP_NONE; + mp->mp_data = NULL; + TAILQ_INIT(&mp->mp_msglist); + rw_init(&mp->mp_msglock); + + return mp; +} + +void +mach_port_put(struct mach_port *mp) +{ + struct mach_message *mm; + +#ifdef DIAGNOSTIC + if (mp->mp_refcount > 0) { + uprintf("mach_port_put: trying to free a referenced port\n"); + return; + } +#endif + + rw_enter(&mp->mp_msglock, RW_WRITER); + while ((mm = TAILQ_FIRST(&mp->mp_msglist)) != NULL) + mach_message_put_exclocked(mm); + rw_exit(&mp->mp_msglock); + rw_destroy(&mp->mp_msglock); + + if (mp->mp_flags & MACH_MP_DATA_ALLOCATED) + free(mp->mp_data, M_EMULDATA); + + pool_put(&mach_port_pool, mp); + + return; +} + +struct mach_right * +mach_right_get(struct mach_port *mp, struct lwp *l, int type, mach_port_t hint) +{ + struct mach_right *mr; + struct mach_emuldata *med; + int rights; + +#ifdef DEBUG_MACH + if (type == 0) + uprintf("mach_right_get: right = 0\n"); +#endif + med = (struct mach_emuldata *)l->l_proc->p_emuldata; + + if (mp != NULL) + MACH_PORT_REF(mp); + + /* Send and receive right must return an existing right */ + rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_RECEIVE); + if (type & rights) { + rw_enter(&med->med_rightlock, RW_READER); + LIST_FOREACH(mr, &med->med_right, mr_list) { + if ((mr->mr_port == mp) && (mr->mr_type & rights)) + break; + } + rw_exit(&med->med_rightlock); + + if (mr != NULL) { + mr->mr_type |= type; + if (type & MACH_PORT_TYPE_SEND) + mr->mr_refcount++; + goto rcvck; + } + } + + mr = pool_get(&mach_right_pool, PR_WAITOK); + + mr->mr_port = mp; + mr->mr_lwp = l; + mr->mr_type = type; + mr->mr_sethead = mr; + mr->mr_refcount = 1; + mr->mr_notify_destroyed = NULL; + mr->mr_notify_dead_name = NULL; + mr->mr_notify_no_senders = NULL; + + LIST_INIT(&mr->mr_set); + + /* Insert the right in the right lists */ + if (type & MACH_PORT_TYPE_ALL_RIGHTS) { + rw_enter(&med->med_rightlock, RW_WRITER); + mr->mr_name = mach_right_newname(l, hint); +#ifdef DEBUG_MACH_RIGHT + printf("mach_right_get: insert right %x(%x)\n", + mr->mr_name, mr->mr_type); +#endif + LIST_INSERT_HEAD(&med->med_right, mr, mr_list); + rw_exit(&med->med_rightlock); + } + +rcvck: + if (type & MACH_PORT_TYPE_RECEIVE) { + /* + * Destroy the former receive right on this port, and + * register the new right. + */ + if (mr->mr_port->mp_recv != NULL) + mach_right_put(mr->mr_port->mp_recv, + MACH_PORT_TYPE_RECEIVE); + mr->mr_port->mp_recv = mr; + } + return mr; +} + +void +mach_right_put(struct mach_right *mr, int right) +{ + struct mach_emuldata *med = mr->mr_lwp->l_proc->p_emuldata; + + rw_enter(&med->med_rightlock, RW_WRITER); + mach_right_put_exclocked(mr, right); + rw_exit(&med->med_rightlock); + + return; +} + +void +mach_right_put_shlocked(struct mach_right *mr, int right) +{ + struct mach_emuldata *med = mr->mr_lwp->l_proc->p_emuldata; + + if (!rw_tryupgrade(&med->med_rightlock)) { + /* XXX */ + rw_exit(&med->med_rightlock); + rw_enter(&med->med_rightlock, RW_WRITER); + } + mach_right_put_exclocked(mr, right); + rw_downgrade(&med->med_rightlock); + + return; +} + +void +mach_right_put_exclocked(struct mach_right *mr, int right) +{ + struct mach_right *cmr; + struct mach_emuldata *med; + int lright; + int kill_right; + + med = mr->mr_lwp->l_proc->p_emuldata; + +#ifdef DEBUG_MACH_RIGHT + printf("mach_right_put: mr = %p\n", mr); + printf("right %x(%x) refcount %d, deallocate %x\n", + mr->mr_name, mr->mr_type, mr->mr_refcount, right); + if ((mr->mr_type & right) == 0) + printf("mach_right_put: dropping nonexistant right %x on %x\n", + right, mr->mr_name); + LIST_FOREACH(cmr, &med->med_right, mr_list) + if (cmr == mr) + break; + if (cmr == NULL) { + printf("mach_right_put: dropping already dropped right %x\n", + mr->mr_name); + return; + } +#endif + kill_right = 0; + + /* When receive right is deallocated, the port should die */ + lright = (right & MACH_PORT_TYPE_RECEIVE); +#ifdef DEBUG_MACH_RIGHT + printf("mr->mr_type = %x, lright = %x, right = %x, refcount = %d\n", + mr->mr_type, lright, right, mr->mr_refcount); +#endif + if (mr->mr_type & lright) { + if (mr->mr_refcount <= 0) { + mr->mr_type &= ~MACH_PORT_TYPE_RECEIVE; + kill_right = 1; + } else { + mr->mr_type &= ~MACH_PORT_TYPE_RECEIVE; + mr->mr_type |= MACH_PORT_TYPE_DEAD_NAME; + mach_notify_port_dead_name(mr->mr_lwp, mr); + } + if (mr->mr_port != NULL) { + /* There is no more receiver */ +#ifdef DIAGNOSTIC + if (mr->mr_port->mp_recv != mr) + printf("several receiver on a single port\n"); +#endif + mr->mr_port->mp_recv = NULL; + + MACH_PORT_UNREF(mr->mr_port); + mr->mr_port = NULL; + } + } + + /* send, send_once and dead_name */ + lright = (right & MACH_PORT_TYPE_REF_RIGHTS); + if (mr->mr_type & lright) { + mr->mr_refcount--; + + mach_notify_port_no_senders(mr->mr_lwp, mr); + + if (mr->mr_refcount <= 0) { + mr->mr_type &= ~MACH_PORT_TYPE_REF_RIGHTS; + if ((mr->mr_type & MACH_PORT_TYPE_RECEIVE) == 0) + kill_right = 1; + } + } + + lright = (right & MACH_PORT_TYPE_PORT_SET); + if ((mr->mr_type & lright) || (kill_right == 1)) { + while ((cmr = LIST_FIRST(&mr->mr_set)) != NULL) { + LIST_REMOVE(cmr, mr_setlist); + cmr->mr_sethead = cmr; + } + mr->mr_type &= ~MACH_PORT_TYPE_PORT_SET; + if ((mr->mr_type & MACH_PORT_TYPE_RECEIVE) == 0) + kill_right = 1; + } + + /* Should we kill it? */ + if (kill_right == 1) { +#ifdef DEBUG_MACH_RIGHT + printf("mach_right_put: kill name %x\n", mr->mr_name); +#endif + /* If the right is used for an IO notification, remove it */ + mach_iokit_cleanup_notify(mr); + + mach_notify_port_destroyed(mr->mr_lwp, mr); + LIST_REMOVE(mr, mr_list); + pool_put(&mach_right_pool, mr); + } + return; +} + +/* + * Check that a process has a given right. + */ +struct mach_right * +mach_right_check(mach_port_t mn, struct lwp *l, int type) +{ + struct mach_right *cmr; + struct mach_emuldata *med; + + if ((mn == 0) || (mn == -1) || (l == NULL)) + return NULL; + + med = (struct mach_emuldata *)l->l_proc->p_emuldata; + + rw_enter(&med->med_rightlock, RW_READER); + +#ifdef DEBUG_MACH_RIGHT + printf("mach_right_check: type = %x, mn = %x\n", type, mn); +#endif + LIST_FOREACH(cmr, &med->med_right, mr_list) { +#ifdef DEBUG_MACH_RIGHT + printf("cmr = %p, cmr->mr_name = %x, cmr->mr_type = %x\n", + cmr, cmr->mr_name, cmr->mr_type); +#endif + if (cmr->mr_name != mn) + continue; + if (type & cmr->mr_type) + break; + } + + rw_exit(&med->med_rightlock); + + return cmr; +} + + +/* + * Find an usnused port name in a given lwp. + * Right lists should be locked. + */ +mach_port_t +mach_right_newname(struct lwp *l, mach_port_t hint) +{ + struct mach_emuldata *med; + struct mach_right *mr; + mach_port_t newname = -1; + + med = l->l_proc->p_emuldata; + + if (hint == 0) + hint = med->med_nextright; + + while (newname == -1) { + LIST_FOREACH(mr, &med->med_right, mr_list) + if (mr->mr_name == hint) + break; + if (mr == NULL) + newname = hint; + hint++; + } + + med->med_nextright = hint; + + return newname; +} + +#ifdef DEBUG_MACH +void +mach_debug_port(void) +{ + struct mach_emuldata *med; + struct mach_right *mr; + struct mach_right *mrs; + struct proc *p; + + PROCLIST_FOREACH(p, &allproc) { + if ((p->p_emul != &emul_mach) && +#ifdef COMPAT_DARWIN + (p->p_emul != &emul_darwin) && +#endif + 1) + continue; + + med = p->p_emuldata; + LIST_FOREACH(mr, &med->med_right, mr_list) { + if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) { + printf("pid %d: %p(%x)=>%p", + p->p_pid, mr, mr->mr_type, mr->mr_port); + if (mr->mr_port && mr->mr_port->mp_recv) + printf("[%p]\n", + mr->mr_port->mp_recv->mr_sethead); + else + printf("[NULL]\n"); + + continue; + } + + /* Port set... */ + printf("pid %d: set %p(%x) ", + p->p_pid, mr, mr->mr_type); + LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) { + printf("%p(%x)=>%p", + mrs, mrs->mr_type, mrs->mr_port); + if (mrs->mr_port && mrs->mr_port->mp_recv) + printf("[%p]", + mrs->mr_port->mp_recv->mr_sethead); + else + printf("[NULL]"); + + printf(" "); + } + printf("\n"); + } + } + return; +} + +#endif /* DEBUG_MACH */ diff --git a/sys/compat/mach/mach_port.h b/sys/compat/mach/mach_port.h new file mode 100644 index 0000000..8399791 --- /dev/null +++ b/sys/compat/mach/mach_port.h @@ -0,0 +1,363 @@ +/* $NetBSD: mach_port.h,v 1.40 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_PORT_H_ +#define _MACH_PORT_H_ + +#define MACH_PORT_REF(mp) (mp)->mp_refcount++ +#define MACH_PORT_UNREF(mp) if (--(mp)->mp_refcount <= 0) mach_port_put(mp) + +#define MACH_PORT_NULL (struct mach_right *)0 +#define MACH_PORT_DEAD (struct mach_right *)-1 + +#define MACH_PORT_RIGHT_SEND 0 +#define MACH_PORT_RIGHT_RECEIVE 1 +#define MACH_PORT_RIGHT_SEND_ONCE 2 +#define MACH_PORT_RIGHT_PORT_SET 3 +#define MACH_PORT_RIGHT_DEAD_NAME 4 +#define MACH_PORT_RIGHT_NUMBER 5 + +#define MACH_PORT_TYPE_SEND (1 << (MACH_PORT_RIGHT_SEND + 16)) +#define MACH_PORT_TYPE_RECEIVE (1 << (MACH_PORT_RIGHT_RECEIVE + 16)) +#define MACH_PORT_TYPE_SEND_ONCE (1 << (MACH_PORT_RIGHT_SEND_ONCE + 16)) +#define MACH_PORT_TYPE_PORT_SET (1 << (MACH_PORT_RIGHT_PORT_SET + 16)) +#define MACH_PORT_TYPE_DEAD_NAME (1 << (MACH_PORT_RIGHT_DEAD_NAME + 16)) +#define MACH_PORT_TYPE_PORT_RIGHTS \ + (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_RECEIVE | MACH_PORT_TYPE_SEND_ONCE) +#define MACH_PORT_TYPE_PORT_OR_DEAD \ + (MACH_PORT_TYPE_PORT_RIGHTS | MACH_PORT_TYPE_DEAD_NAME) +#define MACH_PORT_TYPE_ALL_RIGHTS \ + (MACH_PORT_TYPE_PORT_OR_DEAD|MACH_PORT_TYPE_PORT_SET) +#define MACH_PORT_TYPE_REF_RIGHTS \ + (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_SEND_ONCE | MACH_PORT_TYPE_DEAD_NAME) + +/* port_deallocate */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; +} mach_port_deallocate_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_deallocate_reply_t; + +/* port_allocate */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_right_t req_right; +} mach_port_allocate_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_port_name_t rep_name; + mach_msg_trailer_t rep_trailer; +} mach_port_allocate_reply_t; + +/* port_insert_right */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_poly; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; +} mach_port_insert_right_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_insert_right_reply_t; + +/* port_type */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; +} mach_port_type_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_port_type_t rep_ptype; + mach_msg_trailer_t rep_trailer; +} mach_port_type_reply_t; + +/* port_set_attributes */ + +#define MACH_PORT_LIMITS_INFO 1 +#define MACH_PORT_RECEIVE_STATUS 2 +#define MACH_PORT_DNREQUESTS_SIZE 3 + +typedef struct mach_port_status { + mach_port_name_t mps_pset; + mach_port_seqno_t mps_seqno; + mach_port_mscount_t mps_mscount; + mach_port_msgcount_t mps_qlimit; + mach_port_msgcount_t mps_msgcount; + mach_port_rights_t mps_sorights; + mach_boolean_t mps_srights; + mach_boolean_t mps_pdrequest; + mach_boolean_t mps_nsrequest; + unsigned int mps_flags; +} mach_port_status_t; + +typedef struct mach_port_limits { + mach_port_msgcount_t mpl_qlimit; +} mach_port_limits_t; + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_port_flavor_t req_flavor; + mach_msg_type_number_t req_count; + mach_integer_t req_port_info[0]; +} mach_port_set_attributes_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_set_attributes_reply_t; + +/* port_get_attributes */ + +#define MACH_PORT_QLIMIT_DEFAULT ((mach_port_msgcount_t) 5) +#define MACH_PORT_QLIMIT_MAX ((mach_port_msgcount_t) 16) + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_port_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_port_get_attributes_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_count; + mach_integer_t rep_info[10]; + mach_msg_trailer_t rep_trailer; +} mach_port_get_attributes_reply_t; + +/* port_insert_member */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_port_name_t req_pset; +} mach_port_insert_member_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_insert_member_reply_t; + +/* port_move_member */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_member; + mach_port_name_t req_after; +} mach_port_move_member_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_move_member_reply_t; + +/* port_destroy */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; +} mach_port_destroy_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_destroy_reply_t; + +/* port_request_notification */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_notify; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_msg_id_t req_msgid; + mach_port_mscount_t req_count; +} mach_port_request_notification_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_previous; + mach_msg_trailer_t rep_trailer; +} mach_port_request_notification_reply_t; + +/* port_get_refs */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_port_right_t req_right; +} mach_port_get_refs_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_port_urefs_t rep_refs; + mach_msg_trailer_t rep_trailer; +} mach_port_get_refs_reply_t; + +/* port_mod_refs */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_port_name_t req_name; + mach_port_right_t req_right; + mach_port_delta_t req_delta; +} mach_port_mod_refs_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_port_mod_refs_reply_t; + +/* Kernel-private structures */ + +extern struct mach_port *mach_clock_port; +extern struct mach_port *mach_io_master_port; +extern struct mach_port *mach_bootstrap_port; +extern struct mach_port *mach_saved_bootstrap_port; + +/* In-kernel Mach port right description */ +struct mach_right { + mach_port_t mr_name; /* The right name */ + struct lwp *mr_lwp; /* points back to struct lwp */ + int mr_type; /* right type (recv, send, sendonce) */ + LIST_ENTRY(mach_right) mr_list; /* Right list for a process */ + int mr_refcount; /* Reference count */ + struct mach_right *mr_notify_destroyed; /* notify destroyed */ + struct mach_right *mr_notify_dead_name; /* notify dead name */ + struct mach_right *mr_notify_no_senders; /* notify no senders */ + + /* Revelant only if the right is on a port set */ + LIST_HEAD(mr_set, mach_right) mr_set; + /* The right set list */ + + /* Revelant only if the right is not on a port set */ + struct mach_port *mr_port; /* Port we have the right on */ + LIST_ENTRY(mach_right) mr_setlist; /* Set list */ + + /* Revelant only if the right is part of a port set */ + struct mach_right *mr_sethead; /* Points back to right set */ +}; + +mach_port_t mach_right_newname(struct lwp *, mach_port_t); +struct mach_right *mach_right_get(struct mach_port *, + struct lwp *, int, mach_port_t); +void mach_right_put(struct mach_right *, int); +void mach_right_put_shlocked(struct mach_right *, int); +void mach_right_put_exclocked(struct mach_right *, int); +struct mach_right *mach_right_check(mach_port_t, struct lwp *, int); + +/* In-kernel Mach port description */ +struct mach_port { + struct mach_right *mp_recv; /* The receive right on this port */ + int mp_count; /* Count of queued messages */ + TAILQ_HEAD(mp_msglist, /* Queue pending messages */ + mach_message) mp_msglist; + krwlock_t mp_msglock; /* Lock for the queue */ + int mp_refcount; /* Reference count */ + int mp_flags; /* Flags, see below */ + int mp_datatype; /* Type of field mp_data, see below */ + void *mp_data; /* Data attached to the port */ +}; + +/* mp_flags for struct mach_port */ +#define MACH_MP_INKERNEL 0x01 /* Receiver is inside the kernel */ +#define MACH_MP_DATA_ALLOCATED 0x02 /* mp_data was malloc'ed */ + +/* mp_datatype for struct mach_port */ +#define MACH_MP_NONE 0x0 /* No data */ +#define MACH_MP_LWP 0x1 /* (struct lwp *) */ +#define MACH_MP_DEVICE_ITERATOR 0x2 /* (struct mach_device_iterator *) */ +#define MACH_MP_IOKIT_DEVCLASS 0x3 /* (struct mach_iokit_devclass *) */ +#define MACH_MP_PROC 0x4 /* (struct proc *) */ +#define MACH_MP_NOTIFY_SYNC 0x5 /* int */ +#define MACH_MP_MEMORY_ENTRY 0x6 /* (struct mach_memory_entry *) */ +#define MACH_MP_EXC_INFO 0x7 /* (struct mach_exc_info *) */ +#define MACH_MP_SEMAPHORE 0x8 /* (struct mach_semaphore *) */ + +void mach_port_init(void); +struct mach_port *mach_port_get(void); +void mach_port_put(struct mach_port *); +void mach_remove_recvport(struct mach_port *); +void mach_add_recvport(struct mach_port *, struct lwp *); +int mach_port_check(struct mach_port *); +#ifdef DEBUG_MACH +void mach_debug_port(void); +#endif + +#endif /* _MACH_PORT_H_ */ diff --git a/sys/compat/mach/mach_semaphore.c b/sys/compat/mach/mach_semaphore.c new file mode 100644 index 0000000..327c893 --- /dev/null +++ b/sys/compat/mach/mach_semaphore.c @@ -0,0 +1,438 @@ +/* $NetBSD: mach_semaphore.c,v 1.19 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_semaphore.c,v 1.19 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Semaphore list, lock, pools */ +static LIST_HEAD(mach_semaphore_list, mach_semaphore) mach_semaphore_list; +static krwlock_t mach_semaphore_list_lock; +static struct pool mach_semaphore_list_pool; +static struct pool mach_waiting_lwp_pool; + +/* Function to manipulate them */ +static struct mach_semaphore *mach_semaphore_get(int, int); +static void mach_semaphore_put(struct mach_semaphore *); +static struct mach_waiting_lwp *mach_waiting_lwp_get + (struct lwp *, struct mach_semaphore *); +static void mach_waiting_lwp_put + (struct mach_waiting_lwp *, struct mach_semaphore *, int); + +int +mach_sys_semaphore_wait_trap(struct lwp *l, const struct mach_sys_semaphore_wait_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_name_t) wait_name; + } */ + struct mach_semaphore *ms; + struct mach_waiting_lwp *mwl; + struct mach_right *mr; + mach_port_t mn; + int blocked = 0; + + mn = SCARG(uap, wait_name); + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0) + return EPERM; + + if (mr->mr_port->mp_datatype != MACH_MP_SEMAPHORE) + return EINVAL; + + ms = (struct mach_semaphore *)mr->mr_port->mp_data; + + rw_enter(&ms->ms_lock, RW_WRITER); + ms->ms_value--; + if (ms->ms_value < 0) + blocked = 1; + rw_exit(&ms->ms_lock); + + if (blocked != 0) { + mwl = mach_waiting_lwp_get(l, ms); + while (ms->ms_value < 0) + tsleep(mwl, PZERO|PCATCH, "sem_wait", 0); + mach_waiting_lwp_put(mwl, ms, 0); + } + return 0; +} + +int +mach_sys_semaphore_signal_trap(struct lwp *l, const struct mach_sys_semaphore_signal_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_name_t) signal_name; + } */ + struct mach_semaphore *ms; + struct mach_waiting_lwp *mwl; + struct mach_right *mr; + mach_port_t mn; + int unblocked = 0; + + mn = SCARG(uap, signal_name); + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0) + return EPERM; + + if (mr->mr_port->mp_datatype != MACH_MP_SEMAPHORE) + return EINVAL; + + ms = (struct mach_semaphore *)mr->mr_port->mp_data; + + rw_enter(&ms->ms_lock, RW_WRITER); + ms->ms_value++; + if (ms->ms_value >= 0) + unblocked = 1; + rw_exit(&ms->ms_lock); + + if (unblocked != 0) { + rw_enter(&ms->ms_lock, RW_READER); + mwl = TAILQ_FIRST(&ms->ms_waiting); + wakeup(mwl); + rw_exit(&ms->ms_lock); + } + return 0; +} + +int +mach_semaphore_create(struct mach_trap_args *args) +{ + mach_semaphore_create_request_t *req = args->smsg; + mach_semaphore_create_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct mach_semaphore *ms; + struct mach_port *mp; + struct mach_right *mr; + + ms = mach_semaphore_get(req->req_value, req->req_policy); + + mp = mach_port_get(); + mp->mp_datatype = MACH_MP_SEMAPHORE; + mp->mp_data = (void *)ms; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_semaphore_destroy(struct mach_trap_args *args) +{ + mach_semaphore_destroy_request_t *req = args->smsg; + mach_semaphore_destroy_reply_t *rep = args->rmsg; + struct lwp *l = args->l; + size_t *msglen = args->rsize; + struct mach_semaphore *ms; + struct mach_right *mr; + mach_port_t mn; + + mn = req->req_sem.name; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0) + return mach_msg_error(args, EPERM); + + if (mr->mr_port->mp_datatype != MACH_MP_SEMAPHORE) + return mach_msg_error(args, EINVAL); + + ms = (struct mach_semaphore *)mr->mr_port->mp_data; + mach_semaphore_put(ms); + mach_right_put(mr, MACH_PORT_TYPE_REF_RIGHTS); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +void +mach_semaphore_init(void) +{ + LIST_INIT(&mach_semaphore_list); + rw_init(&mach_semaphore_list_lock); + pool_init(&mach_semaphore_list_pool, sizeof (struct mach_semaphore), + 0, 0, 0, "mach_sem_pool", NULL, IPL_NONE); + pool_init(&mach_waiting_lwp_pool, sizeof (struct mach_waiting_lwp), + 0, 0, 0, "mach_waitp_pool", NULL, IPL_NONE); + + return; +} + +static struct mach_semaphore * +mach_semaphore_get(int value, int policy) +{ + struct mach_semaphore *ms; + + ms = (struct mach_semaphore *)pool_get(&mach_semaphore_list_pool, + M_WAITOK); + ms->ms_value = value; + ms->ms_policy = policy; + TAILQ_INIT(&ms->ms_waiting); + rw_init(&ms->ms_lock); + + rw_enter(&mach_semaphore_list_lock, RW_WRITER); + LIST_INSERT_HEAD(&mach_semaphore_list, ms, ms_list); + rw_exit(&mach_semaphore_list_lock); + + return ms; +} + +static void +mach_semaphore_put(struct mach_semaphore *ms) +{ + struct mach_waiting_lwp *mwl; + + rw_enter(&ms->ms_lock, RW_WRITER); + while ((mwl = TAILQ_FIRST(&ms->ms_waiting)) != NULL) + mach_waiting_lwp_put(mwl, ms, 0); + rw_exit(&ms->ms_lock); + rw_destroy(&ms->ms_lock); + + rw_enter(&mach_semaphore_list_lock, RW_WRITER); + LIST_REMOVE(ms, ms_list); + rw_exit(&mach_semaphore_list_lock); + + pool_put(&mach_semaphore_list_pool, ms); + + return; +} + +static struct mach_waiting_lwp * +mach_waiting_lwp_get(struct lwp *l, struct mach_semaphore *ms) +{ + struct mach_waiting_lwp *mwl; + + mwl = (struct mach_waiting_lwp *)pool_get(&mach_waiting_lwp_pool, + M_WAITOK); + mwl->mwl_l = l; + + rw_enter(&ms->ms_lock, RW_WRITER); + TAILQ_INSERT_TAIL(&ms->ms_waiting, mwl, mwl_list); + rw_exit(&ms->ms_lock); + + return mwl; +} + +static void +mach_waiting_lwp_put(struct mach_waiting_lwp *mwl, struct mach_semaphore *ms, int locked) +{ + if (!locked) + rw_enter(&ms->ms_lock, RW_WRITER); + TAILQ_REMOVE(&ms->ms_waiting, mwl, mwl_list); + if (!locked) + rw_exit(&ms->ms_lock); + pool_put(&mach_waiting_lwp_pool, mwl); + + return; +} + +/* + * Cleanup after process exit. Need improvements, there + * can be some memory leaks here. + */ +void +mach_semaphore_cleanup(struct lwp *l) +{ + struct mach_semaphore *ms; + struct mach_waiting_lwp *mwl; + + rw_enter(&mach_semaphore_list_lock, RW_READER); + LIST_FOREACH(ms, &mach_semaphore_list, ms_list) { + rw_enter(&ms->ms_lock, RW_WRITER); + TAILQ_FOREACH(mwl, &ms->ms_waiting, mwl_list) + if (mwl->mwl_l == l) { + mach_waiting_lwp_put(mwl, ms, 0); + ms->ms_value++; + if (ms->ms_value >= 0) + wakeup(TAILQ_FIRST(&ms->ms_waiting)); + } + rw_exit(&ms->ms_lock); + } + rw_exit(&mach_semaphore_list_lock); + + return; +} + +int +mach_sys_semaphore_wait_signal_trap(struct lwp *l, const struct mach_sys_semaphore_wait_signal_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_name_t) wait_name; + syscallarg(mach_port_name_t) signal_name; + } */ + struct mach_sys_semaphore_wait_trap_args cupwait; + struct mach_sys_semaphore_signal_trap_args cupsig; + int error; + + SCARG(&cupsig, signal_name) = SCARG(uap, signal_name); + if ((error = mach_sys_semaphore_signal_trap(l, &cupsig, retval)) != 0) + return error; + + SCARG(&cupwait, wait_name) = SCARG(uap, wait_name); + if ((error = mach_sys_semaphore_wait_trap(l, &cupwait, retval)) != 0) + return error; + + return 0; +} + + +int +mach_sys_semaphore_signal_thread_trap(struct lwp *l, const struct mach_sys_semaphore_signal_thread_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_name_t) signal_name; + syscallarg(mach_port_name_t) thread; + } */ + struct mach_right *mr; + struct mach_semaphore *ms; + mach_port_t mn; + struct mach_waiting_lwp *mwl; + int unblocked = 0; + + /* + * Get the semaphore + */ + mn = SCARG(uap, signal_name); + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return EINVAL; + + if (mr->mr_port->mp_datatype != MACH_MP_SEMAPHORE) + return EINVAL; + + ms = (struct mach_semaphore *)mr->mr_port->mp_data; + + /* + * Get the thread, and check that it is waiting for our semaphore + * If no thread was supplied, pick up the first one. + */ + mn = SCARG(uap, thread); + if (mn != 0) { + if ((mr = mach_right_check(mn, l, + MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return EINVAL; + + if (mr->mr_port->mp_datatype != MACH_MP_LWP) + return EINVAL; + + rw_enter(&ms->ms_lock, RW_WRITER); + TAILQ_FOREACH(mwl, &ms->ms_waiting, mwl_list) + if (mwl->mwl_l == (struct lwp *)mr->mr_port->mp_data) + break; + } else { + rw_enter(&ms->ms_lock, RW_WRITER); + mwl = TAILQ_FIRST(&ms->ms_waiting); + } + + /* + * No thread was awaiting for this semaphore, + * exit without touching the semaphore. + */ + if (mwl == NULL) { + rw_exit(&ms->ms_lock); + return 0; /* Should be KERN_NOT_WAITING */ + } + + ms->ms_value++; + if (ms->ms_value >= 0) + unblocked = 1; + rw_exit(&ms->ms_lock); + + if (unblocked != 0) + wakeup(mwl); + + return 0; +} + + +int +mach_sys_semaphore_signal_all_trap(struct lwp *l, const struct mach_sys_semaphore_signal_all_trap_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_name_t) signal_name; + } */ + struct mach_right *mr; + struct mach_semaphore *ms; + mach_port_t mn; + struct mach_waiting_lwp *mwl; + int unblocked = 0; + + /* + * Get the semaphore + */ + mn = SCARG(uap, signal_name); + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return EINVAL; + + if (mr->mr_port->mp_datatype != MACH_MP_SEMAPHORE) + return EINVAL; + + ms = (struct mach_semaphore *)mr->mr_port->mp_data; + + rw_enter(&ms->ms_lock, RW_WRITER); + ms->ms_value++; + if (ms->ms_value >= 0) + unblocked = 1; + + /* + * Wakeup all threads sleeping on it. + */ + if (unblocked != 0) + TAILQ_FOREACH(mwl, &ms->ms_waiting, mwl_list) + wakeup(mwl); + + rw_exit(&ms->ms_lock); + + return 0; +} + + diff --git a/sys/compat/mach/mach_semaphore.h b/sys/compat/mach/mach_semaphore.h new file mode 100644 index 0000000..337ca3e --- /dev/null +++ b/sys/compat/mach/mach_semaphore.h @@ -0,0 +1,91 @@ +/* $NetBSD: mach_semaphore.h,v 1.7 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_SEMAPHORE_H_ +#define _MACH_SEMAPHORE_H_ + +#include +#include + +extern int mach_semaphore_cold; + +struct mach_waiting_lwp { + TAILQ_ENTRY(mach_waiting_lwp) mwl_list; + struct lwp *mwl_l; +}; + +struct mach_semaphore { + int ms_value; + int ms_policy; + LIST_ENTRY(mach_semaphore) ms_list; + TAILQ_HEAD(ms_waiting, mach_waiting_lwp) ms_waiting; + krwlock_t ms_lock; +}; + +/* semaphore_create */ + +#define MACH_SYNC_POLICY_FIFO 0 +#define MACH_SYNC_POLICY_FIXED_PRIORITY 1 + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + int req_policy; + int req_value; +} mach_semaphore_create_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_sem; + mach_msg_trailer_t rep_trailer; +} mach_semaphore_create_reply_t; + +/* semaphore_destroy */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_sem; +} mach_semaphore_destroy_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_semaphore_destroy_reply_t; + +void mach_semaphore_init(void); +void mach_semaphore_cleanup(struct lwp *); + +#endif /* _MACH_SEMAPHORE_H_ */ + diff --git a/sys/compat/mach/mach_services.c b/sys/compat/mach/mach_services.c new file mode 100644 index 0000000..bf10124 --- /dev/null +++ b/sys/compat/mach/mach_services.c @@ -0,0 +1,362 @@ +/* $NetBSD: mach_services.c,v 1.19 2009/01/13 22:33:10 pooka Exp $ */ + +/* + * Mach services table. + * + * DO NOT EDIT -- this file is automatically generated. + * created from NetBSD: mach_services.master,v 1.13 2005/12/11 12:20:20 christos Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_services.c,v 1.19 2009/01/13 22:33:10 pooka Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mach_service mach_services_table[] = { + {64, NULL, "obsolete notify_first", 0, 0}, + {65, NULL, "notify_port_deleted", 0, 0}, + {66, NULL, "obsolete notify_msg_accepted", 0, 0}, + {67, NULL, "obsolete notify_ownership_rights", 0, 0}, + {68, NULL, "obsolete notify_receive_rights", 0, 0}, + {69, NULL, "notify_port_destroyed", 0, 0}, + {70, NULL, "notify_port_no_senders", 0, 0}, + {71, NULL, "notify_port_send_once", 0, 0}, + {72, NULL, "notify_port_dead_name", 0, 0}, + {200, mach_host_info, "host_info", sizeof(mach_host_info_request_t), sizeof(mach_host_info_reply_t)}, + {201, NULL, "unimpl. host_kernel_version", 0, 0}, + {202, mach_host_page_size, "host_page_size", sizeof(mach_host_page_size_request_t), sizeof(mach_host_page_size_reply_t)}, + {203, NULL, "unimpl. memory_object_memory_entry", 0, 0}, + {204, NULL, "unimpl. host_processor_info", 0, 0}, + {205, mach_host_get_io_master, "host_get_io_master", sizeof(mach_host_get_io_master_request_t), sizeof(mach_host_get_io_master_reply_t)}, + {206, mach_host_get_clock_service, "host_get_clock_service", sizeof(mach_host_get_clock_service_request_t), sizeof(mach_host_get_clock_service_reply_t)}, + {207, NULL, "unimpl. kmod_get_info", 0, 0}, + {208, NULL, "unimpl. host_zone_info", 0, 0}, + {209, NULL, "unimpl. host_virtual_physical_table_info", 0, 0}, + {210, NULL, "unimpl. host_ipc_hash_info", 0, 0}, + {211, NULL, "unimpl. enable_bluebox", 0, 0}, + {212, NULL, "unimpl. disable_bluebox", 0, 0}, + {213, mach_processor_set_default, "processor_set_default", sizeof(mach_processor_set_default_request_t), sizeof(mach_processor_set_default_reply_t)}, + {214, NULL, "unimpl. processor_set_create", 0, 0}, + {215, NULL, "unimpl. memory_object_memory_entry_64", 0, 0}, + {216, NULL, "unimpl. host_statistics", 0, 0}, + {400, NULL, "unimpl. host_get_boot_info", 0, 0}, + {401, NULL, "unimpl. host_reboot", 0, 0}, + {402, NULL, "unimpl. host_priv_statistics", 0, 0}, + {403, NULL, "unimpl. boostrap_register", 0, 0}, + {404, mach_bootstrap_look_up, "bootstrap_look_up", sizeof(mach_bootstrap_look_up_request_t), sizeof(mach_bootstrap_look_up_reply_t)}, + {405, NULL, "unimpl. thread_wire", 0, 0}, + {406, NULL, "unimpl. vm_allocate_cpm", 0, 0}, + {407, NULL, "unimpl. host_processors", 0, 0}, + {408, NULL, "unimpl. host_get_clock_control", 0, 0}, + {409, NULL, "unimpl. kmod_create", 0, 0}, + {410, NULL, "unimpl. kmod_destroy", 0, 0}, + {411, NULL, "unimpl. kmod_control", 0, 0}, + {412, NULL, "unimpl. host_get_special_port", 0, 0}, + {413, NULL, "unimpl. host_set_special_port", 0, 0}, + {414, NULL, "unimpl. host_set_exception_ports", 0, 0}, + {415, NULL, "unimpl. host_get_exception_ports", 0, 0}, + {416, NULL, "unimpl. host_swap_exception_ports", 0, 0}, + {417, NULL, "unimpl. host_load_symbol_table", 0, 0}, + {418, NULL, "unimpl. task_swappable", 0, 0}, + {419, NULL, "unimpl. host_processor_sets", 0, 0}, + {420, mach_host_processor_set_priv, "host_processor_set_priv", sizeof(mach_host_processor_set_priv_request_t), sizeof(mach_host_processor_set_priv_reply_t)}, + {421, NULL, "unimpl. set_dp_control_port", 0, 0}, + {422, NULL, "unimpl. get_dp_control_port", 0, 0}, + {423, NULL, "unimpl. host_set_UNDServer", 0, 0}, + {424, NULL, "unimpl. host_get_UNDServer", 0, 0}, + {600, NULL, "unimpl. host_security_create_task_token", 0, 0}, + {601, NULL, "unimpl. host_security_set_task_token", 0, 0}, + {1000, mach_clock_get_time, "clock_get_time", sizeof(mach_clock_get_time_request_t), sizeof(mach_clock_get_time_reply_t)}, + {1001, NULL, "unimpl. clock_get_attributes", 0, 0}, + {1002, NULL, "unimpl. clock_alarm", 0, 0}, + {1200, NULL, "unimpl. clock_set_time", 0, 0}, + {1201, NULL, "unimpl. clock_set_attributes", 0, 0}, + {2000, NULL, "unimpl. memory_object_get_attributes", 0, 0}, + {2001, NULL, "unimpl. memory_object_change_attributes", 0, 0}, + {2002, NULL, "unimpl. memory_object_synchronize_completed", 0, 0}, + {2003, NULL, "unimpl. memory_object_lock_request", 0, 0}, + {2004, NULL, "unimpl. memory_object_destroy", 0, 0}, + {2005, NULL, "unimpl. memory_object_upl_request", 0, 0}, + {2006, NULL, "unimpl. memory_object_super_upl_request", 0, 0}, + {2007, NULL, "unimpl. memory_object_page_op", 0, 0}, + {2008, NULL, "unimpl. memory_object_recover_named", 0, 0}, + {2009, NULL, "unimpl. memory_object_release_name", 0, 0}, + {2050, NULL, "unimpl. upl_abort", 0, 0}, + {2051, NULL, "unimpl. upl_abort_range", 0, 0}, + {2052, NULL, "unimpl. upl_commit", 0, 0}, + {2053, NULL, "unimpl. upl_commit_range", 0, 0}, + {2200, NULL, "unimpl. memory_object_init", 0, 0}, + {2201, NULL, "unimpl. memory_object_terminate", 0, 0}, + {2202, NULL, "unimpl. memory_object_data_request", 0, 0}, + {2203, NULL, "unimpl. memory_object_data_return", 0, 0}, + {2204, NULL, "unimpl. memory_object_data_initialize", 0, 0}, + {2205, NULL, "unimpl. memory_object_data_unlock", 0, 0}, + {2206, NULL, "unimpl. memory_object_synchronize", 0, 0}, + {2207, NULL, "unimpl. memory_object_unmap", 0, 0}, + {2250, NULL, "unimpl. memory_object_create", 0, 0}, + {2275, NULL, "unimpl. default_pager_object_create", 0, 0}, + {2276, NULL, "unimpl. default_pager_info", 0, 0}, + {2277, NULL, "unimpl. default_pager_objects", 0, 0}, + {2278, NULL, "unimpl. default_pager_object_pages", 0, 0}, + {2279, NULL, "unimpl. default_pager_backing_store_create", 0, 0}, + {2280, NULL, "unimpl. default_pager_backing_store_delete", 0, 0}, + {2281, NULL, "unimpl. default_pager_add_segment", 0, 0}, + {2282, NULL, "unimpl. default_pager_backing_store_info", 0, 0}, + {2283, NULL, "unimpl. default_pager_add_file", 0, 0}, + {2284, NULL, "unimpl. default_pager_triggers", 0, 0}, + {2295, NULL, "unimpl. default_pager_space_alert", 0, 0}, + {2401, NULL, "exception_raise", 0, 0}, + {2402, NULL, "exception_raise_state", 0, 0}, + {2403, NULL, "exception_raise_state_identity", 0, 0}, + {2450, NULL, "unimpl. samples", 0, 0}, + {2451, NULL, "unimpl. notices", 0, 0}, + {2501, mach_exception_raise, "exception_raise", sizeof(mach_exception_raise_request_t), sizeof(mach_exception_raise_reply_t)}, + {2502, mach_exception_raise_state, "exception_raise_state", sizeof(mach_exception_raise_state_request_t), sizeof(mach_exception_raise_state_reply_t)}, + {2503, mach_exception_raise_state_identity, "exception_raise_state_identity", sizeof(mach_exception_raise_state_identity_request_t), sizeof(mach_exception_raise_state_identity_reply_t)}, + {2800, mach_io_object_get_class, "io_object_get_class", sizeof(mach_io_object_get_class_request_t), sizeof(mach_io_object_get_class_reply_t)}, + {2801, mach_io_object_conforms_to, "io_object_conforms_to", sizeof(mach_io_object_conforms_to_request_t), sizeof(mach_io_object_conforms_to_reply_t)}, + {2802, mach_io_iterator_next, "io_iterator_next", sizeof(mach_io_iterator_next_request_t), sizeof(mach_io_iterator_next_reply_t)}, + {2803, mach_io_iterator_reset, "io_iterator_reset", sizeof(mach_io_iterator_reset_request_t), sizeof(mach_io_iterator_reset_reply_t)}, + {2804, mach_io_service_get_matching_services, "io_service_get_matching_services", sizeof(mach_io_service_get_matching_services_request_t), sizeof(mach_io_service_get_matching_services_reply_t)}, + {2805, mach_io_registry_entry_get_property, "io_registry_entry_get_property", sizeof(mach_io_registry_entry_get_property_request_t), sizeof(mach_io_registry_entry_get_property_reply_t)}, + {2806, NULL, "unimpl. io_registry_create_iterator", 0, 0}, + {2807, NULL, "unimpl. io_registry_iterator_enter_entry", 0, 0}, + {2808, NULL, "unimpl. io_registry_iterator_exit_entry", 0, 0}, + {2809, mach_io_registry_entry_from_path, "io_registry_entry_from_path", sizeof(mach_io_registry_entry_from_path_request_t), sizeof(mach_io_registry_entry_from_path_reply_t)}, + {2810, NULL, "unimpl. io_registry_entry_get_name", 0, 0}, + {2811, mach_io_registry_entry_get_properties, "io_registry_entry_get_properties", sizeof(mach_io_registry_entry_get_properties_request_t), sizeof(mach_io_registry_entry_get_properties_reply_t)}, + {2812, NULL, "unimpl. io_registry_entry_get_property_bytes", 0, 0}, + {2813, mach_io_registry_entry_get_child_iterator, "io_registry_entry_get_child_iterator", sizeof(mach_io_registry_entry_get_child_iterator_request_t), sizeof(mach_io_registry_entry_get_child_iterator_reply_t)}, + {2814, mach_io_registry_entry_get_parent_iterator, "io_registry_entry_get_parent_iterator", sizeof(mach_io_registry_entry_get_parent_iterator_request_t), sizeof(mach_io_registry_entry_get_parent_iterator_reply_t)}, + {2815, mach_io_service_open, "io_service_open", sizeof(mach_io_service_open_request_t), sizeof(mach_io_service_open_reply_t)}, + {2816, mach_io_service_close, "io_service_close", sizeof(mach_io_service_close_request_t), sizeof(mach_io_service_close_reply_t)}, + {2817, mach_io_connect_get_service, "io_connect_get_service", sizeof(mach_io_connect_get_service_request_t), sizeof(mach_io_connect_get_service_reply_t)}, + {2818, mach_io_connect_set_notification_port, "io_connect_set_notification_port", sizeof(mach_io_connect_set_notification_port_request_t), sizeof(mach_io_connect_set_notification_port_reply_t)}, + {2819, mach_io_connect_map_memory, "io_connect_map_memory", sizeof(mach_io_connect_map_memory_request_t), sizeof(mach_io_connect_map_memory_reply_t)}, + {2820, mach_io_connect_add_client, "io_connect_add_client", sizeof(mach_io_connect_add_client_request_t), sizeof(mach_io_connect_add_client_reply_t)}, + {2821, mach_io_connect_set_properties, "io_connect_set_properties", sizeof(mach_io_connect_set_properties_request_t), sizeof(mach_io_connect_set_properties_reply_t)}, + {2822, mach_io_connect_method_scalari_scalaro, "io_connect_method_scalari_scalaro", sizeof(mach_io_connect_method_scalari_scalaro_request_t), sizeof(mach_io_connect_method_scalari_scalaro_reply_t)}, + {2823, mach_io_connect_method_scalari_structo, "io_connect_method_scalari_structo", sizeof(mach_io_connect_method_scalari_structo_request_t), sizeof(mach_io_connect_method_scalari_structo_reply_t)}, + {2824, mach_io_connect_method_scalari_structi, "io_connect_method_scalari_structi", sizeof(mach_io_connect_method_scalari_structi_request_t), sizeof(mach_io_connect_method_scalari_structi_reply_t)}, + {2825, mach_io_connect_method_structi_structo, "io_connect_method_structi_structo", sizeof(mach_io_connect_method_structi_structo_request_t), sizeof(mach_io_connect_method_structi_structo_reply_t)}, + {2826, mach_io_registry_entry_get_path, "io_registry_entry_get_path", sizeof(mach_io_registry_entry_get_path_request_t), sizeof(mach_io_registry_entry_get_path_reply_t)}, + {2827, mach_io_registry_get_root_entry, "io_registry_get_root_entry", sizeof(mach_io_registry_get_root_entry_request_t), sizeof(mach_io_registry_get_root_entry_reply_t)}, + {2828, NULL, "unimpl. io_registry_entry_set_properties", 0, 0}, + {2829, NULL, "unimpl. io_registry_entry_in_plane", 0, 0}, + {2830, NULL, "unimpl. io_object_get_retain_count", 0, 0}, + {2831, NULL, "unimpl. io_service_get_busy_state", 0, 0}, + {2832, NULL, "unimpl. io_service_wait_quiet", 0, 0}, + {2833, mach_io_registry_entry_create_iterator, "io_registry_entry_create_iterator", sizeof(mach_io_registry_entry_create_iterator_request_t), sizeof(mach_io_registry_entry_create_iterator_reply_t)}, + {2834, NULL, "unimpl. io_iterator_is_valid", 0, 0}, + {2835, NULL, "unimpl. io_make_matching", 0, 0}, + {2836, NULL, "unimpl. io_catalog_send_data", 0, 0}, + {2837, NULL, "unimpl. io_catalog_terminate", 0, 0}, + {2838, NULL, "unimpl. io_catalog_get_data", 0, 0}, + {2839, NULL, "unimpl. io_catalog_get_gen_count", 0, 0}, + {2840, NULL, "unimpl. io_catalog_module_loaded", 0, 0}, + {2841, NULL, "unimpl. io_catalog_reset", 0, 0}, + {2842, NULL, "unimpl. io_service_request_probe", 0, 0}, + {2843, mach_io_registry_entry_get_name_in_plane, "io_registry_entry_get_name_in_plane", sizeof(mach_io_registry_entry_get_name_in_plane_request_t), sizeof(mach_io_registry_entry_get_name_in_plane_reply_t)}, + {2844, NULL, "unimpl. io_service_match_property_table", 0, 0}, + {2845, NULL, "unimpl. io_async_method_scalari_scalaro", 0, 0}, + {2846, NULL, "unimpl. io_async_method_scalari_structo", 0, 0}, + {2847, NULL, "unimpl. io_async_method_scalari_structi", 0, 0}, + {2848, NULL, "unimpl. io_async_method_structi_structo", 0, 0}, + {2849, NULL, "unimpl. io_service_add_notification", 0, 0}, + {2850, mach_io_service_add_interest_notification, "io_service_add_interest_notification", sizeof(mach_io_service_add_interest_notification_request_t), sizeof(mach_io_service_add_interest_notification_reply_t)}, + {2851, NULL, "unimpl. io_service_acknowledge_notification", 0, 0}, + {2852, NULL, "unimpl. io_connect_get_notification_semaphore", 0, 0}, + {2853, NULL, "unimpl. io_connect_unmap_memory", 0, 0}, + {2854, mach_io_registry_entry_get_location_in_plane, "io_registry_entry_get_location_in_plane", sizeof(mach_io_registry_entry_get_location_in_plane_request_t), sizeof(mach_io_registry_entry_get_location_in_plane_reply_t)}, + {2855, NULL, "unimpl. io_registry_entry_get_property_recursively", 0, 0}, + {3000, NULL, "unimpl. processor_start", 0, 0}, + {3001, NULL, "unimpl. processor_exit", 0, 0}, + {3002, NULL, "unimpl. processor_info", 0, 0}, + {3003, NULL, "unimpl. processor_control", 0, 0}, + {3004, NULL, "unimpl. processor_assign", 0, 0}, + {3005, NULL, "unimpl. processor_get_assignment", 0, 0}, + {3200, NULL, "unimpl. port_names", 0, 0}, + {3201, mach_port_type, "port_type", sizeof(mach_port_type_request_t), sizeof(mach_port_type_reply_t)}, + {3202, NULL, "unimpl. port_rename", 0, 0}, + {3203, NULL, "unimpl. port_allocate_name", 0, 0}, + {3204, mach_port_allocate, "port_allocate", sizeof(mach_port_allocate_request_t), sizeof(mach_port_allocate_reply_t)}, + {3205, mach_port_destroy, "port_destroy", sizeof(mach_port_destroy_request_t), sizeof(mach_port_destroy_reply_t)}, + {3206, mach_port_deallocate, "port_deallocate", sizeof(mach_port_deallocate_request_t), sizeof(mach_port_deallocate_reply_t)}, + {3207, mach_port_get_refs, "port_get_refs", sizeof(mach_port_get_refs_request_t), sizeof(mach_port_get_refs_reply_t)}, + {3208, mach_port_mod_refs, "port_mod_refs", sizeof(mach_port_mod_refs_request_t), sizeof(mach_port_mod_refs_reply_t)}, + {3210, NULL, "unimpl. port_set_mscount", 0, 0}, + {3211, NULL, "unimpl. port_get_set_status", 0, 0}, + {3212, mach_port_move_member, "port_move_member", sizeof(mach_port_move_member_request_t), sizeof(mach_port_move_member_reply_t)}, + {3213, mach_port_request_notification, "port_request_notification", sizeof(mach_port_request_notification_request_t), sizeof(mach_port_request_notification_reply_t)}, + {3214, mach_port_insert_right, "port_insert_right", sizeof(mach_port_insert_right_request_t), sizeof(mach_port_insert_right_reply_t)}, + {3215, NULL, "unimpl. port_extract_right", 0, 0}, + {3216, NULL, "unimpl. port_set_seqno", 0, 0}, + {3217, mach_port_get_attributes, "port_get_attributes", sizeof(mach_port_get_attributes_request_t), sizeof(mach_port_get_attributes_reply_t)}, + {3218, mach_port_set_attributes, "port_set_attributes", sizeof(mach_port_set_attributes_request_t), sizeof(mach_port_set_attributes_reply_t)}, + {3219, NULL, "unimpl. port_allocate_qos", 0, 0}, + {3220, NULL, "unimpl. port_allocate_full", 0, 0}, + {3221, NULL, "unimpl. task_set_port_space", 0, 0}, + {3222, NULL, "unimpl. port_get_srights", 0, 0}, + {3223, NULL, "unimpl. port_space_info", 0, 0}, + {3224, NULL, "unimpl. port_dnrequest_info", 0, 0}, + {3225, NULL, "unimpl. port_kernel_object", 0, 0}, + {3226, mach_port_insert_member, "port_insert_member", sizeof(mach_port_insert_member_request_t), sizeof(mach_port_insert_member_reply_t)}, + {3227, NULL, "unimpl. port_extract_member", 0, 0}, + {3400, NULL, "unimpl. task_create", 0, 0}, + {3401, mach_task_terminate, "task_terminate", sizeof(mach_task_terminate_request_t), sizeof(mach_task_terminate_reply_t)}, + {3402, mach_task_threads, "task_threads", sizeof(mach_task_threads_request_t), sizeof(mach_task_threads_reply_t)}, + {3403, NULL, "unimpl. ports_register", 0, 0}, + {3404, mach_ports_lookup, "ports_lookup", sizeof(mach_ports_lookup_request_t), sizeof(mach_ports_lookup_reply_t)}, + {3405, mach_task_info, "task_info", sizeof(mach_task_info_request_t), sizeof(mach_task_info_reply_t)}, + {3406, NULL, "unimpl. task_set_info", 0, 0}, + {3407, mach_task_suspend, "task_suspend", sizeof(mach_task_suspend_request_t), sizeof(mach_task_suspend_reply_t)}, + {3408, mach_task_resume, "task_resume", sizeof(mach_task_resume_request_t), sizeof(mach_task_resume_reply_t)}, + {3409, mach_task_get_special_port, "task_get_special_port", sizeof(mach_task_get_special_port_request_t), sizeof(mach_task_get_special_port_reply_t)}, + {3410, mach_task_set_special_port, "task_set_special_port", sizeof(mach_task_set_special_port_request_t), sizeof(mach_task_set_special_port_reply_t)}, + {3411, NULL, "unimpl. thread_create", 0, 0}, + {3412, mach_thread_create_running, "thread_create_running", sizeof(mach_thread_create_running_request_t), sizeof(mach_thread_create_running_reply_t)}, + {3413, mach_task_set_exception_ports, "task_set_exception_ports", sizeof(mach_task_set_exception_ports_request_t), sizeof(mach_task_set_exception_ports_reply_t)}, + {3414, mach_task_get_exception_ports, "task_get_exception_ports", sizeof(mach_task_get_exception_ports_request_t), sizeof(mach_task_get_exception_ports_reply_t)}, + {3415, NULL, "unimpl. task_swap_exception_ports", 0, 0}, + {3416, NULL, "unimpl. lock_set_create", 0, 0}, + {3417, NULL, "unimpl. lock_set_destroy", 0, 0}, + {3418, mach_semaphore_create, "semaphore_create", sizeof(mach_semaphore_create_request_t), sizeof(mach_semaphore_create_reply_t)}, + {3419, mach_semaphore_destroy, "semaphore_destroy", sizeof(mach_semaphore_destroy_request_t), sizeof(mach_semaphore_destroy_reply_t)}, + {3420, NULL, "unimpl. task_policy_set", 0, 0}, + {3421, NULL, "unimpl. task_policy_get", 0, 0}, + {3422, NULL, "unimpl. task_sample", 0, 0}, + {3423, NULL, "unimpl. task_policy", 0, 0}, + {3424, NULL, "unimpl. task_set_emulation", 0, 0}, + {3425, NULL, "unimpl. task_get_emulation_vector", 0, 0}, + {3426, NULL, "unimpl. task_set_emulation_vector", 0, 0}, + {3427, NULL, "unimpl. task_set_ras_pc", 0, 0}, + {3428, NULL, "unimpl. kernel_task_create", 0, 0}, + {3429, NULL, "unimpl. task_assign", 0, 0}, + {3430, NULL, "unimpl. task_assign_default", 0, 0}, + {3431, NULL, "unimpl. task_get_assignment", 0, 0}, + {3432, NULL, "unimpl. task_set_policy", 0, 0}, + {3600, NULL, "unimpl. thread_terminate", 0, 0}, + {3601, NULL, "unimpl. act_get_state", 0, 0}, + {3602, NULL, "unimpl. act_set_state", 0, 0}, + {3603, mach_thread_get_state, "thread_get_state", sizeof(mach_thread_get_state_request_t), sizeof(mach_thread_get_state_reply_t)}, + {3604, mach_thread_set_state, "thread_set_state", sizeof(mach_thread_set_state_request_t), sizeof(mach_thread_set_state_reply_t)}, + {3605, mach_thread_suspend, "thread_suspend", sizeof(mach_thread_suspend_request_t), sizeof(mach_thread_suspend_reply_t)}, + {3606, mach_thread_resume, "thread_resume", sizeof(mach_thread_resume_request_t), sizeof(mach_thread_resume_reply_t)}, + {3607, mach_thread_abort, "thread_abort", sizeof(mach_thread_abort_request_t), sizeof(mach_thread_abort_reply_t)}, + {3608, NULL, "unimpl. thread_abort_safely", 0, 0}, + {3609, NULL, "unimpl. thread_depress_abort", 0, 0}, + {3610, NULL, "unimpl. thread_get_special_port", 0, 0}, + {3611, NULL, "unimpl. thread_set_special_port", 0, 0}, + {3612, mach_thread_info, "thread_info", sizeof(mach_thread_info_request_t), sizeof(mach_thread_info_reply_t)}, + {3613, NULL, "unimpl. thread_set_exception_ports", 0, 0}, + {3614, NULL, "unimpl. thread_get_exception_ports", 0, 0}, + {3615, NULL, "unimpl. thread_swap_exception_ports", 0, 0}, + {3616, mach_thread_policy, "thread_policy", sizeof(mach_thread_policy_request_t), sizeof(mach_thread_policy_reply_t)}, + {3617, NULL, "unimpl. thread_policy_set", 0, 0}, + {3618, NULL, "unimpl. thread_policy_get", 0, 0}, + {3619, NULL, "unimpl. thread_sample", 0, 0}, + {3620, NULL, "unimpl. etap_trace_thread", 0, 0}, + {3621, NULL, "unimpl. thread_assign", 0, 0}, + {3622, NULL, "unimpl. thread_assign_default", 0, 0}, + {3623, NULL, "unimpl. thread_get_assignment", 0, 0}, + {3624, mach_thread_set_policy, "thread_set_policy", sizeof(mach_thread_set_policy_request_t), sizeof(mach_thread_set_policy_reply_t)}, + {3800, mach_vm_region, "vm_region", sizeof(mach_vm_region_request_t), sizeof(mach_vm_region_reply_t)}, + {3801, mach_vm_allocate, "vm_allocate", sizeof(mach_vm_allocate_request_t), sizeof(mach_vm_allocate_reply_t)}, + {3802, mach_vm_deallocate, "vm_deallocate", sizeof(mach_vm_deallocate_request_t), sizeof(mach_vm_deallocate_reply_t)}, + {3803, mach_vm_protect, "vm_protect", sizeof(mach_vm_protect_request_t), sizeof(mach_vm_protect_reply_t)}, + {3804, mach_vm_inherit, "vm_inherit", sizeof(mach_vm_inherit_request_t), sizeof(mach_vm_inherit_reply_t)}, + {3805, mach_vm_read, "vm_read", sizeof(mach_vm_read_request_t), sizeof(mach_vm_read_reply_t)}, + {3806, NULL, "unimpl. vm_read_list", 0, 0}, + {3807, mach_vm_write, "vm_write", sizeof(mach_vm_write_request_t), sizeof(mach_vm_write_reply_t)}, + {3808, mach_vm_copy, "vm_copy", sizeof(mach_vm_copy_request_t), sizeof(mach_vm_copy_reply_t)}, + {3809, NULL, "unimpl. vm_read_overwrite", 0, 0}, + {3810, mach_vm_msync, "vm_msync", sizeof(mach_vm_msync_request_t), sizeof(mach_vm_msync_reply_t)}, + {3811, NULL, "unimpl. vm_behavior_set", 0, 0}, + {3812, mach_vm_map, "vm_map", sizeof(mach_vm_map_request_t), sizeof(mach_vm_map_reply_t)}, + {3813, mach_vm_machine_attribute, "vm_machine_attribute", sizeof(mach_vm_machine_attribute_request_t), sizeof(mach_vm_machine_attribute_reply_t)}, + {3814, NULL, "unimpl. vm_remap", 0, 0}, + {3815, NULL, "unimpl. task_wire", 0, 0}, + {3816, NULL, "unimpl. make_memory_entry", 0, 0}, + {3817, NULL, "unimpl. vm_map_page_query", 0, 0}, + {3818, NULL, "unimpl. vm_region_info", 0, 0}, + {3819, NULL, "unimpl. vm_mapped_pages_info", 0, 0}, + {3820, NULL, "unimpl. vm_region_object_create", 0, 0}, + {3821, NULL, "unimpl. vm_region_recurse", 0, 0}, + {3822, NULL, "unimpl. vm_region_recurse_64", 0, 0}, + {3823, NULL, "unimpl. vm_region_info_64", 0, 0}, + {3824, mach_vm_region_64, "vm_region_64", sizeof(mach_vm_region_64_request_t), sizeof(mach_vm_region_64_reply_t)}, + {3825, mach_make_memory_entry_64, "make_memory_entry_64", sizeof(mach_make_memory_entry_64_request_t), sizeof(mach_make_memory_entry_64_reply_t)}, + {3826, NULL, "unimpl. vm_map_64", 0, 0}, + {3827, NULL, "unimpl. vm_map_get_upl", 0, 0}, + {3828, NULL, "unimpl. vm_upl_map", 0, 0}, + {3829, NULL, "unimpl. vm_upl_unmap", 0, 0}, + {4000, NULL, "unimpl. processor_set_statistics", 0, 0}, + {4001, NULL, "unimpl. processor_set_destroy", 0, 0}, + {4002, NULL, "unimpl. processor_set_max_priority", 0, 0}, + {4003, NULL, "unimpl. processor_set_policy_enable", 0, 0}, + {4004, NULL, "unimpl. processor_set_policy_disable", 0, 0}, + {4005, NULL, "unimpl. processor_set_tasks", 0, 0}, + {4006, NULL, "unimpl. processor_set_threads", 0, 0}, + {4007, NULL, "unimpl. processor_set_policy_control", 0, 0}, + {4008, NULL, "unimpl. processor_set_stack_usage", 0, 0}, + {4009, NULL, "unimpl. processor_set_info", 0, 0}, + {5000, NULL, "unimpl. ledger_create", 0, 0}, + {5001, NULL, "unimpl. ledger_terminate", 0, 0}, + {5002, NULL, "unimpl. ledger_transfer", 0, 0}, + {5003, NULL, "unimpl. ledger_read", 0, 0}, + {6000, NULL, "unimpl. und_execute_rpc", 0, 0}, + {6001, NULL, "unimpl. und_display_notice_from_bundle_rpc", 0, 0}, + {6002, NULL, "unimpl. und_display_alert_from_bundle_rpc", 0, 0}, + {6003, NULL, "unimpl. und_display_custom_from_bundle_rpc", 0, 0}, + {6004, NULL, "unimpl. und_display_custom_from_dictionary_rpc", 0, 0}, + {6005, NULL, "unimpl. und_cancel_notification_rpc", 0, 0}, + {6006, NULL, "unimpl. und_display_notice_simple_rpc", 0, 0}, + {6007, NULL, "unimpl. und_display_alert_simple_rpc", 0, 0}, + {6200, NULL, "unimpl. und_alert_completed_with_result_rpc", 0, 0}, + {6201, NULL, "unimpl. und_notification_created_rpc(", 0, 0}, + {555001, NULL, "unimpl. task_set_child_node", 0, 0}, + {555002, NULL, "unimpl. norma_node_self", 0, 0}, + {555005, NULL, "unimpl. norma_task_clone", 0, 0}, + {555006, NULL, "unimpl. norma_task_create", 0, 0}, + {555007, NULL, "unimpl. norma_get_special_port", 0, 0}, + {555008, NULL, "unimpl. norma_set_special_port", 0, 0}, + {555009, NULL, "unimpl. norma_task_teleport", 0, 0}, + {555012, NULL, "unimpl. norma_port_location_hint", 0, 0}, + {617000, NULL, "unimpl. lock_acquire", 0, 0}, + {617001, NULL, "unimpl. lock_release", 0, 0}, + {617002, NULL, "unimpl. lock_try", 0, 0}, + {617003, NULL, "unimpl. lock_make_stable", 0, 0}, + {617004, NULL, "unimpl. lock_handoff", 0, 0}, + {617005, NULL, "unimpl. lock_handoff_accept", 0, 0}, + {617005, NULL, "unimpl. lock_set_create", 0, 0}, + {617006, NULL, "unimpl. lock_set_destroy", 0, 0}, + {617007, NULL, "unimpl. lock_acquire", 0, 0}, + {617008, NULL, "unimpl. lock_release", 0, 0}, + {617009, NULL, "unimpl. lock_try", 0, 0}, + {617010, NULL, "unimpl. lock_make_stable", 0, 0}, + {617011, NULL, "unimpl. lock_handoff", 0, 0}, + {617012, NULL, "unimpl. lock_handoff_accept", 0, 0}, + {617200, NULL, "unimpl. semaphore_signal", 0, 0}, + {617201, NULL, "unimpl. semaphore_signal_all", 0, 0}, + {617202, NULL, "unimpl. semaphore_wait", 0, 0}, + {617203, NULL, "unimpl. semaphore_signal_thread", 0, 0}, + {617204, NULL, "unimpl. semaphore_timedwait", 0, 0}, + {617205, NULL, "unimpl. semaphore_wait_signal", 0, 0}, + {617206, NULL, "unimpl. semaphore_timedwait_signal", 0, 0}, + {0, NULL, NULL, 0, 0} +}; diff --git a/sys/compat/mach/mach_services.h b/sys/compat/mach/mach_services.h new file mode 100644 index 0000000..4894a3a --- /dev/null +++ b/sys/compat/mach/mach_services.h @@ -0,0 +1,99 @@ +/* $NetBSD: mach_services.h,v 1.19 2009/01/13 22:33:10 pooka Exp $ */ + +/* + * Mach services prototypes. + * + * DO NOT EDIT -- this file is automatically generated. + * created from NetBSD: mach_services.master,v 1.13 2005/12/11 12:20:20 christos Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_services.h,v 1.19 2009/01/13 22:33:10 pooka Exp $"); + +#include +#include + +int mach_host_info(struct mach_trap_args *); +int mach_host_page_size(struct mach_trap_args *); +int mach_host_get_io_master(struct mach_trap_args *); +int mach_host_get_clock_service(struct mach_trap_args *); +int mach_processor_set_default(struct mach_trap_args *); +int mach_bootstrap_look_up(struct mach_trap_args *); +int mach_host_processor_set_priv(struct mach_trap_args *); +int mach_clock_get_time(struct mach_trap_args *); +int mach_exception_raise(struct mach_trap_args *); +int mach_exception_raise_state(struct mach_trap_args *); +int mach_exception_raise_state_identity(struct mach_trap_args *); +int mach_io_object_get_class(struct mach_trap_args *); +int mach_io_object_conforms_to(struct mach_trap_args *); +int mach_io_iterator_next(struct mach_trap_args *); +int mach_io_iterator_reset(struct mach_trap_args *); +int mach_io_service_get_matching_services(struct mach_trap_args *); +int mach_io_registry_entry_get_property(struct mach_trap_args *); +int mach_io_registry_entry_from_path(struct mach_trap_args *); +int mach_io_registry_entry_get_properties(struct mach_trap_args *); +int mach_io_registry_entry_get_child_iterator(struct mach_trap_args *); +int mach_io_registry_entry_get_parent_iterator(struct mach_trap_args *); +int mach_io_service_open(struct mach_trap_args *); +int mach_io_service_close(struct mach_trap_args *); +int mach_io_connect_get_service(struct mach_trap_args *); +int mach_io_connect_set_notification_port(struct mach_trap_args *); +int mach_io_connect_map_memory(struct mach_trap_args *); +int mach_io_connect_add_client(struct mach_trap_args *); +int mach_io_connect_set_properties(struct mach_trap_args *); +int mach_io_connect_method_scalari_scalaro(struct mach_trap_args *); +int mach_io_connect_method_scalari_structo(struct mach_trap_args *); +int mach_io_connect_method_scalari_structi(struct mach_trap_args *); +int mach_io_connect_method_structi_structo(struct mach_trap_args *); +int mach_io_registry_entry_get_path(struct mach_trap_args *); +int mach_io_registry_get_root_entry(struct mach_trap_args *); +int mach_io_registry_entry_create_iterator(struct mach_trap_args *); +int mach_io_registry_entry_get_name_in_plane(struct mach_trap_args *); +int mach_io_service_add_interest_notification(struct mach_trap_args *); +int mach_io_registry_entry_get_location_in_plane(struct mach_trap_args *); +int mach_port_type(struct mach_trap_args *); +int mach_port_allocate(struct mach_trap_args *); +int mach_port_destroy(struct mach_trap_args *); +int mach_port_deallocate(struct mach_trap_args *); +int mach_port_get_refs(struct mach_trap_args *); +int mach_port_mod_refs(struct mach_trap_args *); +int mach_port_move_member(struct mach_trap_args *); +int mach_port_request_notification(struct mach_trap_args *); +int mach_port_insert_right(struct mach_trap_args *); +int mach_port_get_attributes(struct mach_trap_args *); +int mach_port_set_attributes(struct mach_trap_args *); +int mach_port_insert_member(struct mach_trap_args *); +int mach_task_terminate(struct mach_trap_args *); +int mach_task_threads(struct mach_trap_args *); +int mach_ports_lookup(struct mach_trap_args *); +int mach_task_info(struct mach_trap_args *); +int mach_task_suspend(struct mach_trap_args *); +int mach_task_resume(struct mach_trap_args *); +int mach_task_get_special_port(struct mach_trap_args *); +int mach_task_set_special_port(struct mach_trap_args *); +int mach_thread_create_running(struct mach_trap_args *); +int mach_task_set_exception_ports(struct mach_trap_args *); +int mach_task_get_exception_ports(struct mach_trap_args *); +int mach_semaphore_create(struct mach_trap_args *); +int mach_semaphore_destroy(struct mach_trap_args *); +int mach_thread_get_state(struct mach_trap_args *); +int mach_thread_set_state(struct mach_trap_args *); +int mach_thread_suspend(struct mach_trap_args *); +int mach_thread_resume(struct mach_trap_args *); +int mach_thread_abort(struct mach_trap_args *); +int mach_thread_info(struct mach_trap_args *); +int mach_thread_policy(struct mach_trap_args *); +int mach_thread_set_policy(struct mach_trap_args *); +int mach_vm_region(struct mach_trap_args *); +int mach_vm_allocate(struct mach_trap_args *); +int mach_vm_deallocate(struct mach_trap_args *); +int mach_vm_protect(struct mach_trap_args *); +int mach_vm_inherit(struct mach_trap_args *); +int mach_vm_read(struct mach_trap_args *); +int mach_vm_write(struct mach_trap_args *); +int mach_vm_copy(struct mach_trap_args *); +int mach_vm_msync(struct mach_trap_args *); +int mach_vm_map(struct mach_trap_args *); +int mach_vm_machine_attribute(struct mach_trap_args *); +int mach_vm_region_64(struct mach_trap_args *); +int mach_make_memory_entry_64(struct mach_trap_args *); diff --git a/sys/compat/mach/mach_services.master b/sys/compat/mach/mach_services.master new file mode 100644 index 0000000..f5ee01c --- /dev/null +++ b/sys/compat/mach/mach_services.master @@ -0,0 +1,481 @@ + $NetBSD: mach_services.master,v 1.13 2005/12/11 12:20:20 christos Exp $ +; +; Mach services list. +; +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +%% + +; +; Port Notification messages +; +64 OBSOL notify_first +65 NODEF notify_port_deleted +66 OBSOL notify_msg_accepted +67 OBSOL notify_ownership_rights +68 OBSOL notify_receive_rights +69 NODEF notify_port_destroyed +70 NODEF notify_port_no_senders +71 NODEF notify_port_send_once +72 NODEF notify_port_dead_name + +; +; Host subsystem +; +200 STD host_info +201 UNIMPL host_kernel_version +202 STD host_page_size +203 UNIMPL memory_object_memory_entry +204 UNIMPL host_processor_info +205 STD host_get_io_master +206 STD host_get_clock_service +207 UNIMPL kmod_get_info +208 UNIMPL host_zone_info +209 UNIMPL host_virtual_physical_table_info +210 UNIMPL host_ipc_hash_info +; Probably Darwin specific... +211 UNIMPL enable_bluebox +212 UNIMPL disable_bluebox +213 STD processor_set_default +214 UNIMPL processor_set_create +215 UNIMPL memory_object_memory_entry_64 +216 UNIMPL host_statistics + +; +; Host subsystem (private) +; +400 UNIMPL host_get_boot_info +401 UNIMPL host_reboot +402 UNIMPL host_priv_statistics +; Implemented by mach_init, clashes with host_default_memory_manager +403 UNIMPL boostrap_register +; Implemented by mach_init, clashes with vm_wire +404 STD bootstrap_look_up +405 UNIMPL thread_wire +406 UNIMPL vm_allocate_cpm +407 UNIMPL host_processors +408 UNIMPL host_get_clock_control +409 UNIMPL kmod_create +410 UNIMPL kmod_destroy +411 UNIMPL kmod_control +412 UNIMPL host_get_special_port +413 UNIMPL host_set_special_port +414 UNIMPL host_set_exception_ports +415 UNIMPL host_get_exception_ports +416 UNIMPL host_swap_exception_ports +417 UNIMPL host_load_symbol_table +418 UNIMPL task_swappable +419 UNIMPL host_processor_sets +420 STD host_processor_set_priv +421 UNIMPL set_dp_control_port +422 UNIMPL get_dp_control_port +423 UNIMPL host_set_UNDServer +424 UNIMPL host_get_UNDServer + +; +; Host security +; +600 UNIMPL host_security_create_task_token +601 UNIMPL host_security_set_task_token + +; +; Clock subsystem +; +1000 STD clock_get_time +1001 UNIMPL clock_get_attributes +1002 UNIMPL clock_alarm + +; +; Clock subsystem (private) +; +1200 UNIMPL clock_set_time +1201 UNIMPL clock_set_attributes + +; +; Memoey management +; +2000 UNIMPL memory_object_get_attributes +2001 UNIMPL memory_object_change_attributes +2002 UNIMPL memory_object_synchronize_completed +2003 UNIMPL memory_object_lock_request +2004 UNIMPL memory_object_destroy +2005 UNIMPL memory_object_upl_request +2006 UNIMPL memory_object_super_upl_request +2007 UNIMPL memory_object_page_op +2008 UNIMPL memory_object_recover_named +2009 UNIMPL memory_object_release_name + +; +; UPL (External memory management) +; +2050 UNIMPL upl_abort +2051 UNIMPL upl_abort_range +2052 UNIMPL upl_commit +2053 UNIMPL upl_commit_range + +; +; Memory management (control) +; +2200 UNIMPL memory_object_init +2201 UNIMPL memory_object_terminate +2202 UNIMPL memory_object_data_request +2203 UNIMPL memory_object_data_return +2204 UNIMPL memory_object_data_initialize +2205 UNIMPL memory_object_data_unlock +2206 UNIMPL memory_object_synchronize +2207 UNIMPL memory_object_unmap + +; +; Memory management (default) +; +2250 UNIMPL memory_object_create + +; +; Default pager (object) +; +2275 UNIMPL default_pager_object_create +2276 UNIMPL default_pager_info +2277 UNIMPL default_pager_objects +2278 UNIMPL default_pager_object_pages +2279 UNIMPL default_pager_backing_store_create +2280 UNIMPL default_pager_backing_store_delete +2281 UNIMPL default_pager_add_segment +2282 UNIMPL default_pager_backing_store_info +2283 UNIMPL default_pager_add_file +2284 UNIMPL default_pager_triggers + +; +; Default pager (alerts) +; +2295 UNIMPL default_pager_space_alert + +; +; Mach exception interface +; +2401 NODEF exception_raise +2402 NODEF exception_raise_state +2403 NODEF exception_raise_state_identity + +; +; Profiling +; +2450 UNIMPL samples +2451 UNIMPL notices + +; +; Mach exception Replies. +; Defined because the kernel is the client here: +; it has to handle replies instead of reequest. +; +2501 STD exception_raise +2502 STD exception_raise_state +2503 STD exception_raise_state_identity + +; +; Mach IOKit +; +2800 STD io_object_get_class +2801 STD io_object_conforms_to +2802 STD io_iterator_next +2803 STD io_iterator_reset +2804 STD io_service_get_matching_services +2805 STD io_registry_entry_get_property +2806 UNIMPL io_registry_create_iterator +2807 UNIMPL io_registry_iterator_enter_entry +2808 UNIMPL io_registry_iterator_exit_entry +2809 STD io_registry_entry_from_path +2810 UNIMPL io_registry_entry_get_name +2811 STD io_registry_entry_get_properties +2812 UNIMPL io_registry_entry_get_property_bytes +2813 STD io_registry_entry_get_child_iterator +2814 STD io_registry_entry_get_parent_iterator +2815 STD io_service_open +2816 STD io_service_close +2817 STD io_connect_get_service +2818 STD io_connect_set_notification_port +2819 STD io_connect_map_memory +2820 STD io_connect_add_client +2821 STD io_connect_set_properties +2822 STD io_connect_method_scalari_scalaro +2823 STD io_connect_method_scalari_structo +2824 STD io_connect_method_scalari_structi +2825 STD io_connect_method_structi_structo +2826 STD io_registry_entry_get_path +2827 STD io_registry_get_root_entry +2828 UNIMPL io_registry_entry_set_properties +2829 UNIMPL io_registry_entry_in_plane +2830 UNIMPL io_object_get_retain_count +2831 UNIMPL io_service_get_busy_state +2832 UNIMPL io_service_wait_quiet +2833 STD io_registry_entry_create_iterator +2834 UNIMPL io_iterator_is_valid +2835 UNIMPL io_make_matching +2836 UNIMPL io_catalog_send_data +2837 UNIMPL io_catalog_terminate +2838 UNIMPL io_catalog_get_data +2839 UNIMPL io_catalog_get_gen_count +2840 UNIMPL io_catalog_module_loaded +2841 UNIMPL io_catalog_reset +2842 UNIMPL io_service_request_probe +2843 STD io_registry_entry_get_name_in_plane +2844 UNIMPL io_service_match_property_table +2845 UNIMPL io_async_method_scalari_scalaro +2846 UNIMPL io_async_method_scalari_structo +2847 UNIMPL io_async_method_scalari_structi +2848 UNIMPL io_async_method_structi_structo +2849 UNIMPL io_service_add_notification +2850 STD io_service_add_interest_notification +2851 UNIMPL io_service_acknowledge_notification +2852 UNIMPL io_connect_get_notification_semaphore +2853 UNIMPL io_connect_unmap_memory +2854 STD io_registry_entry_get_location_in_plane +2855 UNIMPL io_registry_entry_get_property_recursively + +; +; Processor subsystem +; +3000 UNIMPL processor_start +3001 UNIMPL processor_exit +3002 UNIMPL processor_info +3003 UNIMPL processor_control +3004 UNIMPL processor_assign +3005 UNIMPL processor_get_assignment + +; +; Mach ports +; +3200 UNIMPL port_names +3201 STD port_type +3202 UNIMPL port_rename +3203 UNIMPL port_allocate_name +3204 STD port_allocate +3205 STD port_destroy +3206 STD port_deallocate +3207 STD port_get_refs +3208 STD port_mod_refs +3210 UNIMPL port_set_mscount +3211 UNIMPL port_get_set_status +3212 STD port_move_member +3213 STD port_request_notification +3214 STD port_insert_right +3215 UNIMPL port_extract_right +3216 UNIMPL port_set_seqno +3217 STD port_get_attributes +3218 STD port_set_attributes +3219 UNIMPL port_allocate_qos +3220 UNIMPL port_allocate_full +3221 UNIMPL task_set_port_space +3222 UNIMPL port_get_srights +3223 UNIMPL port_space_info +3224 UNIMPL port_dnrequest_info +3225 UNIMPL port_kernel_object +3226 STD port_insert_member +3227 UNIMPL port_extract_member + +; +; Mach tasks +; +3400 UNIMPL task_create +3401 STD task_terminate +3402 STD task_threads +3403 UNIMPL ports_register +3404 STD ports_lookup +3405 STD task_info +3406 UNIMPL task_set_info +3407 STD task_suspend +3408 STD task_resume +3409 STD task_get_special_port +3410 STD task_set_special_port +3411 UNIMPL thread_create +3412 STD thread_create_running +3413 STD task_set_exception_ports +3414 STD task_get_exception_ports +3415 UNIMPL task_swap_exception_ports +3416 UNIMPL lock_set_create +3417 UNIMPL lock_set_destroy +3418 STD semaphore_create +3419 STD semaphore_destroy +3420 UNIMPL task_policy_set +3421 UNIMPL task_policy_get +3422 UNIMPL task_sample +3423 UNIMPL task_policy +3424 UNIMPL task_set_emulation +3425 UNIMPL task_get_emulation_vector +3426 UNIMPL task_set_emulation_vector +3427 UNIMPL task_set_ras_pc +3428 UNIMPL kernel_task_create +3429 UNIMPL task_assign +3430 UNIMPL task_assign_default +3431 UNIMPL task_get_assignment +3432 UNIMPL task_set_policy + +; +; Mach threads +; +3600 UNIMPL thread_terminate +3601 UNIMPL act_get_state +3602 UNIMPL act_set_state +3603 STD thread_get_state +3604 STD thread_set_state +3605 STD thread_suspend +3606 STD thread_resume +3607 STD thread_abort +3608 UNIMPL thread_abort_safely +3609 UNIMPL thread_depress_abort +3610 UNIMPL thread_get_special_port +3611 UNIMPL thread_set_special_port +3612 STD thread_info +3613 UNIMPL thread_set_exception_ports +3614 UNIMPL thread_get_exception_ports +3615 UNIMPL thread_swap_exception_ports +3616 STD thread_policy +3617 UNIMPL thread_policy_set +3618 UNIMPL thread_policy_get +3619 UNIMPL thread_sample +3620 UNIMPL etap_trace_thread +3621 UNIMPL thread_assign +3622 UNIMPL thread_assign_default +3623 UNIMPL thread_get_assignment +3624 STD thread_set_policy + +; +; VM mappings +; +3800 STD vm_region +3801 STD vm_allocate +3802 STD vm_deallocate +3803 STD vm_protect +3804 STD vm_inherit +3805 STD vm_read +3806 UNIMPL vm_read_list +3807 STD vm_write +3808 STD vm_copy +3809 UNIMPL vm_read_overwrite +3810 STD vm_msync +3811 UNIMPL vm_behavior_set +3812 STD vm_map +3813 STD vm_machine_attribute +3814 UNIMPL vm_remap +3815 UNIMPL task_wire +3816 UNIMPL make_memory_entry +3817 UNIMPL vm_map_page_query +3818 UNIMPL vm_region_info +3819 UNIMPL vm_mapped_pages_info +3820 UNIMPL vm_region_object_create +3821 UNIMPL vm_region_recurse +3822 UNIMPL vm_region_recurse_64 +3823 UNIMPL vm_region_info_64 +3824 STD vm_region_64 +3825 STD make_memory_entry_64 +3826 UNIMPL vm_map_64 +3827 UNIMPL vm_map_get_upl +3828 UNIMPL vm_upl_map +3829 UNIMPL vm_upl_unmap + +; +; Processor set +; +4000 UNIMPL processor_set_statistics +4001 UNIMPL processor_set_destroy +4002 UNIMPL processor_set_max_priority +4003 UNIMPL processor_set_policy_enable +4004 UNIMPL processor_set_policy_disable +4005 UNIMPL processor_set_tasks +4006 UNIMPL processor_set_threads +4007 UNIMPL processor_set_policy_control +4008 UNIMPL processor_set_stack_usage +4009 UNIMPL processor_set_info + +; +; Ledger +; +5000 UNIMPL ledger_create +5001 UNIMPL ledger_terminate +5002 UNIMPL ledger_transfer +5003 UNIMPL ledger_read + +; +; User Notification subsystem (UNDRequest) +; +6000 UNIMPL und_execute_rpc +6001 UNIMPL und_display_notice_from_bundle_rpc +6002 UNIMPL und_display_alert_from_bundle_rpc +6003 UNIMPL und_display_custom_from_bundle_rpc +6004 UNIMPL und_display_custom_from_dictionary_rpc +6005 UNIMPL und_cancel_notification_rpc +6006 UNIMPL und_display_notice_simple_rpc +6007 UNIMPL und_display_alert_simple_rpc + +; +; User Notification subsystem (UNDReply) +; +6200 UNIMPL und_alert_completed_with_result_rpc +6201 UNIMPL und_notification_created_rpc( + +; +; Mach Norma +; +555001 UNIMPL task_set_child_node +555002 UNIMPL norma_node_self +555005 UNIMPL norma_task_clone +555006 UNIMPL norma_task_create +555007 UNIMPL norma_get_special_port +555008 UNIMPL norma_set_special_port +555009 UNIMPL norma_task_teleport +555012 UNIMPL norma_port_location_hint + +; +; Sync, overlapping with Lock set +; +;617000 UNIMPL semaphore_create +;617001 UNIMPL semaphore_destroy +;617002 UNIMPL semaphore_signal +;617003 UNIMPL semaphore_signal_all +;617004 UNIMPL semaphore_wait +;617013 UNIMPL semaphore_signal_thread +;617014 UNIMPL semaphore_timedwait + +; +; Lock set +; +617000 UNIMPL lock_acquire +617001 UNIMPL lock_release +617002 UNIMPL lock_try +617003 UNIMPL lock_make_stable +617004 UNIMPL lock_handoff +617005 UNIMPL lock_handoff_accept +617005 UNIMPL lock_set_create +617006 UNIMPL lock_set_destroy +617007 UNIMPL lock_acquire +617008 UNIMPL lock_release +617009 UNIMPL lock_try +617010 UNIMPL lock_make_stable +617011 UNIMPL lock_handoff +617012 UNIMPL lock_handoff_accept + +; +; Semaphores +; +617200 UNIMPL semaphore_signal +617201 UNIMPL semaphore_signal_all +617202 UNIMPL semaphore_wait +617203 UNIMPL semaphore_signal_thread +617204 UNIMPL semaphore_timedwait +617205 UNIMPL semaphore_wait_signal +617206 UNIMPL semaphore_timedwait_signal diff --git a/sys/compat/mach/mach_services_names.c b/sys/compat/mach/mach_services_names.c new file mode 100644 index 0000000..dd0a3c7 --- /dev/null +++ b/sys/compat/mach/mach_services_names.c @@ -0,0 +1,351 @@ +/* $NetBSD: mach_services_names.c,v 1.16 2009/01/13 22:33:10 pooka Exp $ */ + +/* + * Mach services names. This file is not built + * by the kernel, it is included by kdump sources. + * + * DO NOT EDIT -- this file is automatically generated. + * created from NetBSD: mach_services.master,v 1.13 2005/12/11 12:20:20 christos Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_services_names.c,v 1.16 2009/01/13 22:33:10 pooka Exp $"); + +struct mach_service_name { + int srv_id; + const char *srv_name; +}; + +struct mach_service_name mach_services_names[] = { + {64, "obsolete notify_first"}, + {65, "notify_port_deleted"}, + {66, "obsolete notify_msg_accepted"}, + {67, "obsolete notify_ownership_rights"}, + {68, "obsolete notify_receive_rights"}, + {69, "notify_port_destroyed"}, + {70, "notify_port_no_senders"}, + {71, "notify_port_send_once"}, + {72, "notify_port_dead_name"}, + {200, "host_info"}, + {201, "unimpl. host_kernel_version"}, + {202, "host_page_size"}, + {203, "unimpl. memory_object_memory_entry"}, + {204, "unimpl. host_processor_info"}, + {205, "host_get_io_master"}, + {206, "host_get_clock_service"}, + {207, "unimpl. kmod_get_info"}, + {208, "unimpl. host_zone_info"}, + {209, "unimpl. host_virtual_physical_table_info"}, + {210, "unimpl. host_ipc_hash_info"}, + {211, "unimpl. enable_bluebox"}, + {212, "unimpl. disable_bluebox"}, + {213, "processor_set_default"}, + {214, "unimpl. processor_set_create"}, + {215, "unimpl. memory_object_memory_entry_64"}, + {216, "unimpl. host_statistics"}, + {400, "unimpl. host_get_boot_info"}, + {401, "unimpl. host_reboot"}, + {402, "unimpl. host_priv_statistics"}, + {403, "unimpl. boostrap_register"}, + {404, "bootstrap_look_up"}, + {405, "unimpl. thread_wire"}, + {406, "unimpl. vm_allocate_cpm"}, + {407, "unimpl. host_processors"}, + {408, "unimpl. host_get_clock_control"}, + {409, "unimpl. kmod_create"}, + {410, "unimpl. kmod_destroy"}, + {411, "unimpl. kmod_control"}, + {412, "unimpl. host_get_special_port"}, + {413, "unimpl. host_set_special_port"}, + {414, "unimpl. host_set_exception_ports"}, + {415, "unimpl. host_get_exception_ports"}, + {416, "unimpl. host_swap_exception_ports"}, + {417, "unimpl. host_load_symbol_table"}, + {418, "unimpl. task_swappable"}, + {419, "unimpl. host_processor_sets"}, + {420, "host_processor_set_priv"}, + {421, "unimpl. set_dp_control_port"}, + {422, "unimpl. get_dp_control_port"}, + {423, "unimpl. host_set_UNDServer"}, + {424, "unimpl. host_get_UNDServer"}, + {600, "unimpl. host_security_create_task_token"}, + {601, "unimpl. host_security_set_task_token"}, + {1000, "clock_get_time"}, + {1001, "unimpl. clock_get_attributes"}, + {1002, "unimpl. clock_alarm"}, + {1200, "unimpl. clock_set_time"}, + {1201, "unimpl. clock_set_attributes"}, + {2000, "unimpl. memory_object_get_attributes"}, + {2001, "unimpl. memory_object_change_attributes"}, + {2002, "unimpl. memory_object_synchronize_completed"}, + {2003, "unimpl. memory_object_lock_request"}, + {2004, "unimpl. memory_object_destroy"}, + {2005, "unimpl. memory_object_upl_request"}, + {2006, "unimpl. memory_object_super_upl_request"}, + {2007, "unimpl. memory_object_page_op"}, + {2008, "unimpl. memory_object_recover_named"}, + {2009, "unimpl. memory_object_release_name"}, + {2050, "unimpl. upl_abort"}, + {2051, "unimpl. upl_abort_range"}, + {2052, "unimpl. upl_commit"}, + {2053, "unimpl. upl_commit_range"}, + {2200, "unimpl. memory_object_init"}, + {2201, "unimpl. memory_object_terminate"}, + {2202, "unimpl. memory_object_data_request"}, + {2203, "unimpl. memory_object_data_return"}, + {2204, "unimpl. memory_object_data_initialize"}, + {2205, "unimpl. memory_object_data_unlock"}, + {2206, "unimpl. memory_object_synchronize"}, + {2207, "unimpl. memory_object_unmap"}, + {2250, "unimpl. memory_object_create"}, + {2275, "unimpl. default_pager_object_create"}, + {2276, "unimpl. default_pager_info"}, + {2277, "unimpl. default_pager_objects"}, + {2278, "unimpl. default_pager_object_pages"}, + {2279, "unimpl. default_pager_backing_store_create"}, + {2280, "unimpl. default_pager_backing_store_delete"}, + {2281, "unimpl. default_pager_add_segment"}, + {2282, "unimpl. default_pager_backing_store_info"}, + {2283, "unimpl. default_pager_add_file"}, + {2284, "unimpl. default_pager_triggers"}, + {2295, "unimpl. default_pager_space_alert"}, + {2401, "exception_raise"}, + {2402, "exception_raise_state"}, + {2403, "exception_raise_state_identity"}, + {2450, "unimpl. samples"}, + {2451, "unimpl. notices"}, + {2501, "exception_raise"}, + {2502, "exception_raise_state"}, + {2503, "exception_raise_state_identity"}, + {2800, "io_object_get_class"}, + {2801, "io_object_conforms_to"}, + {2802, "io_iterator_next"}, + {2803, "io_iterator_reset"}, + {2804, "io_service_get_matching_services"}, + {2805, "io_registry_entry_get_property"}, + {2806, "unimpl. io_registry_create_iterator"}, + {2807, "unimpl. io_registry_iterator_enter_entry"}, + {2808, "unimpl. io_registry_iterator_exit_entry"}, + {2809, "io_registry_entry_from_path"}, + {2810, "unimpl. io_registry_entry_get_name"}, + {2811, "io_registry_entry_get_properties"}, + {2812, "unimpl. io_registry_entry_get_property_bytes"}, + {2813, "io_registry_entry_get_child_iterator"}, + {2814, "io_registry_entry_get_parent_iterator"}, + {2815, "io_service_open"}, + {2816, "io_service_close"}, + {2817, "io_connect_get_service"}, + {2818, "io_connect_set_notification_port"}, + {2819, "io_connect_map_memory"}, + {2820, "io_connect_add_client"}, + {2821, "io_connect_set_properties"}, + {2822, "io_connect_method_scalari_scalaro"}, + {2823, "io_connect_method_scalari_structo"}, + {2824, "io_connect_method_scalari_structi"}, + {2825, "io_connect_method_structi_structo"}, + {2826, "io_registry_entry_get_path"}, + {2827, "io_registry_get_root_entry"}, + {2828, "unimpl. io_registry_entry_set_properties"}, + {2829, "unimpl. io_registry_entry_in_plane"}, + {2830, "unimpl. io_object_get_retain_count"}, + {2831, "unimpl. io_service_get_busy_state"}, + {2832, "unimpl. io_service_wait_quiet"}, + {2833, "io_registry_entry_create_iterator"}, + {2834, "unimpl. io_iterator_is_valid"}, + {2835, "unimpl. io_make_matching"}, + {2836, "unimpl. io_catalog_send_data"}, + {2837, "unimpl. io_catalog_terminate"}, + {2838, "unimpl. io_catalog_get_data"}, + {2839, "unimpl. io_catalog_get_gen_count"}, + {2840, "unimpl. io_catalog_module_loaded"}, + {2841, "unimpl. io_catalog_reset"}, + {2842, "unimpl. io_service_request_probe"}, + {2843, "io_registry_entry_get_name_in_plane"}, + {2844, "unimpl. io_service_match_property_table"}, + {2845, "unimpl. io_async_method_scalari_scalaro"}, + {2846, "unimpl. io_async_method_scalari_structo"}, + {2847, "unimpl. io_async_method_scalari_structi"}, + {2848, "unimpl. io_async_method_structi_structo"}, + {2849, "unimpl. io_service_add_notification"}, + {2850, "io_service_add_interest_notification"}, + {2851, "unimpl. io_service_acknowledge_notification"}, + {2852, "unimpl. io_connect_get_notification_semaphore"}, + {2853, "unimpl. io_connect_unmap_memory"}, + {2854, "io_registry_entry_get_location_in_plane"}, + {2855, "unimpl. io_registry_entry_get_property_recursively"}, + {3000, "unimpl. processor_start"}, + {3001, "unimpl. processor_exit"}, + {3002, "unimpl. processor_info"}, + {3003, "unimpl. processor_control"}, + {3004, "unimpl. processor_assign"}, + {3005, "unimpl. processor_get_assignment"}, + {3200, "unimpl. port_names"}, + {3201, "port_type"}, + {3202, "unimpl. port_rename"}, + {3203, "unimpl. port_allocate_name"}, + {3204, "port_allocate"}, + {3205, "port_destroy"}, + {3206, "port_deallocate"}, + {3207, "port_get_refs"}, + {3208, "port_mod_refs"}, + {3210, "unimpl. port_set_mscount"}, + {3211, "unimpl. port_get_set_status"}, + {3212, "port_move_member"}, + {3213, "port_request_notification"}, + {3214, "port_insert_right"}, + {3215, "unimpl. port_extract_right"}, + {3216, "unimpl. port_set_seqno"}, + {3217, "port_get_attributes"}, + {3218, "port_set_attributes"}, + {3219, "unimpl. port_allocate_qos"}, + {3220, "unimpl. port_allocate_full"}, + {3221, "unimpl. task_set_port_space"}, + {3222, "unimpl. port_get_srights"}, + {3223, "unimpl. port_space_info"}, + {3224, "unimpl. port_dnrequest_info"}, + {3225, "unimpl. port_kernel_object"}, + {3226, "port_insert_member"}, + {3227, "unimpl. port_extract_member"}, + {3400, "unimpl. task_create"}, + {3401, "task_terminate"}, + {3402, "task_threads"}, + {3403, "unimpl. ports_register"}, + {3404, "ports_lookup"}, + {3405, "task_info"}, + {3406, "unimpl. task_set_info"}, + {3407, "task_suspend"}, + {3408, "task_resume"}, + {3409, "task_get_special_port"}, + {3410, "task_set_special_port"}, + {3411, "unimpl. thread_create"}, + {3412, "thread_create_running"}, + {3413, "task_set_exception_ports"}, + {3414, "task_get_exception_ports"}, + {3415, "unimpl. task_swap_exception_ports"}, + {3416, "unimpl. lock_set_create"}, + {3417, "unimpl. lock_set_destroy"}, + {3418, "semaphore_create"}, + {3419, "semaphore_destroy"}, + {3420, "unimpl. task_policy_set"}, + {3421, "unimpl. task_policy_get"}, + {3422, "unimpl. task_sample"}, + {3423, "unimpl. task_policy"}, + {3424, "unimpl. task_set_emulation"}, + {3425, "unimpl. task_get_emulation_vector"}, + {3426, "unimpl. task_set_emulation_vector"}, + {3427, "unimpl. task_set_ras_pc"}, + {3428, "unimpl. kernel_task_create"}, + {3429, "unimpl. task_assign"}, + {3430, "unimpl. task_assign_default"}, + {3431, "unimpl. task_get_assignment"}, + {3432, "unimpl. task_set_policy"}, + {3600, "unimpl. thread_terminate"}, + {3601, "unimpl. act_get_state"}, + {3602, "unimpl. act_set_state"}, + {3603, "thread_get_state"}, + {3604, "thread_set_state"}, + {3605, "thread_suspend"}, + {3606, "thread_resume"}, + {3607, "thread_abort"}, + {3608, "unimpl. thread_abort_safely"}, + {3609, "unimpl. thread_depress_abort"}, + {3610, "unimpl. thread_get_special_port"}, + {3611, "unimpl. thread_set_special_port"}, + {3612, "thread_info"}, + {3613, "unimpl. thread_set_exception_ports"}, + {3614, "unimpl. thread_get_exception_ports"}, + {3615, "unimpl. thread_swap_exception_ports"}, + {3616, "thread_policy"}, + {3617, "unimpl. thread_policy_set"}, + {3618, "unimpl. thread_policy_get"}, + {3619, "unimpl. thread_sample"}, + {3620, "unimpl. etap_trace_thread"}, + {3621, "unimpl. thread_assign"}, + {3622, "unimpl. thread_assign_default"}, + {3623, "unimpl. thread_get_assignment"}, + {3624, "thread_set_policy"}, + {3800, "vm_region"}, + {3801, "vm_allocate"}, + {3802, "vm_deallocate"}, + {3803, "vm_protect"}, + {3804, "vm_inherit"}, + {3805, "vm_read"}, + {3806, "unimpl. vm_read_list"}, + {3807, "vm_write"}, + {3808, "vm_copy"}, + {3809, "unimpl. vm_read_overwrite"}, + {3810, "vm_msync"}, + {3811, "unimpl. vm_behavior_set"}, + {3812, "vm_map"}, + {3813, "vm_machine_attribute"}, + {3814, "unimpl. vm_remap"}, + {3815, "unimpl. task_wire"}, + {3816, "unimpl. make_memory_entry"}, + {3817, "unimpl. vm_map_page_query"}, + {3818, "unimpl. vm_region_info"}, + {3819, "unimpl. vm_mapped_pages_info"}, + {3820, "unimpl. vm_region_object_create"}, + {3821, "unimpl. vm_region_recurse"}, + {3822, "unimpl. vm_region_recurse_64"}, + {3823, "unimpl. vm_region_info_64"}, + {3824, "vm_region_64"}, + {3825, "make_memory_entry_64"}, + {3826, "unimpl. vm_map_64"}, + {3827, "unimpl. vm_map_get_upl"}, + {3828, "unimpl. vm_upl_map"}, + {3829, "unimpl. vm_upl_unmap"}, + {4000, "unimpl. processor_set_statistics"}, + {4001, "unimpl. processor_set_destroy"}, + {4002, "unimpl. processor_set_max_priority"}, + {4003, "unimpl. processor_set_policy_enable"}, + {4004, "unimpl. processor_set_policy_disable"}, + {4005, "unimpl. processor_set_tasks"}, + {4006, "unimpl. processor_set_threads"}, + {4007, "unimpl. processor_set_policy_control"}, + {4008, "unimpl. processor_set_stack_usage"}, + {4009, "unimpl. processor_set_info"}, + {5000, "unimpl. ledger_create"}, + {5001, "unimpl. ledger_terminate"}, + {5002, "unimpl. ledger_transfer"}, + {5003, "unimpl. ledger_read"}, + {6000, "unimpl. und_execute_rpc"}, + {6001, "unimpl. und_display_notice_from_bundle_rpc"}, + {6002, "unimpl. und_display_alert_from_bundle_rpc"}, + {6003, "unimpl. und_display_custom_from_bundle_rpc"}, + {6004, "unimpl. und_display_custom_from_dictionary_rpc"}, + {6005, "unimpl. und_cancel_notification_rpc"}, + {6006, "unimpl. und_display_notice_simple_rpc"}, + {6007, "unimpl. und_display_alert_simple_rpc"}, + {6200, "unimpl. und_alert_completed_with_result_rpc"}, + {6201, "unimpl. und_notification_created_rpc("}, + {555001, "unimpl. task_set_child_node"}, + {555002, "unimpl. norma_node_self"}, + {555005, "unimpl. norma_task_clone"}, + {555006, "unimpl. norma_task_create"}, + {555007, "unimpl. norma_get_special_port"}, + {555008, "unimpl. norma_set_special_port"}, + {555009, "unimpl. norma_task_teleport"}, + {555012, "unimpl. norma_port_location_hint"}, + {617000, "unimpl. lock_acquire"}, + {617001, "unimpl. lock_release"}, + {617002, "unimpl. lock_try"}, + {617003, "unimpl. lock_make_stable"}, + {617004, "unimpl. lock_handoff"}, + {617005, "unimpl. lock_handoff_accept"}, + {617005, "unimpl. lock_set_create"}, + {617006, "unimpl. lock_set_destroy"}, + {617007, "unimpl. lock_acquire"}, + {617008, "unimpl. lock_release"}, + {617009, "unimpl. lock_try"}, + {617010, "unimpl. lock_make_stable"}, + {617011, "unimpl. lock_handoff"}, + {617012, "unimpl. lock_handoff_accept"}, + {617200, "unimpl. semaphore_signal"}, + {617201, "unimpl. semaphore_signal_all"}, + {617202, "unimpl. semaphore_wait"}, + {617203, "unimpl. semaphore_signal_thread"}, + {617204, "unimpl. semaphore_timedwait"}, + {617205, "unimpl. semaphore_wait_signal"}, + {617206, "unimpl. semaphore_timedwait_signal"}, + {0, NULL} +}; diff --git a/sys/compat/mach/mach_syscall.h b/sys/compat/mach/mach_syscall.h new file mode 100644 index 0000000..cbab9dc --- /dev/null +++ b/sys/compat/mach/mach_syscall.h @@ -0,0 +1,110 @@ +/* $NetBSD: mach_syscall.h,v 1.21 2009/12/14 00:58:37 matt Exp $ */ + +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.10 2009/01/13 22:27:43 pooka Exp + */ + +#ifndef _MACH_SYS_SYSCALL_H_ +#define _MACH_SYS_SYSCALL_H_ + +#define MACH_SYS_MAXSYSARGS 9 + +/* syscall: "reply_port" ret: "mach_port_name_t" args: */ +#define MACH_SYS_reply_port 26 + +/* syscall: "thread_self_trap" ret: "mach_port_name_t" args: */ +#define MACH_SYS_thread_self_trap 27 + +/* syscall: "task_self_trap" ret: "mach_port_name_t" args: */ +#define MACH_SYS_task_self_trap 28 + +/* syscall: "host_self_trap" ret: "mach_port_name_t" args: */ +#define MACH_SYS_host_self_trap 29 + +/* syscall: "msg_trap" ret: "mach_msg_return_t" args: "mach_msg_header_t *" "mach_msg_option_t" "mach_msg_size_t" "mach_msg_size_t" "mach_port_name_t" "mach_msg_timeout_t" "mach_port_name_t" */ +#define MACH_SYS_msg_trap 31 + +/* syscall: "msg_overwrite_trap" ret: "mach_kern_return_t" args: "mach_msg_header_t *" "mach_msg_option_t" "mach_msg_size_t" "mach_msg_size_t" "mach_port_name_t" "mach_msg_timeout_t" "mach_port_name_t" "mach_msg_header_t *" "mach_msg_size_t" */ +#define MACH_SYS_msg_overwrite_trap 32 + +/* syscall: "semaphore_signal_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" */ +#define MACH_SYS_semaphore_signal_trap 33 + +/* syscall: "semaphore_signal_all_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" */ +#define MACH_SYS_semaphore_signal_all_trap 34 + +/* syscall: "semaphore_signal_thread_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" "mach_port_name_t" */ +#define MACH_SYS_semaphore_signal_thread_trap 35 + +/* syscall: "semaphore_wait_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" */ +#define MACH_SYS_semaphore_wait_trap 36 + +/* syscall: "semaphore_wait_signal_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" "mach_port_name_t" */ +#define MACH_SYS_semaphore_wait_signal_trap 37 + +/* syscall: "semaphore_timedwait_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" "unsigned int" "mach_clock_res_t" */ +#define MACH_SYS_semaphore_timedwait_trap 38 + +/* syscall: "semaphore_timedwait_signal_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" "mach_port_name_t" "unsigned int" "mach_clock_res_t" */ +#define MACH_SYS_semaphore_timedwait_signal_trap 39 + +/* syscall: "init_process" ret: "mach_kern_return_t" args: */ +#define MACH_SYS_init_process 41 + +/* syscall: "map_fd" ret: "mach_kern_return_t" args: "int" "mach_vm_offset_t" "mach_vm_offset_t *" "mach_boolean_t" "mach_vm_size_t" */ +#define MACH_SYS_map_fd 43 + +/* syscall: "task_for_pid" ret: "mach_kern_return_t" args: "mach_port_t" "int" "mach_port_t *" */ +#define MACH_SYS_task_for_pid 45 + +/* syscall: "pid_for_task" ret: "mach_kern_return_t" args: "mach_port_t" "int *" */ +#define MACH_SYS_pid_for_task 46 + +/* syscall: "macx_swapon" ret: "mach_kern_return_t" args: "char *" "int" "int" "int" */ +#define MACH_SYS_macx_swapon 48 + +/* syscall: "macx_swapoff" ret: "mach_kern_return_t" args: "char *" "int" */ +#define MACH_SYS_macx_swapoff 49 + +/* syscall: "macx_triggers" ret: "mach_kern_return_t" args: "int" "int" "int" "mach_port_t" */ +#define MACH_SYS_macx_triggers 51 + +/* syscall: "swtch_pri" ret: "mach_kern_return_t" args: "int" */ +#define MACH_SYS_swtch_pri 59 + +/* syscall: "swtch" ret: "mach_kern_return_t" args: */ +#define MACH_SYS_swtch 60 + +/* syscall: "syscall_thread_switch" ret: "mach_kern_return_t" args: "mach_port_name_t" "int" "mach_msg_timeout_t" */ +#define MACH_SYS_syscall_thread_switch 61 + +/* syscall: "clock_sleep_trap" ret: "mach_kern_return_t" args: "mach_port_name_t" "mach_sleep_type_t" "int" "int" "mach_timespec_t *" */ +#define MACH_SYS_clock_sleep_trap 62 + +/* syscall: "timebase_info" ret: "mach_kern_return_t" args: "mach_timebase_info_t" */ +#define MACH_SYS_timebase_info 89 + +/* syscall: "wait_until" ret: "mach_kern_return_t" args: "u_int64_t" */ +#define MACH_SYS_wait_until 90 + +/* syscall: "timer_create" ret: "mach_port_name_t" args: */ +#define MACH_SYS_timer_create 91 + +/* syscall: "timer_destroy" ret: "mach_kern_return_t" args: "mach_port_name_t" */ +#define MACH_SYS_timer_destroy 92 + +/* syscall: "timer_arm" ret: "mach_kern_return_t" args: "mach_port_name_t" "mach_absolute_time_t" */ +#define MACH_SYS_timer_arm 93 + +/* syscall: "timer_cancel" ret: "mach_kern_return_t" args: "mach_port_name_t" "mach_absolute_time_t *" */ +#define MACH_SYS_timer_cancel 94 + +/* syscall: "get_time_base_info" ret: "mach_kern_return_t" args: */ +#define MACH_SYS_get_time_base_info 95 + +#define MACH_SYS_MAXSYSCALL 128 +#define MACH_SYS_NSYSENT 128 +#endif /* _MACH_SYS_SYSCALL_H_ */ diff --git a/sys/compat/mach/mach_syscallargs.h b/sys/compat/mach/mach_syscallargs.h new file mode 100644 index 0000000..4361eb2 --- /dev/null +++ b/sys/compat/mach/mach_syscallargs.h @@ -0,0 +1,258 @@ +/* $NetBSD: mach_syscallargs.h,v 1.21 2009/12/14 00:58:37 matt Exp $ */ + +/* + * System call argument lists. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.10 2009/01/13 22:27:43 pooka Exp + */ + +#ifndef _MACH_SYS_SYSCALLARGS_H_ +#define _MACH_SYS_SYSCALLARGS_H_ + +#define MACH_SYS_MAXSYSARGS 9 + +#undef syscallarg +#define syscallarg(x) \ + union { \ + register_t pad; \ + struct { x datum; } le; \ + struct { /* LINTED zero array dimension */ \ + int8_t pad[ /* CONSTCOND */ \ + (sizeof (register_t) < sizeof (x)) \ + ? 0 \ + : sizeof (register_t) - sizeof (x)]; \ + x datum; \ + } be; \ + } + +#undef check_syscall_args +#define check_syscall_args(call) \ + typedef char call##_check_args[sizeof (struct call##_args) \ + <= MACH_SYS_MAXSYSARGS * sizeof (register_t) ? 1 : -1]; + +struct mach_sys_msg_trap_args { + syscallarg(mach_msg_header_t *) msg; + syscallarg(mach_msg_option_t) option; + syscallarg(mach_msg_size_t) send_size; + syscallarg(mach_msg_size_t) rcv_size; + syscallarg(mach_port_name_t) rcv_name; + syscallarg(mach_msg_timeout_t) timeout; + syscallarg(mach_port_name_t) notify; +}; +check_syscall_args(mach_sys_msg_trap) + +struct mach_sys_msg_overwrite_trap_args { + syscallarg(mach_msg_header_t *) msg; + syscallarg(mach_msg_option_t) option; + syscallarg(mach_msg_size_t) send_size; + syscallarg(mach_msg_size_t) rcv_size; + syscallarg(mach_port_name_t) rcv_name; + syscallarg(mach_msg_timeout_t) timeout; + syscallarg(mach_port_name_t) notify; + syscallarg(mach_msg_header_t *) rcv_msg; + syscallarg(mach_msg_size_t) scatter_list_size; +}; +check_syscall_args(mach_sys_msg_overwrite_trap) + +struct mach_sys_semaphore_signal_trap_args { + syscallarg(mach_port_name_t) signal_name; +}; +check_syscall_args(mach_sys_semaphore_signal_trap) + +struct mach_sys_semaphore_signal_all_trap_args { + syscallarg(mach_port_name_t) signal_name; +}; +check_syscall_args(mach_sys_semaphore_signal_all_trap) + +struct mach_sys_semaphore_signal_thread_trap_args { + syscallarg(mach_port_name_t) signal_name; + syscallarg(mach_port_name_t) thread; +}; +check_syscall_args(mach_sys_semaphore_signal_thread_trap) + +struct mach_sys_semaphore_wait_trap_args { + syscallarg(mach_port_name_t) wait_name; +}; +check_syscall_args(mach_sys_semaphore_wait_trap) + +struct mach_sys_semaphore_wait_signal_trap_args { + syscallarg(mach_port_name_t) wait_name; + syscallarg(mach_port_name_t) signal_name; +}; +check_syscall_args(mach_sys_semaphore_wait_signal_trap) + +struct mach_sys_semaphore_timedwait_trap_args { + syscallarg(mach_port_name_t) wait_name; + syscallarg(unsigned int) sec; + syscallarg(mach_clock_res_t) nsec; +}; +check_syscall_args(mach_sys_semaphore_timedwait_trap) + +struct mach_sys_semaphore_timedwait_signal_trap_args { + syscallarg(mach_port_name_t) wait_name; + syscallarg(mach_port_name_t) signal_name; + syscallarg(unsigned int) sec; + syscallarg(mach_clock_res_t) nsec; +}; +check_syscall_args(mach_sys_semaphore_timedwait_signal_trap) + +struct mach_sys_map_fd_args { + syscallarg(int) fd; + syscallarg(mach_vm_offset_t) offset; + syscallarg(mach_vm_offset_t *) va; + syscallarg(mach_boolean_t) findspace; + syscallarg(mach_vm_size_t) size; +}; +check_syscall_args(mach_sys_map_fd) + +struct mach_sys_task_for_pid_args { + syscallarg(mach_port_t) target_tport; + syscallarg(int) pid; + syscallarg(mach_port_t *) t; +}; +check_syscall_args(mach_sys_task_for_pid) + +struct mach_sys_pid_for_task_args { + syscallarg(mach_port_t) t; + syscallarg(int *) x; +}; +check_syscall_args(mach_sys_pid_for_task) + +struct mach_sys_macx_swapon_args { + syscallarg(char *) name; + syscallarg(int) flags; + syscallarg(int) size; + syscallarg(int) priority; +}; +check_syscall_args(mach_sys_macx_swapon) + +struct mach_sys_macx_swapoff_args { + syscallarg(char *) name; + syscallarg(int) flags; +}; +check_syscall_args(mach_sys_macx_swapoff) + +struct mach_sys_macx_triggers_args { + syscallarg(int) hi_water; + syscallarg(int) low_water; + syscallarg(int) flags; + syscallarg(mach_port_t) alert_port; +}; +check_syscall_args(mach_sys_macx_triggers) + +struct mach_sys_swtch_pri_args { + syscallarg(int) pri; +}; +check_syscall_args(mach_sys_swtch_pri) + +struct mach_sys_syscall_thread_switch_args { + syscallarg(mach_port_name_t) thread_name; + syscallarg(int) option; + syscallarg(mach_msg_timeout_t) option_time; +}; +check_syscall_args(mach_sys_syscall_thread_switch) + +struct mach_sys_clock_sleep_trap_args { + syscallarg(mach_port_name_t) clock_name; + syscallarg(mach_sleep_type_t) sleep_type; + syscallarg(int) sleep_sec; + syscallarg(int) sleep_nsec; + syscallarg(mach_timespec_t *) wakeup_time; +}; +check_syscall_args(mach_sys_clock_sleep_trap) + +struct mach_sys_timebase_info_args { + syscallarg(mach_timebase_info_t) info; +}; +check_syscall_args(mach_sys_timebase_info) + +struct mach_sys_wait_until_args { + syscallarg(u_int64_t) deadline; +}; +check_syscall_args(mach_sys_wait_until) + +struct mach_sys_timer_destroy_args { + syscallarg(mach_port_name_t) name; +}; +check_syscall_args(mach_sys_timer_destroy) + +struct mach_sys_timer_arm_args { + syscallarg(mach_port_name_t) name; + syscallarg(mach_absolute_time_t) expire_time; +}; +check_syscall_args(mach_sys_timer_arm) + +struct mach_sys_timer_cancel_args { + syscallarg(mach_port_name_t) name; + syscallarg(mach_absolute_time_t *) result_time; +}; +check_syscall_args(mach_sys_timer_cancel) + +/* + * System call prototypes. + */ + +int mach_sys_reply_port(struct lwp *, const void *, register_t *); + +int mach_sys_thread_self_trap(struct lwp *, const void *, register_t *); + +int mach_sys_task_self_trap(struct lwp *, const void *, register_t *); + +int mach_sys_host_self_trap(struct lwp *, const void *, register_t *); + +int mach_sys_msg_trap(struct lwp *, const struct mach_sys_msg_trap_args *, register_t *); + +int mach_sys_msg_overwrite_trap(struct lwp *, const struct mach_sys_msg_overwrite_trap_args *, register_t *); + +int mach_sys_semaphore_signal_trap(struct lwp *, const struct mach_sys_semaphore_signal_trap_args *, register_t *); + +int mach_sys_semaphore_signal_all_trap(struct lwp *, const struct mach_sys_semaphore_signal_all_trap_args *, register_t *); + +int mach_sys_semaphore_signal_thread_trap(struct lwp *, const struct mach_sys_semaphore_signal_thread_trap_args *, register_t *); + +int mach_sys_semaphore_wait_trap(struct lwp *, const struct mach_sys_semaphore_wait_trap_args *, register_t *); + +int mach_sys_semaphore_wait_signal_trap(struct lwp *, const struct mach_sys_semaphore_wait_signal_trap_args *, register_t *); + +int mach_sys_semaphore_timedwait_trap(struct lwp *, const struct mach_sys_semaphore_timedwait_trap_args *, register_t *); + +int mach_sys_semaphore_timedwait_signal_trap(struct lwp *, const struct mach_sys_semaphore_timedwait_signal_trap_args *, register_t *); + +int mach_sys_init_process(struct lwp *, const void *, register_t *); + +int mach_sys_map_fd(struct lwp *, const struct mach_sys_map_fd_args *, register_t *); + +int mach_sys_task_for_pid(struct lwp *, const struct mach_sys_task_for_pid_args *, register_t *); + +int mach_sys_pid_for_task(struct lwp *, const struct mach_sys_pid_for_task_args *, register_t *); + +int mach_sys_macx_swapon(struct lwp *, const struct mach_sys_macx_swapon_args *, register_t *); + +int mach_sys_macx_swapoff(struct lwp *, const struct mach_sys_macx_swapoff_args *, register_t *); + +int mach_sys_macx_triggers(struct lwp *, const struct mach_sys_macx_triggers_args *, register_t *); + +int mach_sys_swtch_pri(struct lwp *, const struct mach_sys_swtch_pri_args *, register_t *); + +int mach_sys_swtch(struct lwp *, const void *, register_t *); + +int mach_sys_syscall_thread_switch(struct lwp *, const struct mach_sys_syscall_thread_switch_args *, register_t *); + +int mach_sys_clock_sleep_trap(struct lwp *, const struct mach_sys_clock_sleep_trap_args *, register_t *); + +int mach_sys_timebase_info(struct lwp *, const struct mach_sys_timebase_info_args *, register_t *); + +int mach_sys_wait_until(struct lwp *, const struct mach_sys_wait_until_args *, register_t *); + +int mach_sys_timer_create(struct lwp *, const void *, register_t *); + +int mach_sys_timer_destroy(struct lwp *, const struct mach_sys_timer_destroy_args *, register_t *); + +int mach_sys_timer_arm(struct lwp *, const struct mach_sys_timer_arm_args *, register_t *); + +int mach_sys_timer_cancel(struct lwp *, const struct mach_sys_timer_cancel_args *, register_t *); + +int mach_sys_get_time_base_info(struct lwp *, const void *, register_t *); + +#endif /* _MACH_SYS_SYSCALLARGS_H_ */ diff --git a/sys/compat/mach/mach_syscalls.c b/sys/compat/mach/mach_syscalls.c new file mode 100644 index 0000000..f8f7d7b --- /dev/null +++ b/sys/compat/mach/mach_syscalls.c @@ -0,0 +1,159 @@ +/* $NetBSD: mach_syscalls.c,v 1.22 2009/12/14 00:58:37 matt Exp $ */ + +/* + * System call names. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.10 2009/01/13 22:27:43 pooka Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_syscalls.c,v 1.22 2009/12/14 00:58:37 matt Exp $"); + +#if defined(_KERNEL_OPT) +#if defined(_KERNEL_OPT) +#include "opt_ntp.h" +#include "opt_sysv.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* _KERNEL_OPT */ + +const char *const mach_syscallnames[] = { + /* 0 */ "#0 (unimplemented)", + /* 1 */ "#1 (unimplemented)", + /* 2 */ "#2 (unimplemented)", + /* 3 */ "#3 (unimplemented)", + /* 4 */ "#4 (unimplemented)", + /* 5 */ "#5 (unimplemented)", + /* 6 */ "#6 (unimplemented)", + /* 7 */ "#7 (unimplemented)", + /* 8 */ "#8 (unimplemented)", + /* 9 */ "#9 (unimplemented)", + /* 10 */ "#10 (unimplemented)", + /* 11 */ "#11 (unimplemented)", + /* 12 */ "#12 (unimplemented)", + /* 13 */ "#13 (unimplemented)", + /* 14 */ "#14 (unimplemented)", + /* 15 */ "#15 (unimplemented)", + /* 16 */ "#16 (unimplemented)", + /* 17 */ "#17 (unimplemented)", + /* 18 */ "#18 (unimplemented)", + /* 19 */ "#19 (unimplemented)", + /* 20 */ "#20 (unimplemented)", + /* 21 */ "#21 (unimplemented)", + /* 22 */ "#22 (unimplemented)", + /* 23 */ "#23 (unimplemented)", + /* 24 */ "#24 (unimplemented)", + /* 25 */ "#25 (unimplemented)", + /* 26 */ "reply_port", + /* 27 */ "thread_self_trap", + /* 28 */ "task_self_trap", + /* 29 */ "host_self_trap", + /* 30 */ "#30 (unimplemented)", + /* 31 */ "msg_trap", + /* 32 */ "msg_overwrite_trap", + /* 33 */ "semaphore_signal_trap", + /* 34 */ "semaphore_signal_all_trap", + /* 35 */ "semaphore_signal_thread_trap", + /* 36 */ "semaphore_wait_trap", + /* 37 */ "semaphore_wait_signal_trap", + /* 38 */ "semaphore_timedwait_trap", + /* 39 */ "semaphore_timedwait_signal_trap", + /* 40 */ "#40 (unimplemented)", + /* 41 */ "init_process", + /* 42 */ "#42 (unimplemented)", + /* 43 */ "map_fd", + /* 44 */ "#44 (unimplemented)", + /* 45 */ "task_for_pid", + /* 46 */ "pid_for_task", + /* 47 */ "#47 (unimplemented)", + /* 48 */ "macx_swapon", + /* 49 */ "macx_swapoff", + /* 50 */ "#50 (unimplemented)", + /* 51 */ "macx_triggers", + /* 52 */ "#52 (unimplemented)", + /* 53 */ "#53 (unimplemented)", + /* 54 */ "#54 (unimplemented)", + /* 55 */ "#55 (unimplemented)", + /* 56 */ "#56 (unimplemented)", + /* 57 */ "#57 (unimplemented)", + /* 58 */ "#58 (unimplemented)", + /* 59 */ "swtch_pri", + /* 60 */ "swtch", + /* 61 */ "syscall_thread_switch", + /* 62 */ "clock_sleep_trap", + /* 63 */ "#63 (unimplemented)", + /* 64 */ "#64 (unimplemented)", + /* 65 */ "#65 (unimplemented)", + /* 66 */ "#66 (unimplemented)", + /* 67 */ "#67 (unimplemented)", + /* 68 */ "#68 (unimplemented)", + /* 69 */ "#69 (unimplemented)", + /* 70 */ "#70 (unimplemented)", + /* 71 */ "#71 (unimplemented)", + /* 72 */ "#72 (unimplemented)", + /* 73 */ "#73 (unimplemented)", + /* 74 */ "#74 (unimplemented)", + /* 75 */ "#75 (unimplemented)", + /* 76 */ "#76 (unimplemented)", + /* 77 */ "#77 (unimplemented)", + /* 78 */ "#78 (unimplemented)", + /* 79 */ "#79 (unimplemented)", + /* 80 */ "#80 (unimplemented)", + /* 81 */ "#81 (unimplemented)", + /* 82 */ "#82 (unimplemented)", + /* 83 */ "#83 (unimplemented)", + /* 84 */ "#84 (unimplemented)", + /* 85 */ "#85 (unimplemented)", + /* 86 */ "#86 (unimplemented)", + /* 87 */ "#87 (unimplemented)", + /* 88 */ "#88 (unimplemented)", + /* 89 */ "timebase_info", + /* 90 */ "wait_until", + /* 91 */ "timer_create", + /* 92 */ "timer_destroy", + /* 93 */ "timer_arm", + /* 94 */ "timer_cancel", + /* 95 */ "get_time_base_info", + /* 96 */ "#96 (unimplemented)", + /* 97 */ "#97 (unimplemented)", + /* 98 */ "#98 (unimplemented)", + /* 99 */ "#99 (unimplemented)", + /* 100 */ "#100 (unimplemented)", + /* 101 */ "#101 (unimplemented)", + /* 102 */ "#102 (unimplemented)", + /* 103 */ "#103 (unimplemented)", + /* 104 */ "#104 (unimplemented)", + /* 105 */ "#105 (unimplemented)", + /* 106 */ "#106 (unimplemented)", + /* 107 */ "#107 (unimplemented)", + /* 108 */ "#108 (unimplemented)", + /* 109 */ "#109 (unimplemented)", + /* 110 */ "#110 (unimplemented)", + /* 111 */ "#111 (unimplemented)", + /* 112 */ "#112 (unimplemented)", + /* 113 */ "#113 (unimplemented)", + /* 114 */ "#114 (unimplemented)", + /* 115 */ "#115 (unimplemented)", + /* 116 */ "#116 (unimplemented)", + /* 117 */ "#117 (unimplemented)", + /* 118 */ "#118 (unimplemented)", + /* 119 */ "#119 (unimplemented)", + /* 120 */ "#120 (unimplemented)", + /* 121 */ "#121 (unimplemented)", + /* 122 */ "#122 (unimplemented)", + /* 123 */ "#123 (unimplemented)", + /* 124 */ "#124 (unimplemented)", + /* 125 */ "#125 (unimplemented)", + /* 126 */ "#126 (unimplemented)", + /* 127 */ "#127 (unimplemented)", +}; diff --git a/sys/compat/mach/mach_sysctl.c b/sys/compat/mach/mach_sysctl.c new file mode 100644 index 0000000..07421ee --- /dev/null +++ b/sys/compat/mach/mach_sysctl.c @@ -0,0 +1,73 @@ +/* $NetBSD: mach_sysctl.c,v 1.4 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_sysctl.c,v 1.4 2008/04/28 20:23:44 martin Exp $"); + +#include +#include +#include +#include + +#include + +int mach_exception_hang = 0; + +SYSCTL_SETUP(sysctl_emul_mach_setup, "sysctl emul.mach subtree setup") +{ + + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "emul", NULL, + NULL, 0, NULL, 0, + CTL_EMUL, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "mach", + SYSCTL_DESCR("Mach emulation settings"), + NULL, 0, NULL, 0, + CTL_EMUL, EMUL_MACH, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "exception", + SYSCTL_DESCR("Mach exceptions settings"), + NULL, 0, NULL, 0, + CTL_EMUL, EMUL_MACH, + EMUL_MACH_EXCEPTION, CTL_EOL); + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "hang", + SYSCTL_DESCR("Mach exceptions hang the process"), + NULL, 0, &mach_exception_hang, 0, + CTL_EMUL, EMUL_MACH, EMUL_MACH_EXCEPTION, + EMUL_MACH_EXCEPTION_HANG, CTL_EOL); +} + diff --git a/sys/compat/mach/mach_sysctl.h b/sys/compat/mach/mach_sysctl.h new file mode 100644 index 0000000..6f6a422 --- /dev/null +++ b/sys/compat/mach/mach_sysctl.h @@ -0,0 +1,43 @@ +/* $NetBSD: mach_sysctl.h,v 1.3 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_SYSCTL_H_ +#define _MACH_SYSCTL_H_ + +extern int mach_exception_hang; + +#define EMUL_MACH_EXCEPTION 1 +#define EMUL_MACH_MAXID 2 + +#define EMUL_MACH_EXCEPTION_HANG 1 +#define EMUL_MACH_EXCEPTION_MAXID 2 + +#endif /* _MACH_SYSCTL_H_ */ diff --git a/sys/compat/mach/mach_sysent.c b/sys/compat/mach/mach_sysent.c new file mode 100644 index 0000000..fc925f6 --- /dev/null +++ b/sys/compat/mach/mach_sysent.c @@ -0,0 +1,289 @@ +/* $NetBSD: mach_sysent.c,v 1.23 2009/12/14 00:58:37 matt Exp $ */ + +/* + * System call switch table. + * + * DO NOT EDIT-- this file is automatically generated. + * created from NetBSD: syscalls.master,v 1.10 2009/01/13 22:27:43 pooka Exp + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_sysent.c,v 1.23 2009/12/14 00:58:37 matt Exp $"); + +#if defined(_KERNEL_OPT) +#include "opt_ntp.h" +#include "opt_sysv.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define s(type) sizeof(type) +#define n(type) (sizeof(type)/sizeof (register_t)) +#define ns(type) n(type), s(type) + +struct sysent mach_sysent[] = { + { 0, 0, 0, + sys_nosys }, /* 0 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 1 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 2 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 3 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 4 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 5 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 6 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 7 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 8 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 9 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 10 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 11 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 12 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 13 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 14 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 15 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 16 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 17 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 18 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 19 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 20 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 21 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 22 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 23 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 24 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 25 = unimplemented */ + { 0, 0, 0, + (sy_call_t *)mach_sys_reply_port }, /* 26 = reply_port */ + { 0, 0, 0, + (sy_call_t *)mach_sys_thread_self_trap },/* 27 = thread_self_trap */ + { 0, 0, 0, + (sy_call_t *)mach_sys_task_self_trap },/* 28 = task_self_trap */ + { 0, 0, 0, + (sy_call_t *)mach_sys_host_self_trap },/* 29 = host_self_trap */ + { 0, 0, 0, + sys_nosys }, /* 30 = unimplemented */ + { ns(struct mach_sys_msg_trap_args), 0, + (sy_call_t *)mach_sys_msg_trap }, /* 31 = msg_trap */ + { ns(struct mach_sys_msg_overwrite_trap_args), 0, + (sy_call_t *)mach_sys_msg_overwrite_trap },/* 32 = msg_overwrite_trap */ + { ns(struct mach_sys_semaphore_signal_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_signal_trap },/* 33 = semaphore_signal_trap */ + { ns(struct mach_sys_semaphore_signal_all_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_signal_all_trap },/* 34 = semaphore_signal_all_trap */ + { ns(struct mach_sys_semaphore_signal_thread_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_signal_thread_trap },/* 35 = semaphore_signal_thread_trap */ + { ns(struct mach_sys_semaphore_wait_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_wait_trap },/* 36 = semaphore_wait_trap */ + { ns(struct mach_sys_semaphore_wait_signal_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_wait_signal_trap },/* 37 = semaphore_wait_signal_trap */ + { ns(struct mach_sys_semaphore_timedwait_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_timedwait_trap },/* 38 = semaphore_timedwait_trap */ + { ns(struct mach_sys_semaphore_timedwait_signal_trap_args), 0, + (sy_call_t *)mach_sys_semaphore_timedwait_signal_trap },/* 39 = semaphore_timedwait_signal_trap */ + { 0, 0, 0, + sys_nosys }, /* 40 = unimplemented */ + { 0, 0, 0, + (sy_call_t *)mach_sys_init_process },/* 41 = init_process */ + { 0, 0, 0, + sys_nosys }, /* 42 = unimplemented */ + { ns(struct mach_sys_map_fd_args), 0, + (sy_call_t *)mach_sys_map_fd }, /* 43 = map_fd */ + { 0, 0, 0, + sys_nosys }, /* 44 = unimplemented */ + { ns(struct mach_sys_task_for_pid_args), 0, + (sy_call_t *)mach_sys_task_for_pid },/* 45 = task_for_pid */ + { ns(struct mach_sys_pid_for_task_args), 0, + (sy_call_t *)mach_sys_pid_for_task },/* 46 = pid_for_task */ + { 0, 0, 0, + sys_nosys }, /* 47 = unimplemented */ + { ns(struct mach_sys_macx_swapon_args), 0, + (sy_call_t *)mach_sys_macx_swapon },/* 48 = macx_swapon */ + { ns(struct mach_sys_macx_swapoff_args), 0, + (sy_call_t *)mach_sys_macx_swapoff },/* 49 = macx_swapoff */ + { 0, 0, 0, + sys_nosys }, /* 50 = unimplemented */ + { ns(struct mach_sys_macx_triggers_args), 0, + (sy_call_t *)mach_sys_macx_triggers },/* 51 = macx_triggers */ + { 0, 0, 0, + sys_nosys }, /* 52 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 53 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 54 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 55 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 56 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 57 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 58 = unimplemented */ + { ns(struct mach_sys_swtch_pri_args), 0, + (sy_call_t *)mach_sys_swtch_pri }, /* 59 = swtch_pri */ + { 0, 0, 0, + (sy_call_t *)mach_sys_swtch }, /* 60 = swtch */ + { ns(struct mach_sys_syscall_thread_switch_args), 0, + (sy_call_t *)mach_sys_syscall_thread_switch },/* 61 = syscall_thread_switch */ + { ns(struct mach_sys_clock_sleep_trap_args), 0, + (sy_call_t *)mach_sys_clock_sleep_trap },/* 62 = clock_sleep_trap */ + { 0, 0, 0, + sys_nosys }, /* 63 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 64 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 65 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 66 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 67 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 68 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 69 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 70 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 71 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 72 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 73 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 74 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 75 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 76 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 77 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 78 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 79 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 80 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 81 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 82 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 83 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 84 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 85 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 86 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 87 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 88 = unimplemented */ + { ns(struct mach_sys_timebase_info_args), 0, + (sy_call_t *)mach_sys_timebase_info },/* 89 = timebase_info */ + { ns(struct mach_sys_wait_until_args), 0, + (sy_call_t *)mach_sys_wait_until }, /* 90 = wait_until */ + { 0, 0, 0, + (sy_call_t *)mach_sys_timer_create },/* 91 = timer_create */ + { ns(struct mach_sys_timer_destroy_args), 0, + (sy_call_t *)mach_sys_timer_destroy },/* 92 = timer_destroy */ + { ns(struct mach_sys_timer_arm_args), 0, + (sy_call_t *)mach_sys_timer_arm }, /* 93 = timer_arm */ + { ns(struct mach_sys_timer_cancel_args), 0, + (sy_call_t *)mach_sys_timer_cancel },/* 94 = timer_cancel */ + { 0, 0, 0, + (sy_call_t *)mach_sys_get_time_base_info },/* 95 = get_time_base_info */ + { 0, 0, 0, + sys_nosys }, /* 96 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 97 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 98 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 99 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 100 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 101 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 102 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 103 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 104 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 105 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 106 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 107 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 108 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 109 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 110 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 111 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 112 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 113 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 114 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 115 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 116 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 117 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 118 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 119 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 120 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 121 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 122 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 123 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 124 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 125 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 126 = unimplemented */ + { 0, 0, 0, + sys_nosys }, /* 127 = unimplemented */ +}; diff --git a/sys/compat/mach/mach_task.c b/sys/compat/mach/mach_task.c new file mode 100644 index 0000000..d37c571 --- /dev/null +++ b/sys/compat/mach/mach_task.c @@ -0,0 +1,707 @@ +/* $NetBSD: mach_task.c,v 1.72 2010/07/01 02:38:29 rmind Exp $ */ + +/*- + * Copyright (c) 2002-2003, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_compat_darwin.h" + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.72 2010/07/01 02:38:29 rmind Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef COMPAT_DARWIN +#include +#endif + +#define ISSET(t, f) ((t) & (f)) + +static void +update_exception_port(struct mach_emuldata *, int exc, struct mach_port *); + +int +mach_task_get_special_port(struct mach_trap_args *args) +{ + mach_task_get_special_port_request_t *req = args->smsg; + mach_task_get_special_port_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + struct mach_emuldata *med; + struct mach_right *mr; + + med = (struct mach_emuldata *)tl->l_proc->p_emuldata; + + switch (req->req_which_port) { + case MACH_TASK_KERNEL_PORT: + mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0); + break; + + case MACH_TASK_HOST_PORT: + mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0); + break; + + case MACH_TASK_BOOTSTRAP_PORT: + mr = mach_right_get(med->med_bootstrap, + l, MACH_PORT_TYPE_SEND, 0); + break; + + case MACH_TASK_WIRED_LEDGER_PORT: + case MACH_TASK_PAGED_LEDGER_PORT: + default: + uprintf("mach_task_get_special_port(): unimpl. port %d\n", + req->req_which_port); + return mach_msg_error(args, EINVAL); + break; + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_ports_lookup(struct mach_trap_args *args) +{ + mach_ports_lookup_request_t *req = args->smsg; + mach_ports_lookup_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + struct mach_emuldata *med; + struct mach_right *mr; + mach_port_name_t mnp[7]; + void *uaddr; + int error; + int count; + + /* + * This is some out of band data sent with the reply. In the + * encountered situation, the out of band data has always been null + * filled. We have to see more of this in order to fully understand + * how this trap works. + */ + med = (struct mach_emuldata *)tl->l_proc->p_emuldata; + mnp[0] = (mach_port_name_t)MACH_PORT_DEAD; + mnp[3] = (mach_port_name_t)MACH_PORT_DEAD; + mnp[5] = (mach_port_name_t)MACH_PORT_DEAD; + mnp[6] = (mach_port_name_t)MACH_PORT_DEAD; + + mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0); + mnp[MACH_TASK_KERNEL_PORT] = mr->mr_name; + mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0); + mnp[MACH_TASK_HOST_PORT] = mr->mr_name; + mr = mach_right_get(med->med_bootstrap, l, MACH_PORT_TYPE_SEND, 0); + mnp[MACH_TASK_BOOTSTRAP_PORT] = mr->mr_name; + + /* + * On Darwin, the data seems always null... + */ + uaddr = NULL; + if ((error = mach_ool_copyout(l, &mnp[0], + &uaddr, sizeof(mnp), MACH_OOL_TRACE)) != 0) + return mach_msg_error(args, error); + + count = 3; /* XXX Shouldn't this be 7? */ + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_ool_ports_desc(rep, uaddr, count); + + rep->rep_init_port_set_count = count; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_set_special_port(struct mach_trap_args *args) +{ + mach_task_set_special_port_request_t *req = args->smsg; + mach_task_set_special_port_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + mach_port_t mn; + struct mach_right *mr; + struct mach_port *mp; + struct mach_emuldata *med; + + mn = req->req_special_port.name; + + /* Null port ? */ + if (mn == 0) + return mach_msg_error(args, 0); + + /* Does the inserted port exists? */ + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0) + return mach_msg_error(args, EPERM); + + if (mr->mr_type == MACH_PORT_TYPE_DEAD_NAME) + return mach_msg_error(args, EINVAL); + + med = (struct mach_emuldata *)tl->l_proc->p_emuldata; + + switch (req->req_which_port) { + case MACH_TASK_KERNEL_PORT: + mp = med->med_kernel; + med->med_kernel = mr->mr_port; + if (mr->mr_port != NULL) + MACH_PORT_REF(mr->mr_port); + MACH_PORT_UNREF(mp); + break; + + case MACH_TASK_HOST_PORT: + mp = med->med_host; + med->med_host = mr->mr_port; + if (mr->mr_port != NULL) + MACH_PORT_REF(mr->mr_port); + MACH_PORT_UNREF(mp); + break; + + case MACH_TASK_BOOTSTRAP_PORT: + mp = med->med_bootstrap; + med->med_bootstrap = mr->mr_port; + if (mr->mr_port != NULL) + MACH_PORT_REF(mr->mr_port); + MACH_PORT_UNREF(mp); +#ifdef COMPAT_DARWIN + /* + * mach_init sets the bootstrap port for any new process. + */ + { + struct darwin_emuldata *ded; + + ded = tl->l_proc->p_emuldata; + if (ded->ded_fakepid == 1) { + mach_bootstrap_port = med->med_bootstrap; +#ifdef DEBUG_DARWIN + printf("*** New bootstrap port %p, " + "recv %p [%p]\n", + mach_bootstrap_port, + mach_bootstrap_port->mp_recv, + mach_bootstrap_port->mp_recv->mr_sethead); +#endif /* DEBUG_DARWIN */ + } + } +#endif /* COMPAT_DARWIN */ + break; + + default: + uprintf("mach_task_set_special_port: unimplemented port %d\n", + req->req_which_port); + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_threads(struct mach_trap_args *args) +{ + mach_task_threads_request_t *req = args->smsg; + mach_task_threads_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + struct proc *tp = tl->l_proc; + struct lwp *cl; + struct mach_emuldata *med; + struct mach_lwp_emuldata *mle; + int error; + void *uaddr; + size_t size; + int i = 0; + struct mach_right *mr; + mach_port_name_t *mnp; + + med = tp->p_emuldata; + size = tp->p_nlwps * sizeof(*mnp); + mnp = malloc(size, M_TEMP, M_WAITOK); + uaddr = NULL; + + LIST_FOREACH(cl, &tp->p_lwps, l_sibling) { + mle = cl->l_emuldata; + mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0); + mnp[i++] = mr->mr_name; + } + + /* This will free mnp */ + if ((error = mach_ool_copyout(l, mnp, &uaddr, + size, MACH_OOL_TRACE|MACH_OOL_FREE)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_ool_ports_desc(rep, uaddr, tp->p_nlwps); + + rep->rep_count = tp->p_nlwps; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_get_exception_ports(struct mach_trap_args *args) +{ + mach_task_get_exception_ports_request_t *req = args->smsg; + mach_task_get_exception_ports_reply_t *rep = args->rmsg; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + size_t *msglen = args->rsize; + struct mach_emuldata *med; + struct mach_right *mr; + struct mach_exc_info *mei; + int i, j, count; + + med = tl->l_proc->p_emuldata; + + /* It always returns an array of 32 ports even if only 9 can be used */ + count = sizeof(rep->rep_old_handler) / sizeof(rep->rep_old_handler[0]); + + mach_set_header(rep, req, *msglen); + + rep->rep_masks_count = count; + + j = 0; + for (i = 0; i <= MACH_EXC_MAX; i++) { + if (med->med_exc[i] == NULL) + continue; + + if (med->med_exc[i]->mp_datatype != MACH_MP_EXC_INFO) { +#ifdef DIAGNOSTIC + printf("Exception port without mach_exc_info\n"); +#endif + continue; + } + mei = med->med_exc[i]->mp_data; + + mr = mach_right_get(med->med_exc[i], l, MACH_PORT_TYPE_SEND, 0); + + mach_add_port_desc(rep, mr->mr_name); + + rep->rep_masks[j] = 1 << i; + rep->rep_old_behaviors[j] = mei->mei_behavior; + rep->rep_old_flavors[j] = mei->mei_flavor; + + j++; + } + + *msglen = sizeof(*rep); + mach_set_trailer(rep, *msglen); + + return 0; +} + +static void +update_exception_port(struct mach_emuldata *med, int exc, struct mach_port *mp) +{ + if (med->med_exc[exc] != NULL) + MACH_PORT_UNREF(med->med_exc[exc]); + med->med_exc[exc] = mp; + MACH_PORT_REF(mp); + + return; +} + +int +mach_task_set_exception_ports(struct mach_trap_args *args) +{ + mach_task_set_exception_ports_request_t *req = args->smsg; + mach_task_set_exception_ports_reply_t *rep = args->rmsg; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + size_t *msglen = args->rsize; + struct mach_emuldata *med; + mach_port_name_t mn; + struct mach_right *mr; + struct mach_port *mp; + struct mach_exc_info *mei; + + mn = req->req_new_port.name; + if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_SEND)) == 0) + return mach_msg_error(args, EPERM); + + mp = mr->mr_port; +#ifdef DIAGNOSTIC + if ((mp->mp_datatype != MACH_MP_EXC_INFO) && + (mp->mp_datatype != MACH_MP_NONE)) + printf("mach_task_set_exception_ports: data exists\n"); +#endif + mei = malloc(sizeof(*mei), M_EMULDATA, M_WAITOK); + mei->mei_flavor = req->req_flavor; + mei->mei_behavior = req->req_behavior; + + mp->mp_data = mei; + mp->mp_flags |= MACH_MP_DATA_ALLOCATED; + mp->mp_datatype = MACH_MP_EXC_INFO; + + med = tl->l_proc->p_emuldata; + if (req->req_mask & MACH_EXC_MASK_BAD_ACCESS) + update_exception_port(med, MACH_EXC_BAD_ACCESS, mp); + if (req->req_mask & MACH_EXC_MASK_BAD_INSTRUCTION) + update_exception_port(med, MACH_EXC_BAD_INSTRUCTION, mp); + if (req->req_mask & MACH_EXC_MASK_ARITHMETIC) + update_exception_port(med, MACH_EXC_ARITHMETIC, mp); + if (req->req_mask & MACH_EXC_MASK_EMULATION) + update_exception_port(med, MACH_EXC_EMULATION, mp); + if (req->req_mask & MACH_EXC_MASK_SOFTWARE) + update_exception_port(med, MACH_EXC_SOFTWARE, mp); + if (req->req_mask & MACH_EXC_MASK_BREAKPOINT) + update_exception_port(med, MACH_EXC_BREAKPOINT, mp); + if (req->req_mask & MACH_EXC_MASK_SYSCALL) + update_exception_port(med, MACH_EXC_SYSCALL, mp); + if (req->req_mask & MACH_EXC_MASK_MACH_SYSCALL) + update_exception_port(med, MACH_EXC_MACH_SYSCALL, mp); + if (req->req_mask & MACH_EXC_MASK_RPC_ALERT) + update_exception_port(med, MACH_EXC_RPC_ALERT, mp); + +#ifdef DEBUG_MACH + if (req->req_mask & (MACH_EXC_ARITHMETIC | + MACH_EXC_EMULATION | MACH_EXC_MASK_SYSCALL | + MACH_EXC_MASK_MACH_SYSCALL | MACH_EXC_RPC_ALERT)) + printf("mach_set_exception_ports: some exceptions are " + "not supported (mask %x)\n", req->req_mask); +#endif + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_info(struct mach_trap_args *args) +{ + mach_task_info_request_t *req = args->smsg; + mach_task_info_reply_t *rep = args->rmsg; + struct lwp *tl = args->tl; + size_t *msglen = args->rsize; + int count; + struct proc *tp = tl->l_proc; + + switch(req->req_flavor) { + case MACH_TASK_BASIC_INFO: { + struct mach_task_basic_info *mtbi; + struct rusage ru; + + count = sizeof(*mtbi) / sizeof(rep->rep_info[0]); + if (req->req_count < count) + return mach_msg_error(args, ENOBUFS); + + ru = tp->p_stats->p_ru; + mtbi = (struct mach_task_basic_info *)&rep->rep_info[0]; + mutex_enter(tp->p_lock); + rulwps(tp, &ru); + mutex_exit(tp->p_lock); + + mtbi->mtbi_suspend_count = ru.ru_nvcsw + ru.ru_nivcsw; + mtbi->mtbi_virtual_size = ru.ru_ixrss; + mtbi->mtbi_resident_size = ru.ru_maxrss; + mtbi->mtbi_user_time.seconds = ru.ru_utime.tv_sec; + mtbi->mtbi_user_time.microseconds = ru.ru_utime.tv_usec; + mtbi->mtbi_system_time.seconds = ru.ru_stime.tv_sec; + mtbi->mtbi_system_time.microseconds = ru.ru_stime.tv_usec; + mtbi->mtbi_policy = 0; + + *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mtbi); + break; + } + + /* XXX this is supposed to be about threads, not processes... */ + case MACH_TASK_THREAD_TIMES_INFO: { + struct mach_task_thread_times_info *mttti; + struct rusage ru; + + count = sizeof(*mttti) / sizeof(rep->rep_info[0]); + if (req->req_count < count) + return mach_msg_error(args, ENOBUFS); + + ru = tp->p_stats->p_ru; + mttti = (struct mach_task_thread_times_info *)&rep->rep_info[0]; + + mttti->mttti_user_time.seconds = ru.ru_utime.tv_sec; + mttti->mttti_user_time.microseconds = ru.ru_utime.tv_usec; + mttti->mttti_system_time.seconds = ru.ru_stime.tv_sec; + mttti->mttti_system_time.microseconds = ru.ru_stime.tv_usec; + + *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mttti); + break; + } + + /* XXX a few statistics missing here */ + case MACH_TASK_EVENTS_INFO: { + struct mach_task_events_info *mtei; + struct rusage ru; + + count = sizeof(*mtei) / sizeof(rep->rep_info[0]); + if (req->req_count < count) + return mach_msg_error(args, ENOBUFS); + + mtei = (struct mach_task_events_info *)&rep->rep_info[0]; + ru = tp->p_stats->p_ru; + mutex_enter(tp->p_lock); + rulwps(tp, &ru); + mutex_exit(tp->p_lock); + + mtei->mtei_faults = ru.ru_majflt; + mtei->mtei_pageins = ru.ru_minflt; + mtei->mtei_cow_faults = 0; /* XXX */ + mtei->mtei_message_sent = ru.ru_msgsnd; + mtei->mtei_message_received = ru.ru_msgrcv; + mtei->mtei_syscalls_mach = 0; /* XXX */ + mtei->mtei_syscalls_unix = 0; /* XXX */ + mtei->mtei_csw = 0; /* XXX */ + + *msglen = sizeof(*rep) - sizeof(rep->rep_info) + sizeof(*mtei); + break; + } + + default: + uprintf("mach_task_info: unsupported flavor %d\n", + req->req_flavor); + return mach_msg_error(args, EINVAL); + }; + + mach_set_header(rep, req, *msglen); + + rep->rep_count = count; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_suspend(struct mach_trap_args *args) +{ + mach_task_suspend_request_t *req = args->smsg; + mach_task_suspend_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct lwp *lp; + struct mach_emuldata *med; + struct proc *tp = tl->l_proc; + + med = tp->p_emuldata; + med->med_suspend++; /* XXX Mach also has a per thread semaphore */ + + LIST_FOREACH(lp, &tp->p_lwps, l_sibling) { + switch(lp->l_stat) { + case LSONPROC: + case LSRUN: + case LSSLEEP: + case LSSUSPENDED: + case LSZOMB: + break; + default: + return mach_msg_error(args, 0); + break; + } + } + mutex_enter(proc_lock); + mutex_enter(tp->p_lock); + proc_stop(tp, 0, SIGSTOP); + mutex_enter(tp->p_lock); + mutex_enter(proc_lock); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_resume(struct mach_trap_args *args) +{ + mach_task_resume_request_t *req = args->smsg; + mach_task_resume_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct mach_emuldata *med; + struct proc *tp = tl->l_proc; + + med = tp->p_emuldata; + med->med_suspend--; /* XXX Mach also has a per thread semaphore */ +#if 0 + if (med->med_suspend > 0) + return mach_msg_error(args, 0); /* XXX error code */ +#endif + + /* XXX We should also wake up the stopped thread... */ +#ifdef DEBUG_MACH + printf("resuming pid %d\n", tp->p_pid); +#endif + mutex_enter(proc_lock); + mutex_enter(tp->p_lock); + (void)proc_unstop(tp); + mutex_enter(tp->p_lock); + mutex_enter(proc_lock); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_task_terminate(struct mach_trap_args *args) +{ + mach_task_resume_request_t *req = args->smsg; + mach_task_resume_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct sys_exit_args cup; + register_t retval; + int error; + + + SCARG(&cup, rval) = 0; + error = sys_exit(tl, &cup, &retval); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = native_to_mach_errno[error]; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_sys_task_for_pid(struct lwp *l, const struct mach_sys_task_for_pid_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_t) target_tport; + syscallarg(int) pid; + syscallarg(mach_port_t) *t; + } */ + struct mach_right *mr; + struct mach_emuldata *med; + struct proc *t; + int error; + + /* + * target_tport is used because the task may be on + * a different host. (target_tport, pid) is unique. + * We don't support multiple-host configuration + * yet, so this parameter should be useless. + * However, we still validate it. + */ + if ((mr = mach_right_check(SCARG(uap, target_tport), + l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return EPERM; + + mutex_enter(proc_lock); + if ((t = proc_find(SCARG(uap, pid))) == NULL) { + mutex_exit(proc_lock); + return ESRCH; + } + mutex_enter(t->p_lock); + mutex_exit(proc_lock); + + /* Allowed only if the UID match, if setuid, or if superuser */ + if ((kauth_cred_getuid(t->p_cred) != kauth_cred_getuid(l->l_cred) || + ISSET(t->p_flag, PK_SUGID)) && (error = kauth_authorize_generic(l->l_cred, + KAUTH_GENERIC_ISSUSER, NULL)) != 0) { + mutex_exit(t->p_lock); + return (error); + } + + /* This will only work on a Mach process */ + if ((t->p_emul != &emul_mach) && +#ifdef COMPAT_DARWIN + (t->p_emul != &emul_darwin) && +#endif + 1) { + mutex_exit(t->p_lock); + return EINVAL; + } + mutex_exit(t->p_lock); + + /* XXX: Unlocked, broken. */ + med = t->p_emuldata; + mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0); + if (mr) { + error = copyout(&mr->mr_name, SCARG(uap, t), + sizeof(mr->mr_name)); + } else { + error = EINVAL; + } + + return error; +} + diff --git a/sys/compat/mach/mach_task.h b/sys/compat/mach/mach_task.h new file mode 100644 index 0000000..e0ea1f8 --- /dev/null +++ b/sys/compat/mach/mach_task.h @@ -0,0 +1,227 @@ +/* $NetBSD: mach_task.h,v 1.16 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_TASK_H_ +#define _MACH_TASK_H_ + +/* task_get_special_port */ + +#define MACH_TASK_KERNEL_PORT 1 +#define MACH_TASK_HOST_PORT 2 +#define MACH_TASK_BOOTSTRAP_PORT 4 +#define MACH_TASK_WIRED_LEDGER_PORT 5 +#define MACH_TASK_PAGED_LEDGER_PORT 6 + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + int req_which_port; +} mach_task_get_special_port_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_msgh_body; + mach_msg_port_descriptor_t rep_special_port; + mach_msg_trailer_t rep_trailer; +} mach_task_get_special_port_reply_t; + +/* mach_ports_lookup */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_ports_lookup_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_msgh_body; + mach_msg_ool_ports_descriptor_t rep_init_port_set; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_init_port_set_count; + mach_msg_trailer_t rep_trailer; +} mach_ports_lookup_reply_t; + +/* mach_set_special_port */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_msgh_body; + mach_msg_port_descriptor_t req_special_port; + mach_ndr_record_t req_ndr; + int req_which_port; +} mach_task_set_special_port_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_task_set_special_port_reply_t; + +/* task_threads */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_task_threads_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_ool_ports_descriptor_t rep_list; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_count; + mach_msg_trailer_t rep_trailer; +} mach_task_threads_reply_t; + +/* task_get_exception_ports */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_exception_mask_t req_mask; +} mach_task_get_exception_ports_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_old_handler[32]; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_masks_count; + mach_exception_mask_t rep_masks[32]; + mach_exception_behavior_t rep_old_behaviors[32]; + mach_thread_state_flavor_t rep_old_flavors[32]; + mach_msg_trailer_t rep_trailer; +} mach_task_get_exception_ports_reply_t; + +/* task_set_exception_ports */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_new_port; + mach_ndr_record_t req_ndr; + mach_exception_mask_t req_mask; + mach_exception_behavior_t req_behavior; + mach_thread_state_flavor_t req_flavor; +} mach_task_set_exception_ports_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_task_set_exception_ports_reply_t; + +/* task_info */ + +#define MACH_TASK_BASIC_INFO 4 +struct mach_task_basic_info { + mach_integer_t mtbi_suspend_count; + mach_vm_size_t mtbi_virtual_size; + mach_vm_size_t mtbi_resident_size; + mach_time_value_t mtbi_user_time; + mach_time_value_t mtbi_system_time; + mach_policy_t mtbi_policy; +}; + +#define MACH_TASK_EVENTS_INFO 2 +struct mach_task_events_info { + mach_integer_t mtei_faults; + mach_integer_t mtei_pageins; + mach_integer_t mtei_cow_faults; + mach_integer_t mtei_message_sent; + mach_integer_t mtei_message_received; + mach_integer_t mtei_syscalls_mach; + mach_integer_t mtei_syscalls_unix; + mach_integer_t mtei_csw; +}; + +#define MACH_TASK_THREAD_TIMES_INFO 3 +struct mach_task_thread_times_info { + mach_time_value_t mttti_user_time; + mach_time_value_t mttti_system_time; +}; + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_task_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_task_info_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_count; + mach_integer_t rep_info[8]; + mach_msg_trailer_t rep_trailer; +} mach_task_info_reply_t; + +/* task_suspend */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_task_suspend_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_task_suspend_reply_t; + +/* task_resume */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_task_resume_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_task_resume_reply_t; + +/* task_terminate */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_task_terminate_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_task_terminate_reply_t; + +#endif /* _MACH_TASK_H_ */ diff --git a/sys/compat/mach/mach_thread.c b/sys/compat/mach/mach_thread.c new file mode 100644 index 0000000..a5abd61 --- /dev/null +++ b/sys/compat/mach/mach_thread.c @@ -0,0 +1,486 @@ +/* $NetBSD: mach_thread.c,v 1.50 2010/06/13 04:13:31 yamt Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_thread.c,v 1.50 2010/06/13 04:13:31 yamt Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +mach_sys_syscall_thread_switch(struct lwp *l, const struct mach_sys_syscall_thread_switch_args *uap, register_t *retval) +{ + /* { + syscallarg(mach_port_name_t) thread_name; + syscallarg(int) option; + syscallarg(mach_msg_timeout_t) option_time; + } */ + int timeout; + struct mach_emuldata *med; + + med = (struct mach_emuldata *)l->l_proc->p_emuldata; + timeout = SCARG(uap, option_time) * hz / 1000; + + /* + * The day we will be able to find out the struct proc from + * the port number, try to use preempt() to call the right thread. + * [- but preempt() is for _involuntary_ context switches.] + */ + switch(SCARG(uap, option)) { + case MACH_SWITCH_OPTION_NONE: + yield(); + break; + + case MACH_SWITCH_OPTION_WAIT: + med->med_thpri = 1; + while (med->med_thpri != 0) + (void)tsleep(&med->med_thpri, PZERO|PCATCH, + "thread_switch", timeout); + break; + + case MACH_SWITCH_OPTION_DEPRESS: + case MACH_SWITCH_OPTION_IDLE: + /* Use a callout to restore the priority after depression? */ + med->med_thpri = l->l_priority; + l->l_priority = MAXPRI; + break; + + default: + uprintf("mach_sys_syscall_thread_switch(): unknown option %d\n", SCARG(uap, option)); + break; + } + return 0; +} + +int +mach_sys_swtch_pri(struct lwp *l, const struct mach_sys_swtch_pri_args *uap, register_t *retval) +{ + /* { + syscallarg(int) pri; + } */ + + /* + * Copied from preempt(9). We cannot just call preempt + * because we want to return mi_switch(9) return value. + */ + KERNEL_UNLOCK_ALL(l, &l->l_biglocks); + lwp_lock(l); + if (l->l_stat == LSONPROC) + l->l_proc->p_stats->p_ru.ru_nivcsw++; /* XXXSMP */ + *retval = mi_switch(l); + KERNEL_LOCK(l->l_biglocks, l); + + return 0; +} + +int +mach_sys_swtch(struct lwp *l, const void *v, register_t *retval) +{ + struct mach_sys_swtch_pri_args cup; + + SCARG(&cup, pri) = 0; + + return mach_sys_swtch_pri(l, &cup, retval); +} + + +int +mach_thread_policy(struct mach_trap_args *args) +{ + mach_thread_policy_request_t *req = args->smsg; + mach_thread_policy_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + int end_offset; + + /* Sanity check req_count */ + end_offset = req->req_count + + (sizeof(req->req_setlimit) / sizeof(req->req_base[0])); + if (MACH_REQMSG_OVERFLOW(args, req->req_base[end_offset])) + return mach_msg_error(args, EINVAL); + + uprintf("Unimplemented mach_thread_policy\n"); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +/* XXX it might be possible to use this on another task */ +int +mach_thread_create_running(struct mach_trap_args *args) +{ + mach_thread_create_running_request_t *req = args->smsg; + mach_thread_create_running_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct proc *p = l->l_proc; + struct mach_create_thread_child_args mctc; + struct mach_right *child_mr; + struct mach_lwp_emuldata *mle; + vaddr_t uaddr; + int flags; + int error; + int end_offset; + + /* Sanity check req_count */ + end_offset = req->req_count; + if (MACH_REQMSG_OVERFLOW(args, req->req_state[end_offset])) + return mach_msg_error(args, EINVAL); + + /* + * Prepare the data we want to transmit to the child. + */ + mctc.mctc_flavor = req->req_flavor; + mctc.mctc_oldlwp = l; + mctc.mctc_child_done = 0; + mctc.mctc_state = req->req_state; + + uaddr = uvm_uarea_alloc(); + if (__predict_false(uaddr == 0)) + return ENOMEM; + + flags = 0; + if ((error = lwp_create(l, p, uaddr, flags, NULL, 0, + mach_create_thread_child, (void *)&mctc, &mctc.mctc_lwp, + SCHED_OTHER)) != 0) + { + uvm_uarea_free(uaddr); + return mach_msg_error(args, error); + } + + /* + * Make the child runnable. + */ + mutex_enter(p->p_lock); + lwp_lock(mctc.mctc_lwp); + mctc.mctc_lwp->l_private = 0; + mctc.mctc_lwp->l_stat = LSRUN; + sched_enqueue(mctc.mctc_lwp, false); + lwp_unlock(mctc.mctc_lwp); + mutex_exit(p->p_lock); + + /* + * Get the child's kernel port + */ + mle = mctc.mctc_lwp->l_emuldata; + child_mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0); + + /* + * The child relies on some values in mctc, so we should not + * exit until it is finished with it. We catch signals so that + * the process can be killed with kill -9, but we loop to avoid + * spurious wakeups due to other signals. + */ + while(mctc.mctc_child_done == 0) + (void)tsleep(&mctc.mctc_child_done, + PZERO|PCATCH, "mach_thread", 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, child_mr->mr_name); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_info(struct mach_trap_args *args) +{ + mach_thread_info_request_t *req = args->smsg; + mach_thread_info_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + struct proc *tp = tl->l_proc; + + /* Sanity check req->req_count */ + if (req->req_count > 12) + return mach_msg_error(args, EINVAL); + + rep->rep_count = req->req_count; + + *msglen = sizeof(*rep) + ((req->req_count - 12) * sizeof(int)); + mach_set_header(rep, req, *msglen); + + switch (req->req_flavor) { + case MACH_THREAD_BASIC_INFO: { + struct mach_thread_basic_info *tbi; + + if (req->req_count != (sizeof(*tbi) / sizeof(int))) /* 10 */ + return mach_msg_error(args, EINVAL); + + tbi = (struct mach_thread_basic_info *)rep->rep_out; + tbi->user_time.seconds = tp->p_uticks * hz / 1000000; + tbi->user_time.microseconds = + (tp->p_uticks) * hz - tbi->user_time.seconds; + tbi->system_time.seconds = tp->p_sticks * hz / 1000000; + tbi->system_time.microseconds = + (tp->p_sticks) * hz - tbi->system_time.seconds; + tbi->cpu_usage = tp->p_pctcpu; + tbi->policy = MACH_THREAD_STANDARD_POLICY; + + /* XXX this is not very accurate */ + tbi->run_state = MACH_TH_STATE_RUNNING; + tbi->flags = 0; + switch (l->l_stat) { + case LSRUN: + tbi->run_state = MACH_TH_STATE_RUNNING; + break; + case LSSTOP: + tbi->run_state = MACH_TH_STATE_STOPPED; + break; + case LSSLEEP: + tbi->run_state = MACH_TH_STATE_WAITING; + break; + case LSIDL: + tbi->run_state = MACH_TH_STATE_RUNNING; + tbi->flags = MACH_TH_FLAGS_IDLE; + break; + default: + break; + } + + tbi->suspend_count = 0; + tbi->sleep_time = tl->l_slptime; + break; + } + + case MACH_THREAD_SCHED_TIMESHARE_INFO: { + struct mach_policy_timeshare_info *pti; + + if (req->req_count != (sizeof(*pti) / sizeof(int))) /* 5 */ + return mach_msg_error(args, EINVAL); + + pti = (struct mach_policy_timeshare_info *)rep->rep_out; + + pti->max_priority = tl->l_priority; + pti->base_priority = tl->l_priority; + pti->cur_priority = tl->l_priority; + pti->depressed = 0; + pti->depress_priority = tl->l_priority; + break; + } + + case MACH_THREAD_SCHED_RR_INFO: + case MACH_THREAD_SCHED_FIFO_INFO: + uprintf("Unimplemented thread_info flavor %d\n", + req->req_flavor); + default: + return mach_msg_error(args, EINVAL); + break; + } + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_get_state(struct mach_trap_args *args) +{ + mach_thread_get_state_request_t *req = args->smsg; + mach_thread_get_state_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + int error; + int size; + + /* Sanity check req->req_count */ + if (req->req_count > 144) + return mach_msg_error(args, EINVAL); + + if ((error = mach_thread_get_state_machdep(tl, + req->req_flavor, &rep->rep_state, &size)) != 0) + return mach_msg_error(args, error); + + rep->rep_count = size / sizeof(int); + *msglen = sizeof(*rep) + ((req->req_count - 144) * sizeof(int)); + mach_set_header(rep, req, *msglen); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_set_state(struct mach_trap_args *args) +{ + mach_thread_set_state_request_t *req = args->smsg; + mach_thread_set_state_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + int error; + int end_offset; + + /* Sanity check req_count */ + end_offset = req->req_count; + if (MACH_REQMSG_OVERFLOW(args, req->req_state[end_offset])) + return mach_msg_error(args, EINVAL); + + if ((error = mach_thread_set_state_machdep(tl, + req->req_flavor, &req->req_state)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_suspend(struct mach_trap_args *args) +{ + mach_thread_suspend_request_t *req = args->smsg; + mach_thread_suspend_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + struct proc *p = tl->l_proc; + int error; + + mutex_enter(p->p_lock); + lwp_lock(tl); + error = lwp_suspend(l, tl); + mutex_exit(p->p_lock); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + rep->rep_retval = native_to_mach_errno[error]; + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_resume(struct mach_trap_args *args) +{ + mach_thread_resume_request_t *req = args->smsg; + mach_thread_resume_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct proc *p = tl->l_proc; + + mutex_enter(p->p_lock); + lwp_lock(tl); + lwp_continue(tl); + mutex_exit(p->p_lock); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + rep->rep_retval = 0; + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_abort(struct mach_trap_args *args) +{ + mach_thread_abort_request_t *req = args->smsg; + mach_thread_abort_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + + lwp_exit(tl); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + rep->rep_retval = 0; + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_thread_set_policy(struct mach_trap_args *args) +{ + mach_thread_set_policy_request_t *req = args->smsg; + mach_thread_set_policy_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + mach_port_t mn; + struct mach_right *mr; + int limit_count_offset, limit_offset; + int limit_count; + int *limit; + + limit_count_offset = req->req_base_count; + if (MACH_REQMSG_OVERFLOW(args, req->req_base[limit_count_offset])) + return mach_msg_error(args, EINVAL); + + limit_count = req->req_base[limit_count_offset]; + limit_offset = limit_count_offset + + (sizeof(req->req_limit_count) / sizeof(req->req_base[0])); + limit = &req->req_base[limit_offset]; + if (MACH_REQMSG_OVERFLOW(args, limit[limit_count])) + return mach_msg_error(args, EINVAL); + + mn = req->req_pset.name; + if ((mr = mach_right_check(mn, tl, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL) + return mach_msg_error(args, EINVAL); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + rep->rep_retval = 0; + mach_set_trailer(rep, *msglen); + + return 0; +} + diff --git a/sys/compat/mach/mach_thread.h b/sys/compat/mach/mach_thread.h new file mode 100644 index 0000000..9a10ebb --- /dev/null +++ b/sys/compat/mach/mach_thread.h @@ -0,0 +1,249 @@ +/* $NetBSD: mach_thread.h,v 1.19 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_THREAD_H_ +#define _MACH_THREAD_H_ + +#include +#include +#include +#include + +#include +#include + +/* For mach_create_thread_child() */ +struct mach_create_thread_child_args { + struct lwp *mctc_lwp; + struct lwp *mctc_oldlwp; + mach_natural_t *mctc_state; + int mctc_flavor; + int mctc_child_done; +}; + +/* For mach_sys_syscall_thread_switch() */ +#define MACH_SWITCH_OPTION_NONE 0 +#define MACH_SWITCH_OPTION_DEPRESS 1 +#define MACH_SWITCH_OPTION_WAIT 2 +#define MACH_SWITCH_OPTION_IDLE 3 + +/* For mach_thread_info */ +#define MACH_THREAD_BASIC_INFO 3 +struct mach_thread_basic_info { + mach_time_value_t user_time; + mach_time_value_t system_time; + mach_integer_t cpu_usage; + mach_policy_t policy; + mach_integer_t run_state; + mach_integer_t flags; + mach_integer_t suspend_count; + mach_integer_t sleep_time; +}; +#define MACH_TH_STATE_RUNNING 1 +#define MACH_TH_STATE_STOPPED 2 +#define MACH_TH_STATE_WAITING 3 +#define MACH_TH_STATE_UNINTERRUPTIBLE 4 +#define MACH_TH_STATE_HALTED 5 + +#define MACH_TH_FLAGS_SWAPPED 1 +#define MACH_TH_FLAGS_IDLE 2 + +#define MACH_THREAD_SCHED_TIMESHARE_INFO 10 +struct mach_policy_timeshare_info { + mach_integer_t max_priority; + mach_integer_t base_priority; + mach_integer_t cur_priority; + mach_boolean_t depressed; + mach_integer_t depress_priority; +}; + +#define MACH_THREAD_SCHED_RR_INFO 11 +#define MACH_THREAD_SCHED_FIFO_INFO 12 + +/* For mach_policy_t */ +#define MACH_THREAD_STANDARD_POLICY 1 +#define MACH_THREAD_TIME_CONSTRAINT_POLICY 2 +#define MACH_THREAD_PRECEDENCE_POLICY 3 + +/* thread_policy */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_policy_t req_policy; + mach_msg_type_number_t req_count; + mach_integer_t req_base[0]; + mach_boolean_t req_setlimit; +} mach_thread_policy_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_thread_policy_reply_t; + +/* mach_thread_create_running */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_thread_state_flavor_t req_flavor; + mach_msg_type_number_t req_count; + mach_natural_t req_state[0]; +} mach_thread_create_running_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_child_act; + mach_msg_trailer_t rep_trailer; +} mach_thread_create_running_reply_t; + +/* mach_thread_info */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_thread_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_thread_info_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_count; + mach_integer_t rep_out[12]; + mach_msg_trailer_t rep_trailer; +} mach_thread_info_reply_t; + +/* thread_get_state */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_thread_state_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_thread_get_state_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_type_number_t rep_count; + mach_integer_t rep_state[144]; + mach_msg_trailer_t rep_trailer; +} mach_thread_get_state_reply_t; + +/* mach_thread_set_state */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_thread_state_flavor_t req_flavor; + mach_msg_type_number_t req_count; + mach_integer_t req_state[0]; +} mach_thread_set_state_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_thread_set_state_reply_t; + +/* thread_suspend */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_thread_suspend_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_thread_suspend_reply_t; + +/* thread_resume */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_thread_resume_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_thread_resume_reply_t; + +/* thread_abort */ + +typedef struct { + mach_msg_header_t req_msgh; +} mach_thread_abort_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_thread_abort_reply_t; + +/* thread_set_policy */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_pset; + mach_ndr_record_t req_ndr; + mach_policy_t req_policy; + mach_msg_type_number_t req_base_count; + mach_integer_t req_base[0]; + mach_msg_type_number_t req_limit_count; + mach_integer_t req_limit[0]; +} mach_thread_set_policy_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_thread_set_policy_reply_t; + +/* These are machine dependent functions */ +int mach_thread_get_state_machdep(struct lwp *, int, void *, int *); +int mach_thread_set_state_machdep(struct lwp *, int, void *); +void mach_create_thread_child(void *); + +#endif /* _MACH_THREAD_H_ */ diff --git a/sys/compat/mach/mach_types.h b/sys/compat/mach/mach_types.h new file mode 100644 index 0000000..7a2617b --- /dev/null +++ b/sys/compat/mach/mach_types.h @@ -0,0 +1,113 @@ +/* $NetBSD: mach_types.h,v 1.24 2008/04/28 20:23:44 martin Exp $ */ + +/*- + * Copyright (c) 2001-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas and Emmanuel Dreyfus. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_TYPES_H_ +#define _MACH_TYPES_H_ + +typedef int mach_port_t; +typedef int mach_port_name_t; +typedef int mach_port_type_t; +typedef register_t mach_kern_return_t; +typedef int mach_clock_res_t; +typedef int mach_clock_id_t; +typedef int mach_boolean_t; +typedef int mach_sleep_type_t; +typedef int mach_absolute_time_t; +typedef int mach_integer_t; +typedef int mach_cpu_type_t; +typedef int mach_cpu_subtype_t; +typedef int mach_port_right_t; +typedef register_t mach_vm_address_t; +typedef int mach_vm_inherit_t; +typedef int mach_vm_prot_t; +typedef int mach_thread_state_flavor_t; +typedef unsigned int mach_natural_t; +typedef unsigned long mach_vm_size_t; +typedef uint64_t mach_memory_object_size_t; +typedef unsigned long mach_vm_offset_t; +typedef uint64_t mach_memory_object_offset_t; +typedef int mach_vm_region_flavor_t; +typedef int mach_vm_behavior_t; +typedef int mach_vm_sync_t; +typedef int mach_exception_type_t; +typedef int mach_exception_behavior_t; +typedef unsigned int mach_exception_mask_t; +typedef int mach_port_flavor_t; +typedef mach_natural_t mach_port_seqno_t; +typedef mach_natural_t mach_port_mscount_t; +typedef mach_natural_t mach_port_msgcount_t; +typedef mach_natural_t mach_port_rights_t; +typedef mach_natural_t mach_task_flavor_t; +typedef mach_natural_t mach_thread_flavor_t; +typedef int mach_policy_t; +typedef int mach_vm_machine_attribute_val_t; +typedef unsigned int mach_vm_machine_attribute_t; +typedef mach_natural_t mach_port_urefs_t; +typedef int mach_port_delta_t; + + +/* + * This is called cproc_t in Mach (cthread_t in Darwin). It is a pointer to + * a struct cproc (struct cthread in Darwin), which is stored in userland and + * seems to be opaque to the kernel. The kernel just has to store and restore + * it with cthread_self() (pthread_self() in Darwin) and _cthread_set_self() + * (_pthread_set_self() in Darwin). + */ +typedef void *mach_cproc_t; + +typedef struct mach_timebase_info { + u_int32_t numer; + u_int32_t denom; +} *mach_timebase_info_t; + +typedef struct { + u_int8_t mig_vers; + u_int8_t if_vers; + u_int8_t reserved1; + u_int8_t mig_encoding; + u_int8_t int_rep; + u_int8_t char_rep; + u_int8_t float_rep; + u_int8_t reserved2; +} mach_ndr_record_t; + +typedef struct { + mach_integer_t seconds; + mach_integer_t microseconds; +} mach_time_value_t; + +#ifdef DEBUG_MACH +#define DPRINTF(a) printf a +#else +#define DPRINTF(a) +#endif /* DEBUG_MACH */ + +#endif /* !_MACH_TYPES_H_ */ diff --git a/sys/compat/mach/mach_vm.c b/sys/compat/mach/mach_vm.c new file mode 100644 index 0000000..b495add --- /dev/null +++ b/sys/compat/mach/mach_vm.c @@ -0,0 +1,881 @@ +/* $NetBSD: mach_vm.c,v 1.62 2010/06/24 13:03:07 hannken Exp $ */ + +/*- + * Copyright (c) 2002-2003, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: mach_vm.c,v 1.62 2010/06/24 13:03:07 hannken Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +int +mach_vm_map(struct mach_trap_args *args) +{ + mach_vm_map_request_t *req = args->smsg; + mach_vm_map_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct proc *tp = tl->l_proc; + struct sys_mmap_args cup; + vaddr_t addr; + int error, flags; + void *ret; + +#ifdef DEBUG_MACH_VM + printf("mach_vm_map(addr = %p, size = 0x%08lx, obj = 0x%x, " + "mask = 0x%08lx, flags = 0x%x, offset = 0x%08llx, " + "copy = %d, cur_prot = 0x%x, max_prot = 0x%x, inh = 0x%x);\n", + (void *)req->req_address, (long)req->req_size, req->req_object.name, + (long)req->req_mask, req->req_flags, (off_t)req->req_offset, + req->req_copy, req->req_cur_protection, req->req_max_protection, + req->req_inherance); +#endif + + /* XXX Darwin fails on mapping a page at address 0 */ + if (req->req_address == 0) + return mach_msg_error(args, ENOMEM); + + req->req_size = round_page(req->req_size); + + /* Where Mach uses 0x00ff, we use 0x0100 */ + if ((req->req_mask & (req->req_mask + 1)) || (req->req_mask == 0)) + req->req_mask = 0; + else + req->req_mask += 1; + + if (req->req_flags & MACH_VM_FLAGS_ANYWHERE) { + SCARG(&cup, flags) = MAP_ANON; + flags = 0; + } else { + SCARG(&cup, flags) = MAP_ANON | MAP_FIXED; + flags = MAP_FIXED; + } + + /* + * Use uvm_map_findspace to find a place which conforms to the + * requested alignement. + */ + vm_map_lock(&tp->p_vmspace->vm_map); + ret = uvm_map_findspace(&tp->p_vmspace->vm_map, + trunc_page(req->req_address), req->req_size, &addr, + NULL, 0, req->req_mask, flags); + vm_map_unlock(&tp->p_vmspace->vm_map); + + if (ret == NULL) + return mach_msg_error(args, ENOMEM); + + switch(req->req_inherance) { + case MACH_VM_INHERIT_SHARE: + SCARG(&cup, flags) |= MAP_INHERIT; + break; + case MACH_VM_INHERIT_COPY: + SCARG(&cup, flags) |= MAP_COPY; + break; + case MACH_VM_INHERIT_NONE: + break; + case MACH_VM_INHERIT_DONATE_COPY: + default: + uprintf("mach_vm_map: unsupported inherance flag %d\n", + req->req_inherance); + break; + } + + SCARG(&cup, addr) = (void *)addr; + SCARG(&cup, len) = req->req_size; + SCARG(&cup, prot) = req->req_cur_protection; + SCARG(&cup, fd) = -1; /* XXX For now, no object mapping */ + SCARG(&cup, pos) = req->req_offset; + + if ((error = sys_mmap(tl, &cup, &rep->rep_retval)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_allocate(struct mach_trap_args *args) +{ + mach_vm_allocate_request_t *req = args->smsg; + mach_vm_allocate_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct proc *tp = tl->l_proc; + struct sys_mmap_args cup; + vaddr_t addr; + size_t size; + int error; + + addr = req->req_address; + size = req->req_size; + +#ifdef DEBUG_MACH_VM + printf("mach_vm_allocate(addr = %p, size = 0x%08x);\n", + (void *)addr, size); +#endif + + /* + * Avoid mappings at address zero: it should + * be a "red zone" with nothing mapped on it. + */ + if (addr == 0) { + if (req->req_flags & MACH_VM_FLAGS_ANYWHERE) + addr = 0x1000; + else + return mach_msg_error(args, EINVAL); +#ifdef DEBUG_MACH_VM + printf("mach_vm_allocate: trying addr = %p\n", (void *)addr); +#endif + } + + size = round_page(size); + if (req->req_flags & MACH_VM_FLAGS_ANYWHERE) + addr = vm_map_min(&tp->p_vmspace->vm_map); + else + addr = trunc_page(addr); + + if (((addr + size) > vm_map_max(&tp->p_vmspace->vm_map)) || + ((addr + size) <= addr)) + addr = vm_map_min(&tp->p_vmspace->vm_map); + + if (size == 0) + goto out; + + SCARG(&cup, addr) = (void *)addr; + SCARG(&cup, len) = size; + SCARG(&cup, prot) = PROT_READ | PROT_WRITE; + SCARG(&cup, flags) = MAP_ANON; + if ((req->req_flags & MACH_VM_FLAGS_ANYWHERE) == 0) + SCARG(&cup, flags) |= MAP_FIXED; + SCARG(&cup, fd) = -1; + SCARG(&cup, pos) = 0; + + if ((error = sys_mmap(tl, &cup, &rep->rep_address)) != 0) + return mach_msg_error(args, error); +#ifdef DEBUG_MACH_VM + printf("vm_allocate: success at %p\n", (void *)rep->rep_address); +#endif + +out: + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_deallocate(struct mach_trap_args *args) +{ + mach_vm_deallocate_request_t *req = args->smsg; + mach_vm_deallocate_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct sys_munmap_args cup; + int error; + +#ifdef DEBUG_MACH_VM + printf("mach_vm_deallocate(addr = %p, size = 0x%08lx);\n", + (void *)req->req_address, (long)req->req_size); +#endif + + SCARG(&cup, addr) = (void *)req->req_address; + SCARG(&cup, len) = req->req_size; + + if ((error = sys_munmap(tl, &cup, &rep->rep_retval)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_set_trailer(rep, *msglen); + + return 0; +} + +/* + * XXX This server message Id clashes with bootstrap_look_up. + * Is there a way to resolve this easily? + */ +#if 0 +int +mach_vm_wire(struct mach_trap_args *args) +{ + mach_vm_wire_request_t *req = args->smsg; + mach_vm_wire_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + register_t retval; + int error; + +#ifdef DEBUG_MACH_VM + printf("mach_vm_wire(addr = %p, size = 0x%08x, prot = 0x%x);\n", + (void *)req->req_address, req->req_size, req->req_access); +#endif + + memset(&rep, 0, sizeof(*rep)); + + if ((req->req_access & ~VM_PROT_ALL) != 0) + return mach_msg_error(args, EINVAL); + + /* + * Mach maintains a count of how many times a page is wired + * and unwire it once the count is zero. We cannot do that yet. + */ + if (req->req_access == 0) { + struct sys_munlock_args cup; + + SCARG(&cup, addr) = (void *)req->req_address; + SCARG(&cup, len) = req->req_size; + error = sys_munlock(tl, &cup, &retval); + } else { + struct sys_mlock_args cup; + + SCARG(&cup, addr) = (void *)req->req_address; + SCARG(&cup, len) = req->req_size; + error = sys_mlock(tl, &cup, &retval); + } + if (error != 0) + return mach_msg_error(args, error); + + if ((error = uvm_map_protect(&tl->l_proc->p_vmspace->vm_map, + req->req_address, req->req_address + req->req_size, + req->req_access, 0)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_set_trailer(rep, *msglen); + + return 0; +} +#endif + +int +mach_vm_protect(struct mach_trap_args *args) +{ + mach_vm_protect_request_t *req = args->smsg; + mach_vm_protect_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct sys_mprotect_args cup; + register_t retval; + int error; + + SCARG(&cup, addr) = (void *)req->req_addr; + SCARG(&cup, len) = req->req_size; + SCARG(&cup, prot) = req->req_prot; + + if ((error = sys_mprotect(tl, &cup, &retval)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_sys_map_fd(struct lwp *l, const struct mach_sys_map_fd_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(mach_vm_offset_t) offset; + syscallarg(mach_vm_offset_t *) va; + syscallarg(mach_boolean_t) findspace; + syscallarg(mach_vm_size_t) size; + } */ + file_t *fp; + struct vnode *vp; + struct exec_vmcmd evc; + struct vm_map_entry *ret; + struct proc *p = l->l_proc; + register_t dontcare; + struct sys_munmap_args cup; + void *va; + int error; + + if ((error = copyin(SCARG(uap, va), (void *)&va, sizeof(va))) != 0) + return error; + + if (SCARG(uap, findspace) == 0) { + /* Make some free space XXX probably not The Right Way */ + SCARG(&cup, addr) = va; + SCARG(&cup, len) = SCARG(uap, size); + (void)sys_munmap(l, &cup, &dontcare); + } + + fp = fd_getfile(SCARG(uap, fd)); + if (fp == NULL) + return EBADF; + + vp = fp->f_data; + vref(vp); + +#ifdef DEBUG_MACH_VM + printf("vm_map_fd: addr = %p len = 0x%08lx\n", + va, (long)SCARG(uap, size)); +#endif + memset(&evc, 0, sizeof(evc)); + evc.ev_addr = (u_long)va; + evc.ev_len = SCARG(uap, size); + evc.ev_prot = VM_PROT_ALL; + evc.ev_flags = SCARG(uap, findspace) ? 0 : VMCMD_FIXED; + evc.ev_proc = vmcmd_map_readvn; + evc.ev_offset = SCARG(uap, offset); + evc.ev_vp = vp; + + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if ((error = (*evc.ev_proc)(l, &evc)) != 0) { + VOP_UNLOCK(vp); + +#ifdef DEBUG_MACH_VM + printf("mach_sys_map_fd: mapping at %p failed\n", va); +#endif + + if (SCARG(uap, findspace) == 0) + goto bad2; + + vm_map_lock(&p->p_vmspace->vm_map); + if ((ret = uvm_map_findspace(&p->p_vmspace->vm_map, + vm_map_min(&p->p_vmspace->vm_map), evc.ev_len, + (vaddr_t *)&evc.ev_addr, NULL, 0, PAGE_SIZE, 0)) == NULL) { + vm_map_unlock(&p->p_vmspace->vm_map); + goto bad2; + } + vm_map_unlock(&p->p_vmspace->vm_map); + + va = (void *)evc.ev_addr; + + memset(&evc, 0, sizeof(evc)); + evc.ev_addr = (u_long)va; + evc.ev_len = SCARG(uap, size); + evc.ev_prot = VM_PROT_ALL; + evc.ev_flags = 0; + evc.ev_proc = vmcmd_map_readvn; + evc.ev_offset = SCARG(uap, offset); + evc.ev_vp = vp; + +#ifdef DEBUG_MACH_VM + printf("mach_sys_map_fd: trying at %p\n", va); +#endif + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if ((error = (*evc.ev_proc)(l, &evc)) != 0) + goto bad1; + } + + vput(vp); + fd_putfile(SCARG(uap, fd)); +#ifdef DEBUG_MACH_VM + printf("mach_sys_map_fd: mapping at %p\n", (void *)evc.ev_addr); +#endif + + va = (mach_vm_offset_t *)evc.ev_addr; + + if ((error = copyout((void *)&va, SCARG(uap, va), sizeof(va))) != 0) + return error; + + return 0; + +bad1: + VOP_UNLOCK(vp); +bad2: + vrele(vp); + fd_putfile(SCARG(uap, fd)); +#ifdef DEBUG_MACH_VM + printf("mach_sys_map_fd: mapping at %p failed, error = %d\n", + (void *)evc.ev_addr, error); +#endif + return error; +} + +int +mach_vm_inherit(struct mach_trap_args *args) +{ + mach_vm_inherit_request_t *req = args->smsg; + mach_vm_inherit_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct sys_minherit_args cup; + register_t retval; + int error; + + SCARG(&cup, addr) = (void *)req->req_addr; + SCARG(&cup, len) = req->req_size; + /* Flags map well between Mach and NetBSD */ + SCARG(&cup, inherit) = req->req_inh; + + if ((error = sys_minherit(tl, &cup, &retval)) != 0) + return mach_msg_error(args, error); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_make_memory_entry_64(struct mach_trap_args *args) +{ + mach_make_memory_entry_64_request_t *req = args->smsg; + mach_make_memory_entry_64_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + struct mach_port *mp; + struct mach_right *mr; + struct mach_memory_entry *mme; + + printf("mach_make_memory_entry_64, offset 0x%lx, size 0x%lx\n", + (u_long)req->req_offset, (u_long)req->req_size); + + mp = mach_port_get(); + mp->mp_flags |= (MACH_MP_INKERNEL | MACH_MP_DATA_ALLOCATED); + mp->mp_datatype = MACH_MP_MEMORY_ENTRY; + + mme = malloc(sizeof(*mme), M_EMULDATA, M_WAITOK); + mme->mme_proc = tl->l_proc; + mme->mme_offset = req->req_offset; + mme->mme_size = req->req_size; + mp->mp_data = mme; + + mr = mach_right_get(mp, l, MACH_PORT_TYPE_SEND, 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, mr->mr_name); + + rep->rep_size = req->req_size; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_region(struct mach_trap_args *args) +{ + mach_vm_region_request_t *req = args->smsg; + mach_vm_region_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct mach_vm_region_basic_info *rbi; + struct vm_map *map; + struct vm_map_entry *vme; + int error; + + /* Sanity check req_count */ + if (req->req_count > 9) + return mach_msg_error(args, EINVAL); + + /* + * MACH_VM_REGION_BASIC_INFO is the only + * supported flavor in Darwin. + */ + if (req->req_flavor != MACH_VM_REGION_BASIC_INFO) + return mach_msg_error(args, EINVAL); + if (req->req_count != (sizeof(*rbi) / sizeof(int))) /* This is 8 */ + return mach_msg_error(args, EINVAL); + *msglen = sizeof(*rep) + ((req->req_count - 9) * sizeof(int)); + + map = &tl->l_proc->p_vmspace->vm_map; + + vm_map_lock(map); + error = uvm_map_lookup_entry(map, req->req_addr, &vme); + vm_map_unlock(map); + + if (error == 0) + return mach_msg_error(args, ENOMEM); + + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, 0); /* XXX Why this null name */ + + rep->rep_addr = vme->start; + rep->rep_size = vme->end - vme->start; + rep->rep_count = req->req_count; + + rbi = (struct mach_vm_region_basic_info *)&rep->rep_info[0]; + rbi->protection = vme->protection; + rbi->inheritance = 1; /* vme->inheritance */ + rbi->shared = 0; /* XXX how can we know? */ + rbi->offset = vme->offset; + rbi->behavior = MACH_VM_BEHAVIOR_DEFAULT; /* XXX What is it? */ + rbi->user_wired_count = vme->wired_count; + + /* XXX Why this? */ + *(short *)((u_long)&rbi->user_wired_count + sizeof(short)) = 1; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_region_64(struct mach_trap_args *args) +{ + mach_vm_region_64_request_t *req = args->smsg; + mach_vm_region_64_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct mach_vm_region_basic_info_64 *rbi; + struct vm_map *map; + struct vm_map_entry *vme; + int error; + + /* Sanity check req_count */ + if (req->req_count > 10) + return mach_msg_error(args, EINVAL); + + /* + * MACH_VM_REGION_BASIC_INFO is the only + * supported flavor in Darwin. + */ + if (req->req_flavor != MACH_VM_REGION_BASIC_INFO) + return mach_msg_error(args, EINVAL); + if (req->req_count != (sizeof(*rbi) / sizeof(int))) /* This is 8 */ + return mach_msg_error(args, EINVAL); + *msglen = sizeof(*rep) + ((req->req_count - 9) * sizeof(int)); + + map = &tl->l_proc->p_vmspace->vm_map; + + vm_map_lock(map); + error = uvm_map_lookup_entry(map, req->req_addr, &vme); + vm_map_unlock(map); + + if (error == 0) + return mach_msg_error(args, ENOMEM); + + mach_set_header(rep, req, *msglen); + mach_add_port_desc(rep, 0); /* XXX null port ? */ + + rep->rep_size = PAGE_SIZE; /* XXX Why? */ + rep->rep_count = req->req_count; + + rbi = (struct mach_vm_region_basic_info_64 *)&rep->rep_info[0]; + rbi->protection = vme->protection; + rbi->inheritance = 1; /* vme->inheritance */ + rbi->shared = 0; /* XXX how can we know? */ + rbi->offset = vme->offset; + rbi->behavior = MACH_VM_BEHAVIOR_DEFAULT; /* XXX What is it? */ + rbi->user_wired_count = vme->wired_count; + + /* XXX Why this? */ + *(short *)((u_long)&rbi->user_wired_count + sizeof(short)) = 1; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_msync(struct mach_trap_args *args) +{ + mach_vm_msync_request_t *req = args->smsg; + mach_vm_msync_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + struct sys___msync13_args cup; + int error; + register_t dontcare; + + SCARG(&cup, addr) = (void *)req->req_addr; + SCARG(&cup, len) = req->req_size; + SCARG(&cup, flags) = 0; + if (req->req_flags & MACH_VM_SYNC_ASYNCHRONOUS) + SCARG(&cup, flags) |= MS_ASYNC; + if (req->req_flags & MACH_VM_SYNC_SYNCHRONOUS) + SCARG(&cup, flags) |= MS_SYNC; + if (req->req_flags & MACH_VM_SYNC_INVALIDATE) + SCARG(&cup, flags) |= MS_INVALIDATE; + + error = sys___msync13(tl, &cup, &dontcare); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = native_to_mach_errno[error]; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +/* XXX Do it for remote task */ +int +mach_vm_copy(struct mach_trap_args *args) +{ + mach_vm_copy_request_t *req = args->smsg; + mach_vm_copy_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + char *tmpbuf; + int error; + char *src, *dst; + size_t size; + +#ifdef DEBUG_MACH_VM + printf("mach_vm_copy: src = 0x%08lx, size = 0x%08lx, addr = 0x%08lx\n", + (long)req->req_src, (long)req->req_size, (long)req->req_addr); +#endif + if ((req->req_src & (PAGE_SIZE - 1)) || + (req->req_addr & (PAGE_SIZE - 1)) || + (req->req_size & (PAGE_SIZE - 1))) + return mach_msg_error(args, EINVAL); + + src = (void *)req->req_src; + dst = (void *)req->req_addr; + size = (size_t)req->req_size; + + tmpbuf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); + + /* Is there an easy way of dealing with that efficiently? */ + do { + if ((error = copyin(src, tmpbuf, PAGE_SIZE)) != 0) + goto out; + + if ((error = copyout(tmpbuf, dst, PAGE_SIZE)) != 0) + goto out; + + src += PAGE_SIZE; + dst += PAGE_SIZE; + size -= PAGE_SIZE; + } while (size > 0); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + free(tmpbuf, M_TEMP); + return 0; + +out: + free(tmpbuf, M_TEMP); + return mach_msg_error(args, error); +} + +int +mach_vm_read(struct mach_trap_args *args) +{ + mach_vm_read_request_t *req = args->smsg; + mach_vm_read_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *l = args->l; + struct lwp *tl = args->tl; + char *tbuf; + void *addr; + vaddr_t va; + size_t size; + int error; + + size = req->req_size; + va = vm_map_min(&l->l_proc->p_vmspace->vm_map); + if ((error = uvm_map(&l->l_proc->p_vmspace->vm_map, &va, + round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0, + UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL, + UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0) { + printf("uvm_map error = %d\n", error); + return mach_msg_error(args, EFAULT); + } + + /* + * Copy the data from the target process to the current process + * This is reasonable for small chunk of data, but we should + * remap COW for areas bigger than a page. + */ + tbuf = malloc(size, M_EMULDATA, M_WAITOK); + + addr = (void *)req->req_addr; + if ((error = copyin_proc(tl->l_proc, addr, tbuf, size)) != 0) { + printf("copyin_proc error = %d, addr = %p, size = %x\n", error, addr, size); + free(tbuf, M_WAITOK); + return mach_msg_error(args, EFAULT); + } + + if ((error = copyout(tbuf, (void *)va, size)) != 0) { + printf("copyout error = %d\n", error); + free(tbuf, M_WAITOK); + return mach_msg_error(args, EFAULT); + } + + if (error == 0) + ktrmool(tbuf, size, (void *)va); + + free(tbuf, M_WAITOK); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + mach_add_ool_desc(rep, (void *)va, size); + + rep->rep_count = size; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_write(struct mach_trap_args *args) +{ + mach_vm_write_request_t *req = args->smsg; + mach_vm_write_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + size_t size; + void *addr; + char *tbuf; + int error; + +#ifdef DEBUG_MACH + if (req->req_body.msgh_descriptor_count != 1) + printf("mach_vm_write: OOL descriptor count is not 1\n"); +#endif + + /* + * Copy the data from the current process to the target process + * This is reasonable for small chunk of data, but we should + * remap COW for areas bigger than a page. + */ + size = req->req_data.size; + tbuf = malloc(size, M_EMULDATA, M_WAITOK); + + if ((error = copyin(req->req_data.address, tbuf, size)) != 0) { + printf("copyin error = %d\n", error); + free(tbuf, M_WAITOK); + return mach_msg_error(args, EFAULT); + } + + addr = (void *)req->req_addr; + if ((error = copyout_proc(tl->l_proc, tbuf, addr, size)) != 0) { + printf("copyout_proc error = %d\n", error); + free(tbuf, M_WAITOK); + return mach_msg_error(args, EFAULT); + } + + if (error == 0) + ktrmool(tbuf, size, (void *)addr); + + free(tbuf, M_WAITOK); + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = 0; + + mach_set_trailer(rep, *msglen); + + return 0; +} + +int +mach_vm_machine_attribute(struct mach_trap_args *args) +{ + mach_vm_machine_attribute_request_t *req = args->smsg; + mach_vm_machine_attribute_reply_t *rep = args->rmsg; + size_t *msglen = args->rsize; + struct lwp *tl = args->tl; + int error = 0; + int attribute, value; + + attribute = req->req_attribute; + value = req->req_value; + + switch (attribute) { + case MACH_MATTR_CACHE: + switch(value) { + case MACH_MATTR_VAL_CACHE_FLUSH: + case MACH_MATTR_VAL_DCACHE_FLUSH: + case MACH_MATTR_VAL_ICACHE_FLUSH: + case MACH_MATTR_VAL_CACHE_SYNC: + error = mach_vm_machine_attribute_machdep(tl, + req->req_addr, req->req_size, &value); + break; + default: +#ifdef DEBUG_MACH + printf("unimplemented value %d\n", req->req_value); +#endif + error = EINVAL; + break; + } + break; + + case MACH_MATTR_MIGRATE: + case MACH_MATTR_REPLICATE: + default: +#ifdef DEBUG_MACH + printf("unimplemented attribute %d\n", req->req_attribute); +#endif + error = EINVAL; + break; + } + + *msglen = sizeof(*rep); + mach_set_header(rep, req, *msglen); + + rep->rep_retval = native_to_mach_errno[error]; + if (error != 0) + rep->rep_value = value; + + mach_set_trailer(rep, *msglen); + + return 0; +} diff --git a/sys/compat/mach/mach_vm.h b/sys/compat/mach/mach_vm.h new file mode 100644 index 0000000..0c887d9 --- /dev/null +++ b/sys/compat/mach/mach_vm.h @@ -0,0 +1,391 @@ +/* $NetBSD: mach_vm.h,v 1.30 2008/04/28 20:23:45 martin Exp $ */ + +/*- + * Copyright (c) 2002-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emmanuel Dreyfus + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACH_VM_H_ +#define _MACH_VM_H_ + + +#include +#include + +#include +#include + +#define MACH_ALTERNATE_LOAD_SITE 1 +#define MACH_NEW_LOCAL_SHARED_REGIONS 2 +#define MACH_QUERY_IS_SYSTEM_REGION 4 +#define MACH_SF_PREV_LOADED 1 +#define MACH_SYSTEM_REGION_BACKED 2 + +#define MACH_VM_PROT_COW 0x8 +#define MACH_VM_PROT_ZF 0x10 + +typedef struct mach_sf_mapping { + mach_vm_offset_t mapping_offset; + mach_vm_size_t size; + mach_vm_offset_t file_offset; + mach_vm_prot_t protection; + mach_vm_offset_t cksum; +} mach_sf_mapping_t; + +struct mach_vm_region_basic_info { + mach_vm_prot_t protection; + mach_vm_prot_t max_protection; + mach_vm_inherit_t inheritance; + mach_boolean_t shared; + mach_boolean_t reserved; + mach_vm_offset_t offset; + mach_vm_behavior_t behavior; + unsigned short user_wired_count; +}; + +/* There is no difference between 32 and 64 bits versions */ +struct mach_vm_region_basic_info_64 { + mach_vm_prot_t protection; + mach_vm_prot_t max_protection; + mach_vm_inherit_t inheritance; + mach_boolean_t shared; + mach_boolean_t reserved; + mach_vm_offset_t offset; + mach_vm_behavior_t behavior; + unsigned short user_wired_count; +}; + +/* mach_vm_behavior_t values */ +#define MACH_VM_BEHAVIOR_DEFAULT 0 +#define MACH_VM_BEHAVIOR_RANDOM 1 +#define MACH_VM_BEHAVIOR_SEQUENTIAL 2 +#define MACH_VM_BEHAVIOR_RSEQNTL 3 +#define MACH_VM_BEHAVIOR_WILLNEED 4 +#define MACH_VM_BEHAVIOR_DONTNEED 5 + +/* vm_map */ +#define MACH_VM_INHERIT_SHARE 0 +#define MACH_VM_INHERIT_COPY 1 +#define MACH_VM_INHERIT_NONE 2 +#define MACH_VM_INHERIT_DONATE_COPY 3 +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_object; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_address; + mach_vm_size_t req_size; + mach_vm_address_t req_mask; + int req_flags; + mach_vm_offset_t req_offset; + mach_boolean_t req_copy; + mach_vm_prot_t req_cur_protection; + mach_vm_prot_t req_max_protection; + mach_vm_inherit_t req_inherance; +} mach_vm_map_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_vm_address_t rep_address; + mach_msg_trailer_t rep_trailer; +} mach_vm_map_reply_t; + +/* vm_allocate */ +#define MACH_VM_FLAGS_ANYWHERE 1 +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_address; + mach_vm_size_t req_size; + int req_flags; +} mach_vm_allocate_request_t; + + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_vm_address_t rep_address; + mach_msg_trailer_t rep_trailer; +} mach_vm_allocate_reply_t; + +/* vm_deallocate */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_address; + mach_vm_size_t req_size; +} mach_vm_deallocate_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_deallocate_reply_t; + +/* vm_wire */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_task; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_address; + mach_vm_size_t req_size; + mach_vm_prot_t req_access; +} mach_vm_wire_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_wire_reply_t; + +/* vm_protect */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_size_t req_size; + mach_boolean_t req_set_maximum; + mach_vm_prot_t req_prot; +} mach_vm_protect_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_protect_reply_t; + +/* vm_inherit */ +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_size_t req_size; + mach_vm_inherit_t req_inh; +} mach_vm_inherit_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_inherit_reply_t; + +/* + * make_memory_entry_64 + */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_port_descriptor_t req_parent_entry; + mach_ndr_record_t req_ndr; + mach_memory_object_size_t req_size; + mach_memory_object_offset_t req_offset; + mach_vm_prot_t req_perm; +} __packed mach_make_memory_entry_64_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_obj_handle; + mach_ndr_record_t rep_ndr; + mach_memory_object_size_t rep_size; + mach_msg_trailer_t rep_trailer; +} __packed mach_make_memory_entry_64_reply_t; + +/* vm_region */ + +#define MACH_VM_REGION_BASIC_INFO 10 +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_region_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_vm_region_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_obj; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_addr; + mach_vm_size_t rep_size; + mach_msg_type_number_t rep_count; + int rep_info[9]; + mach_msg_trailer_t rep_trailer; +} mach_vm_region_reply_t; + +/* vm_region_64 */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_region_flavor_t req_flavor; + mach_msg_type_number_t req_count; +} mach_vm_region_64_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_port_descriptor_t rep_obj; + mach_ndr_record_t rep_ndr; + mach_vm_address_t rep_addr; + mach_vm_size_t rep_size; + mach_msg_type_number_t rep_count; + int rep_info[10]; + mach_msg_trailer_t rep_trailer; +} mach_vm_region_64_reply_t; + +/* vm_msync */ +#define MACH_VM_SYNC_ASYNCHRONOUS 0x01 +#define MACH_VM_SYNC_SYNCHRONOUS 0x02 +#define MACH_VM_SYNC_INVALIDATE 0x04 +#define MACH_VM_SYNC_KILLPAGES 0x08 +#define MACH_VM_SYNC_DEACTIVATE 0x10 +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_size_t req_size; + mach_vm_sync_t req_flags; +} mach_vm_msync_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_msync_reply_t; + +/* vm_copy */ +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_src; + mach_vm_size_t req_size; + mach_vm_address_t req_addr; +} mach_vm_copy_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_kern_return_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_copy_reply_t; + +/* vm_read */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_size_t req_size; +} mach_vm_read_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_msg_body_t rep_body; + mach_msg_ool_descriptor_t rep_data; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_count; + mach_msg_trailer_t rep_trailer; +} mach_vm_read_reply_t; + +/* vm_write */ + +typedef struct { + mach_msg_header_t req_msgh; + mach_msg_body_t req_body; + mach_msg_ool_descriptor_t req_data; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_msg_type_number_t req_count; +} mach_vm_write_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_retval; + mach_msg_trailer_t rep_trailer; +} mach_vm_write_reply_t; + +/* vm_machine_attribute */ + +#define MACH_MATTR_CACHE 1 +#define MACH_MATTR_MIGRATE 2 +#define MACH_MATTR_REPLICATE 4 + +#define MACH_MATTR_VAL_OFF 0 +#define MACH_MATTR_VAL_ON 1 +#define MACH_MATTR_VAL_GET 2 +#define MACH_MATTR_VAL_CACHE_FLUSH 6 +#define MACH_MATTR_VAL_DCACHE_FLUSH 7 +#define MACH_MATTR_VAL_ICACHE_FLUSH 8 +#define MACH_MATTR_VAL_CACHE_SYNC 9 +#define MACH_MATTR_VAL_GET_INFO 10 + +typedef struct { + mach_msg_header_t req_msgh; + mach_ndr_record_t req_ndr; + mach_vm_address_t req_addr; + mach_vm_address_t req_size; + mach_vm_machine_attribute_t req_attribute; + mach_vm_machine_attribute_val_t req_value; +} mach_vm_machine_attribute_request_t; + +typedef struct { + mach_msg_header_t rep_msgh; + mach_ndr_record_t rep_ndr; + mach_msg_type_number_t rep_retval; + mach_vm_machine_attribute_val_t rep_value; + mach_msg_trailer_t rep_trailer; +} mach_vm_machine_attribute_reply_t; + +/* Kernel-private structures */ + +struct mach_memory_entry { + struct proc *mme_proc; + vaddr_t mme_offset; + size_t mme_size; +}; + +/* These are machine dependent functions */ +int mach_vm_machine_attribute_machdep(struct lwp *, vaddr_t, size_t, int *); + +#endif /* _MACH_VM_H_ */ diff --git a/sys/compat/mach/makemachservices.sh b/sys/compat/mach/makemachservices.sh new file mode 100755 index 0000000..34c2be6 --- /dev/null +++ b/sys/compat/mach/makemachservices.sh @@ -0,0 +1,133 @@ +#!/bin/sh +# $NetBSD: makemachservices.sh,v 1.8 2008/05/04 00:43:55 martin Exp $ +# +# Copyright (c) 2003 The NetBSD Foundation, Inc. +# All rights reserved. +# This code is derived from software contributed to The NetBSD Foundation +# by Emmanuel Dreyfus. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +master="mach_services.master" +table="mach_services.c" +headers="mach_services.h" +names="mach_services_names.c" + +sed -e ' +:join + /\\$/{a\ + + N + s/\\\n// + b join + } +' $master | awk ' +BEGIN{ + intable = 0; + table = "'$table'"; + headers = "'$headers'"; + names = "'$names'"; + + printf("/* \$NetBSD\$ *\/\n\n") > table; + printf("/*\n * Mach services table.\n *\n") > table; + printf(" * DO NOT EDIT -- this file is automatically generated.\n") > \ + table; + + printf("/* \$NetBSD\$ *\/\n\n") > headers; + printf("/*\n * Mach services prototypes.\n *\n") > headers; + printf(" * DO NOT EDIT -- this file is automatically generated.\n") > \ + headers; + + printf("/* \$NetBSD\$ *\/\n\n") > names; + printf("/*\n * Mach services names. This file is not built\n") > names; + printf(" * by the kernel, it is included by kdump sources.\n *\n") > \ + names; + printf(" * DO NOT EDIT -- this file is automatically generated.\n") > \ + names; +} +(NR == 1) { + gsub(/^[^\$]*\$/, "", $0); + gsub(/\$.*$/, "", $0); + sub(/ $/, ""); + printf(" * created from %s\n */\n\n", $0) > table; + printf("#include \\n__KERNEL_RCSID(0, " \ + "\"\$NetBSD\$\");\n\n") > table; + + printf(" * created from %s\n */\n\n", $0) > headers; + printf("#include \\n__KERNEL_RCSID(0, " \ + "\"\$NetBSD\$\");\n\n") > headers; + printf("#include \n") > headers; + printf("#include \n") > headers; + + printf(" * created from %s\n */\n\n", $0) > names; + printf("#include \\n__KERNEL_RCSID(0, " \ + "\"\$NetBSD\$\");\n\n") > names; + printf("struct mach_service_name {\n") > names; + printf(" int srv_id;\n") > names; + printf(" const char *srv_name;\n") > names; + printf("};\n\n") > names; + next; +} +(NF == 0 || $1 ~ /^;/) { + next; +} +($0 ~ /^%%$/) { + intable = 1; + printf("\nstruct mach_service mach_services_table[] = {\n") > table; + printf("\n") > headers; + printf("struct mach_service_name mach_services_names[] = {\n") > names; + next; +} +(!intable) { + printf("%s\n", $0) > table; + next; +} +(intable && $2 == "STD") { + printf(" {%d, mach_%s, \"%s\", " \ + "sizeof(mach_%s_request_t), sizeof(mach_%s_reply_t)},\n", \ + $1, $3, $3, $3, $3) > table; + printf("int mach_%s(struct mach_trap_args *);\n", $3) > headers; + printf(" {%d, \"%s\"},\n", $1, $3) > names; +} +(intable && $2 == "NODEF") { + printf(" {%d, NULL, \"%s\", 0, 0},\n", \ + $1, $3, $3, $3, $3) > table; + printf(" {%d, \"%s\"},\n", $1, $3) > names; +} +(intable && $2 == "UNIMPL") { + printf(" {%d, NULL, \"unimpl. %s\", 0, 0},\n", \ + $1, $3, $3, $3, $3) > table; + printf(" {%d, \"unimpl. %s\"},\n", $1, $3) > names; +} +(intable && $2 == "OBSOL") { + printf(" {%d, NULL, \"obsolete %s\", 0, 0},\n", \ + $1, $3, $3, $3, $3) > table; + printf(" {%d, \"obsolete %s\"},\n", $1, $3) > names; +} +END { + printf(" {0, NULL, NULL, 0, 0}\n") > table; + printf("};\n") > table; + + printf(" {0, NULL}\n") > names; + printf("};\n") > names; +} +' diff --git a/sys/compat/mach/syscalls.conf b/sys/compat/mach/syscalls.conf new file mode 100644 index 0000000..c416d08 --- /dev/null +++ b/sys/compat/mach/syscalls.conf @@ -0,0 +1,14 @@ +# $NetBSD: syscalls.conf,v 1.2 2007/12/10 22:32:15 dsl Exp $ + +sysnames="mach_syscalls.c" +sysnumhdr="mach_syscall.h" +syssw="mach_sysent.c" +sysarghdr="mach_syscallargs.h" +compatopts="" +libcompatopts="" + +switchname="mach_sysent" +namesname="mach_syscallnames" +constprefix="MACH_SYS_" +nsysent=128 +maxsysargs=9 diff --git a/sys/compat/mach/syscalls.master b/sys/compat/mach/syscalls.master new file mode 100644 index 0000000..001a094 --- /dev/null +++ b/sys/compat/mach/syscalls.master @@ -0,0 +1,241 @@ + $NetBSD: syscalls.master,v 1.10 2009/01/13 22:27:43 pooka Exp $ + +; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 + +; NetBSD COMPAT_MACH system call name/number "master" file. +; This is used for the negative mach syscalls. +; (See syscalls.conf to see what it is processed into.) +; +; Fields: number type [type-dependent ...] +; number system call number, must be in order +; type one of STD, OBSOL, UNIMPL, NODEF, NOARGS, or one of +; the compatibility options defined in syscalls.conf. +; +; types: +; STD always included +; OBSOL obsolete, not included in system +; UNIMPL unimplemented, not included in system +; NODEF included, but don't define the syscall number +; NOARGS included, but don't define the syscall args structure +; +; The compat options are defined in the syscalls.conf file, and the +; compat option name is prefixed to the syscall name. Other than +; that, they're like NODEF (for 'compat' options), or STD (for +; 'libcompat' options). +; +; The type-dependent arguments are as follows: +; For STD, NODEF, NOARGS, and compat syscalls: +; { pseudo-proto } [alias] +; For other syscalls: +; [comment] +; +; #ifdef's, etc. may be included, and are copied to the output files. +; #include's are copied to the syscall names and switch definition files only. + +#if defined(_KERNEL_OPT) +#include "opt_ntp.h" +#include "opt_sysv.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +%% + +0 UNIMPL +1 UNIMPL +2 UNIMPL +3 UNIMPL +4 UNIMPL +5 UNIMPL +6 UNIMPL +7 UNIMPL +8 UNIMPL +9 UNIMPL +10 UNIMPL +11 UNIMPL +12 UNIMPL +13 UNIMPL +14 UNIMPL +15 UNIMPL +16 UNIMPL +17 UNIMPL +18 UNIMPL +19 UNIMPL +20 UNIMPL +21 UNIMPL +22 UNIMPL +23 UNIMPL +24 UNIMPL +25 UNIMPL +26 STD { mach_port_name_t|mach_sys||reply_port(void); } +27 STD { mach_port_name_t|mach_sys||thread_self_trap(void); } +28 STD { mach_port_name_t|mach_sys||task_self_trap(void); } +29 STD { mach_port_name_t|mach_sys||host_self_trap(void); } +30 UNIMPL +31 STD { mach_msg_return_t|mach_sys||msg_trap( \ + mach_msg_header_t *msg, \ + mach_msg_option_t option, \ + mach_msg_size_t send_size, \ + mach_msg_size_t rcv_size, \ + mach_port_name_t rcv_name, \ + mach_msg_timeout_t timeout, \ + mach_port_name_t notify); } +32 STD { mach_kern_return_t|mach_sys||msg_overwrite_trap( \ + mach_msg_header_t *msg, \ + mach_msg_option_t option, \ + mach_msg_size_t send_size, \ + mach_msg_size_t rcv_size, \ + mach_port_name_t rcv_name, \ + mach_msg_timeout_t timeout, \ + mach_port_name_t notify, \ + mach_msg_header_t *rcv_msg, \ + mach_msg_size_t scatter_list_size); } +33 STD { mach_kern_return_t|\ + mach_sys||semaphore_signal_trap( \ + mach_port_name_t signal_name); } +34 STD { mach_kern_return_t|\ + mach_sys||semaphore_signal_all_trap( \ + mach_port_name_t signal_name); } +35 STD { mach_kern_return_t|\ + mach_sys||semaphore_signal_thread_trap( \ + mach_port_name_t signal_name, \ + mach_port_name_t thread); } +36 STD { mach_kern_return_t|\ + mach_sys||semaphore_wait_trap( \ + mach_port_name_t wait_name); } +37 STD { mach_kern_return_t|\ + mach_sys||semaphore_wait_signal_trap( \ + mach_port_name_t wait_name, \ + mach_port_name_t signal_name); } +38 STD { mach_kern_return_t|\ + mach_sys||semaphore_timedwait_trap( \ + mach_port_name_t wait_name, \ + unsigned int sec, \ + mach_clock_res_t nsec); } +39 STD { mach_kern_return_t|\ + mach_sys||semaphore_timedwait_signal_trap( \ + mach_port_name_t wait_name, \ + mach_port_name_t signal_name, \ + unsigned int sec, \ + mach_clock_res_t nsec); } +40 UNIMPL +41 STD { mach_kern_return_t|mach_sys||init_process(void); } +42 UNIMPL +43 STD { mach_kern_return_t|mach_sys||map_fd(int fd, \ + mach_vm_offset_t offset, mach_vm_offset_t *va, \ + mach_boolean_t findspace, mach_vm_size_t size); } +44 UNIMPL +45 STD { mach_kern_return_t|mach_sys||task_for_pid( \ + mach_port_t target_tport, int pid, \ + mach_port_t *t); } +46 STD { mach_kern_return_t|mach_sys||pid_for_task( \ + mach_port_t t, int *x); } +47 UNIMPL +48 STD { mach_kern_return_t|mach_sys||macx_swapon( \ + char *name, int flags, int size, int priority); } +49 STD { mach_kern_return_t|mach_sys||macx_swapoff( \ + char *name, int flags); } +50 UNIMPL +51 STD { mach_kern_return_t|mach_sys||macx_triggers( \ + int hi_water, int low_water, int flags, \ + mach_port_t alert_port); } +52 UNIMPL +53 UNIMPL +54 UNIMPL +55 UNIMPL +56 UNIMPL +57 UNIMPL +58 UNIMPL +59 STD { mach_kern_return_t|mach_sys||swtch_pri( \ + int pri); } +60 STD { mach_kern_return_t|mach_sys||swtch(void); } +61 STD { mach_kern_return_t|mach_sys||syscall_thread_switch( \ + mach_port_name_t thread_name, \ + int option, \ + mach_msg_timeout_t option_time); } +62 STD { mach_kern_return_t|mach_sys||clock_sleep_trap( \ + mach_port_name_t clock_name, \ + mach_sleep_type_t sleep_type, \ + int sleep_sec, int sleep_nsec, \ + mach_timespec_t *wakeup_time); } +63 UNIMPL +64 UNIMPL +65 UNIMPL +66 UNIMPL +67 UNIMPL +68 UNIMPL +69 UNIMPL +70 UNIMPL +71 UNIMPL +72 UNIMPL +73 UNIMPL +74 UNIMPL +75 UNIMPL +76 UNIMPL +77 UNIMPL +78 UNIMPL +79 UNIMPL +80 UNIMPL +81 UNIMPL +82 UNIMPL +83 UNIMPL +84 UNIMPL +85 UNIMPL +86 UNIMPL +87 UNIMPL +88 UNIMPL +89 STD { mach_kern_return_t|mach_sys||timebase_info( \ + mach_timebase_info_t info); } +90 STD { mach_kern_return_t|mach_sys||wait_until( \ + u_int64_t deadline); } +91 STD { mach_port_name_t|mach_sys||timer_create(void); } +92 STD { mach_kern_return_t|mach_sys||timer_destroy( \ + mach_port_name_t name); } +93 STD { mach_kern_return_t|mach_sys||timer_arm( \ + mach_port_name_t name, \ + mach_absolute_time_t expire_time); } +94 STD { mach_kern_return_t|mach_sys||timer_cancel( \ + mach_port_name_t name, \ + mach_absolute_time_t *result_time); } +95 STD { mach_kern_return_t|mach_sys||get_time_base_info(void); } +96 UNIMPL +97 UNIMPL +98 UNIMPL +99 UNIMPL +100 UNIMPL +101 UNIMPL +102 UNIMPL +103 UNIMPL +104 UNIMPL +105 UNIMPL +106 UNIMPL +107 UNIMPL +108 UNIMPL +109 UNIMPL +110 UNIMPL +111 UNIMPL +112 UNIMPL +113 UNIMPL +114 UNIMPL +115 UNIMPL +116 UNIMPL +117 UNIMPL +118 UNIMPL +119 UNIMPL +120 UNIMPL +121 UNIMPL +122 UNIMPL +123 UNIMPL +124 UNIMPL +125 UNIMPL +126 UNIMPL +127 UNIMPL -- 1.8.4.2