From 2cf0c62f09dc2069a9446a5a694bb73dd1322108 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Sat, 27 Feb 2016 09:10:23 +0100 Subject: No need for a new kind of notification, we can provide a smoother upgrade path --- device/ds_routines.c | 5 +++-- device/interrupt.h | 8 ++++--- device/intr.c | 63 +++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 60 insertions(+), 16 deletions(-) (limited to 'device') diff --git a/device/ds_routines.c b/device/ds_routines.c index 74569aa..a54bb0e 100644 --- a/device/ds_routines.c +++ b/device/ds_routines.c @@ -333,7 +333,7 @@ experimental_device_intr_register (ipc_port_t master_port, int line, if (master_port != master_device_port) return D_INVALID_OPERATION; - if (receive_port == MACH_PORT_NULL) + if (receive_port == IP_NULL) return D_INVALID_OPERATION; /* XXX: move to arch-specific */ @@ -362,7 +362,7 @@ experimental_device_intr_register2 (ipc_port_t master_port, int line, if (master_port != master_device_port) return D_INVALID_OPERATION; - if (notification_port == MACH_PORT_NULL) + if (notification_port == IP_NULL) return D_INVALID_OPERATION; /* XXX: move to arch-specific */ @@ -1860,6 +1860,7 @@ device_writev_trap (mach_device_t device, dev_mode_t mode, kern_return_t experimental_device_intr_enable(ipc_port_t master_port, int line, char status) { + return D_INVALID_OPERATION; #ifdef MACH_XEN return D_INVALID_OPERATION; #else /* MACH_XEN */ diff --git a/device/interrupt.h b/device/interrupt.h index 12e6efc..7a00456 100644 --- a/device/interrupt.h +++ b/device/interrupt.h @@ -24,11 +24,13 @@ kern_return_t insert_intr_entry (int line, ipc_port_t dest, int new_style, /* version2 notifications? */ struct intr_entry **entry); +boolean_t intr_entry_notify (mach_msg_header_t *msg); +void intr_thread (void); + +/* linux/dev/arch/i386/kernel/irq.c */ int install_user_intr_handler (unsigned int line, unsigned long flags, struct intr_entry *entry); - -boolean_t intr_entry_notify (mach_msg_header_t *msg); -void intr_thread (void); +int remove_user_intr_handler (unsigned int irq, struct intr_entry *entry); #endif /* DEVICE_INTERRUPT_H */ diff --git a/device/intr.c b/device/intr.c index 143bed3..5033d93 100644 --- a/device/intr.c +++ b/device/intr.c @@ -172,9 +172,23 @@ intr_entry_port_lookup (ipc_port_t port) boolean_t intr_entry_notify (mach_msg_header_t *msg) { - if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME) + struct intr_entry *entry; + + if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS) + { + extern void enable_irq (unsigned int irq_nr); + mach_no_senders_notification_t *ns; + + ns = (mach_no_senders_notification_t *) msg; + entry = intr_entry_port_lookup + ((ipc_port_t) ns->not_header.msgh_remote_port); + assert (entry); + + enable_irq (entry->line); /* entry is not locked here */ + return TRUE; + } + else if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME) { - struct intr_entry *entry; int line; mach_dead_name_notification_t *dn; unsigned long flags; @@ -188,6 +202,7 @@ intr_entry_notify (mach_msg_header_t *msg) line = entry->line; assert (!queue_empty (&intr_queue)); queue_remove (&intr_queue, entry, struct intr_entry *, chain); + remove_user_intr_handler (entry->line, entry); cpu_intr_restore (flags); ipc_port_dealloc_kernel (entry->port); @@ -212,7 +227,8 @@ init_mach_intr_notification (mach_intr_notification_t *n) mach_msg_header_t *m = &n->intr_header; mach_msg_type_t *t = &n->intr_type; - m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); + m->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_PORT_SEND, + MACH_MSG_TYPE_PORT_SEND); m->msgh_size = sizeof *n; m->msgh_seqno = INTR_NOTIFY_MSGH_SEQNO; m->msgh_local_port = MACH_PORT_NULL; @@ -229,10 +245,11 @@ init_mach_intr_notification (mach_intr_notification_t *n) } static boolean_t -deliver_intr (int line, ipc_port_t dest_port) +deliver_intr (int line, ipc_port_t dest_port, ipc_port_t interrupt_port) { ipc_kmsg_t kmsg; mach_intr_notification_t *n; + ipc_port_t sright, sonce, old; mach_port_t dest = (mach_port_t) dest_port; if (dest == MACH_PORT_NULL) @@ -246,7 +263,17 @@ deliver_intr (int line, ipc_port_t dest_port) n = (mach_intr_notification_t *) &kmsg->ikm_header; *n = mach_intr_notification_template; + /* Arrange no-senders notification. */ + sright = ipc_port_make_send (interrupt_port); + sonce = ipc_port_make_sonce (interrupt_port); + ip_lock (interrupt_port); + ipc_port_nsrequest (interrupt_port, interrupt_port->ip_mscount, + sonce, &old); + if (old != IP_NULL) + ipc_port_release_sonce (old); + n->intr_header.msgh_remote_port = dest; + n->intr_header.msgh_local_port = (mach_port_t) sright; n->line = line; ipc_port_copy_send (dest_port); @@ -269,7 +296,7 @@ init_mach_intr_notification2 (mach_intr_notification2_t *n) m->msgh_seqno = INTR_NOTIFY_MSGH_SEQNO; m->msgh_local_port = MACH_PORT_NULL; m->msgh_remote_port = MACH_PORT_NULL; - m->msgh_id = MACH_INTR_NOTIFY; + m->msgh_id = MACH_INTR_NOTIFY2; t->msgt_name = MACH_MSG_TYPE_INTEGER_32; t->msgt_size = 32; @@ -289,7 +316,7 @@ init_mach_intr_notification2 (mach_intr_notification2_t *n) t->msgt_unused = 0; t = &n->port_type; - t->msgt_name = MACH_MSG_TYPE_MAKE_SEND; + t->msgt_name = MACH_MSG_TYPE_MOVE_SEND; t->msgt_size = 32; t->msgt_number = 1; t->msgt_inline = TRUE; @@ -304,6 +331,7 @@ deliver_intr_notification2 (ipc_port_t notification_port, ipc_port_t interrupt_port) { ipc_kmsg_t kmsg; + ipc_port_t sright, sonce, old; mach_intr_notification2_t *n; assert (notification_port); @@ -317,10 +345,19 @@ deliver_intr_notification2 (ipc_port_t notification_port, n = (mach_intr_notification2_t *) &kmsg->ikm_header; *n = mach_intr_notification2_template; + /* Arrange no-senders notification. */ + sright = ipc_port_make_send (interrupt_port); + sonce = ipc_port_make_sonce (interrupt_port); + ip_lock (interrupt_port); + ipc_port_nsrequest (interrupt_port, interrupt_port->ip_mscount, + sonce, &old); + if (old != IP_NULL) + ipc_port_release_sonce (old); + n->intr_header.msgh_remote_port = (mach_port_t) notification_port; n->line = line; n->count = count; - n->interrupt_port = (mach_port_t) interrupt_port; + n->interrupt_port = (mach_port_t) sright; ipc_port_copy_send (notification_port); ipc_mqueue_send_always(kmsg); @@ -351,16 +388,18 @@ intr_thread () queue_iterate (&intr_queue, e, struct intr_entry *, chain) if (e->interrupts) { + int ok; + ipc_port_t interrupt_port = e->port; + int count = e->interrupts; line = e->line; dest = e->dest; if (e->new_style) { - ipc_port_t interrupt_port = e->port; - int count = e->interrupts; e->interrupts = 0; cpu_intr_restore (flags); - deliver_intr_notification2 (dest, line, count, interrupt_port); + ok = deliver_intr_notification2 (dest, line, count, interrupt_port); + printf ("new: count? %d ok? %d\n", count, ok); cpu_intr_save (&flags); } else @@ -368,8 +407,10 @@ intr_thread () e->interrupts--; cpu_intr_restore (flags); - deliver_intr (line, dest); + deliver_intr (line, dest, interrupt_port); cpu_intr_save (&flags); + + assert (e->interrupts == 0); } /* We cannot assume that e still exists at this point -- cgit v1.2.3