Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/compat First work on Mach exceptions. Things that can tu...



details:   https://anonhg.NetBSD.org/src/rev/d75677a303c2
branches:  trunk
changeset: 555421:d75677a303c2
user:      manu <manu%NetBSD.org@localhost>
date:      Mon Nov 17 01:52:14 2003 +0000

description:
First work on Mach exceptions. Things that can turn into signals on UNIX
may turn into exceptions on Mach: a small message sent by the kernel to
the task that requested the exception.
On Darwin, when an exception is sent, no signal can be delivered.

TODO: more exceptions: arithmetic, bad instructions, emulation, s
software, and syscalls (plain and Mach). There is also RPC alert, but
I have no idea about what it is.

While we are there, remove some user ktrace in notification code, and add
a NODEF qualifier in mach_services.master: it will be used for notifications
and exceptions, where the kernel is always client and never server: we
don't want the message to be displayed as "unimplemented xxx" in kdump (thus
UNIMPL is not good), but we don't want to generate the server prototype
(therefore, STD is not good either). NODEF will declare it normally in the
name tables without creating the prototype.

diffstat:

 sys/compat/darwin/darwin_exec.c       |    6 +-
 sys/compat/darwin/darwin_signal.c     |   21 ++-
 sys/compat/darwin/darwin_signal.h     |    3 +-
 sys/compat/mach/mach_exec.c           |    6 +-
 sys/compat/mach/mach_notify.c         |  265 ++++++++++++++++++++++++++++++++-
 sys/compat/mach/mach_notify.h         |  106 ++++++++++--
 sys/compat/mach/mach_port.h           |    3 +-
 sys/compat/mach/mach_services.c       |   22 +-
 sys/compat/mach/mach_services.h       |    6 +-
 sys/compat/mach/mach_services.master  |   18 +-
 sys/compat/mach/mach_services_names.c |   22 +-
 sys/compat/mach/mach_task.c           |   40 ++++-
 sys/compat/mach/mach_task.h           |    4 +-
 sys/compat/mach/makemachservices.sh   |    7 +-
 14 files changed, 442 insertions(+), 87 deletions(-)

diffs (truncated from 858 to 300 lines):

diff -r 807bd48fee89 -r d75677a303c2 sys/compat/darwin/darwin_exec.c
--- a/sys/compat/darwin/darwin_exec.c   Mon Nov 17 01:44:49 2003 +0000
+++ b/sys/compat/darwin/darwin_exec.c   Mon Nov 17 01:52:14 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: darwin_exec.c,v 1.22 2003/10/25 10:43:45 manu Exp $ */
+/*     $NetBSD: darwin_exec.c,v 1.23 2003/11/17 01:52:14 manu Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 
 #include "opt_compat_darwin.h" /* For COMPAT_DARWIN in mach_port.h */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.22 2003/10/25 10:43:45 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.23 2003/11/17 01:52:14 manu Exp $");
 
 #include "opt_syscall_debug.h"
 
@@ -110,7 +110,7 @@
        NULL,
 #endif
        darwin_sendsig,
-       trapsignal,
+       darwin_trapsignal,
 #if !defined(__HAVE_SIGINFO) || defined(COMPAT_16)
        sigcode,
        esigcode,
diff -r 807bd48fee89 -r d75677a303c2 sys/compat/darwin/darwin_signal.c
--- a/sys/compat/darwin/darwin_signal.c Mon Nov 17 01:44:49 2003 +0000
+++ b/sys/compat/darwin/darwin_signal.c Mon Nov 17 01:52:14 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: darwin_signal.c,v 1.7 2003/10/25 18:38:07 christos Exp $ */
+/*     $NetBSD: darwin_signal.c,v 1.8 2003/11/17 01:52:14 manu Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: darwin_signal.c,v 1.7 2003/10/25 18:38:07 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: darwin_signal.c,v 1.8 2003/11/17 01:52:14 manu Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -52,6 +52,8 @@
 
 #include <compat/mach/mach_types.h>
 #include <compat/mach/mach_vm.h>
+#include <compat/mach/mach_port.h>
+#include <compat/mach/mach_notify.h>
 
 #include <compat/darwin/darwin_signal.h>
 #include <compat/darwin/darwin_syscallargs.h>
@@ -122,3 +124,18 @@
        return 0;
 }
 
+void
+darwin_trapsignal(l, ksi)
+       struct lwp *l;
+       const struct ksiginfo *ksi;
+{
+       /* 
+        * If mach_trapsignal1 returns 0, the exception was intercepted at
+        * the Mach level, n signal is to be sent. if it returns an error,
+        * we call native trapsignal to fire a UNIX signal.
+        */
+       if (mach_trapsignal1(l, ksi) != 0)
+               trapsignal(l, ksi);
+
+       return;
+}
diff -r 807bd48fee89 -r d75677a303c2 sys/compat/darwin/darwin_signal.h
--- a/sys/compat/darwin/darwin_signal.h Mon Nov 17 01:44:49 2003 +0000
+++ b/sys/compat/darwin/darwin_signal.h Mon Nov 17 01:52:14 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: darwin_signal.h,v 1.8 2003/09/30 21:04:54 manu Exp $ */
+/*     $NetBSD: darwin_signal.h,v 1.9 2003/11/17 01:52:14 manu Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -80,6 +80,7 @@
 };
 
 void darwin_sendsig(const ksiginfo_t *, const sigset_t *);
+void darwin_trapsignal(struct lwp *, const struct ksiginfo *);
 
 #endif /* _DARWIN_SIGNAL_H_ */
 
diff -r 807bd48fee89 -r d75677a303c2 sys/compat/mach/mach_exec.c
--- a/sys/compat/mach/mach_exec.c       Mon Nov 17 01:44:49 2003 +0000
+++ b/sys/compat/mach/mach_exec.c       Mon Nov 17 01:52:14 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mach_exec.c,v 1.34 2003/09/10 16:45:22 christos Exp $   */
+/*     $NetBSD: mach_exec.c,v 1.35 2003/11/17 01:52:14 manu Exp $       */
 
 /*-
  * Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.34 2003/09/10 16:45:22 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.35 2003/11/17 01:52:14 manu Exp $");
 
 #include "opt_syscall_debug.h"
 
@@ -98,7 +98,7 @@
        NULL,
 #endif
        sendsig,
-       trapsignal,
+       mach_trapsignal,
 #if !defined(__HAVE_SIGINFO) || defined(COMPAT_16)
        sigcode,
        esigcode,
diff -r 807bd48fee89 -r d75677a303c2 sys/compat/mach/mach_notify.c
--- a/sys/compat/mach/mach_notify.c     Mon Nov 17 01:44:49 2003 +0000
+++ b/sys/compat/mach/mach_notify.c     Mon Nov 17 01:52:14 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mach_notify.c,v 1.2 2003/04/05 19:27:51 manu Exp $ */
+/*     $NetBSD: mach_notify.c,v 1.3 2003/11/17 01:52:14 manu Exp $ */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mach_notify.c,v 1.2 2003/04/05 19:27:51 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_notify.c,v 1.3 2003/11/17 01:52:14 manu Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
@@ -53,8 +53,11 @@
 
 #include <compat/mach/mach_types.h>
 #include <compat/mach/mach_exec.h>
+#include <compat/mach/mach_thread.h>
 #include <compat/mach/mach_notify.h>
 
+static void mach_siginfo_to_exception(const struct ksiginfo *, int *);
+
 void
 mach_notify_port_destroyed(l, mr)
        struct lwp *l;
@@ -80,14 +83,11 @@
            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_msgh.msgh_id = MACH_NOTIFY_DESTROYED_MSGID;
        req->req_body.msgh_descriptor_count = 1;
        req->req_rights.name = mr->mr_name;
        req->req_trailer.msgh_trailer_size = 8;
 
-#ifdef KTRACE 
-       ktruser(l->l_proc, "notify_port_destroyed", NULL, 0, 0);
-#endif
        (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",
@@ -127,13 +127,10 @@
            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_msgh.msgh_id = MACH_NOTIFY_NO_SENDERS_MSGID;
        req->req_mscount = mr->mr_refcount;
        req->req_trailer.msgh_trailer_size = 8;
 
-#ifdef KTRACE 
-       ktruser(l->l_proc, "notify_port_no_senders", NULL, 0, 0);
-#endif
        (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",
@@ -171,14 +168,10 @@
            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_msgh.msgh_id = MACH_NOTIFY_DEAD_NAME_MSGID;
        req->req_name = mr->mr_name;
        req->req_trailer.msgh_trailer_size = 8;
 
-#ifdef KTRACE 
-       ktruser(l->l_proc, "notify_port_dead_name", NULL, 0, 0);
-#endif
-
        mr->mr_refcount++;
 
        mp = mr->mr_notify_dead_name->mr_port;
@@ -193,3 +186,245 @@
        return;
 }
 
+
+/* 
+ * Exception handler 
+ * Mach does not use signals, so mach_trapsignal will not try to send
+ * any signal. 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 inhiubit 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 signls if it gets a non zero return value.
+ */
+void
+mach_trapsignal(l, ksi)
+       struct lwp *l;
+       const struct ksiginfo *ksi;
+{
+       (void)mach_trapsignal1(l, ksi);
+       return;
+}
+
+int
+mach_trapsignal1(l, ksi)
+       struct lwp *l;
+       const struct ksiginfo *ksi;
+{
+       struct proc *p = l->l_proc;
+       struct mach_emuldata *med = (struct mach_emuldata *)p->p_emuldata;
+       struct mach_port *exc_port;
+       struct mach_right *task;
+       struct mach_right *thread;
+       int exc_no;
+
+       /* XXX Thread and task should have different ports */
+       task = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
+       thread = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
+
+       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_SOFTWARE;
+               break;
+       default: /* SIGCHLD, SIGPOLL */
+               return EINVAL;
+               break;
+       }
+
+       if ((exc_port = med->med_exc[exc_no]) == NULL)
+               return EINVAL;
+       else
+               return mach_exception(l, ksi, exc_port, exc_no, task, thread);
+}
+
+int
+mach_exception(l, ksi, exc_port, exc, task, thread)
+       struct lwp *l;
+       const struct ksiginfo *ksi;
+       struct mach_port *exc_port;
+       int exc;
+       struct mach_right *task;
+       struct mach_right *thread;
+{
+       int behavior, flavor;
+       mach_msg_header_t *msgh;
+       size_t msglen;
+       struct mach_right *exc_right;
+
+#ifdef DIAGNOSTIC
+       if (exc_port->mp_datatype != MACH_MP_EXC_FLAGS)
+               printf("mach_exception: unexpected datatype");
+#endif
+       behavior = (int)exc_port->mp_data >> 16;
+       flavor = (int)exc_port->mp_data & 0xffff;
+       exc_right = mach_right_get(exc_port, 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_BITS_COMPLEX |
+                   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_local_port = exc_right->mr_name;
+               req->req_msgh.msgh_id = MACH_EXC_RAISE_MSGID;
+               req->req_body.msgh_descriptor_count = 2;
+               req->req_thread.name = thread->mr_name;



Home | Main Index | Thread Index | Old Index