summaryrefslogtreecommitdiff
path: root/debian/patches/700003-Rework-comment-on-the-userspace-interrupt-handling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/700003-Rework-comment-on-the-userspace-interrupt-handling.patch')
-rw-r--r--debian/patches/700003-Rework-comment-on-the-userspace-interrupt-handling.patch284
1 files changed, 284 insertions, 0 deletions
diff --git a/debian/patches/700003-Rework-comment-on-the-userspace-interrupt-handling.patch b/debian/patches/700003-Rework-comment-on-the-userspace-interrupt-handling.patch
new file mode 100644
index 0000000..8ad50ef
--- /dev/null
+++ b/debian/patches/700003-Rework-comment-on-the-userspace-interrupt-handling.patch
@@ -0,0 +1,284 @@
+From 652cbc1f88f02f92096051a7ce13dcbf77e55fc4 Mon Sep 17 00:00:00 2001
+From: Justus Winter <justus@gnupg.org>
+Date: Thu, 25 Feb 2016 20:54:22 +0100
+Subject: [PATCH gnumach 3/9] Rework/comment on the userspace interrupt
+ handling
+
+---
+ device/ds_routines.c | 8 +++----
+ device/interrupt.h | 14 ++++++++++++
+ device/intr.c | 37 +++++++++++++++---------------
+ kern/startup.c | 2 +-
+ linux/dev/arch/i386/kernel/irq.c | 49 ++++++++++++++++++----------------------
+ 5 files changed, 58 insertions(+), 52 deletions(-)
+ create mode 100644 device/interrupt.h
+
+diff --git a/device/ds_routines.c b/device/ds_routines.c
+index 9d399ee..7a5dda5 100644
+--- a/device/ds_routines.c
++++ b/device/ds_routines.c
+@@ -325,9 +325,7 @@ experimental_device_intr_register (ipc_port_t master_port, int line,
+ #ifdef MACH_XEN
+ return D_INVALID_OPERATION;
+ #else /* MACH_XEN */
+- extern int install_user_intr_handler (unsigned int line,
+- unsigned long flags,
+- ipc_port_t dest);
++ struct intr_entry *entry;
+ io_return_t ret;
+
+ /* Open must be called on the master device port. */
+@@ -338,13 +336,13 @@ experimental_device_intr_register (ipc_port_t master_port, int line,
+ if (line < 0 || line >= 16)
+ return D_INVALID_OPERATION;
+
+- ret = insert_intr_entry (line, receive_port);
++ ret = insert_intr_entry (line, receive_port, &entry);
+ if (ret)
+ return ret;
+ // TODO The original port should be replaced
+ // when the same device driver calls it again,
+ // in order to handle the case that the device driver crashes and restarts.
+- ret = install_user_intr_handler (line, flags, receive_port);
++ ret = install_user_intr_handler (line, flags, entry);
+
+ /* If the port is installed successfully, increase its reference by 1.
+ * Thus, the port won't be destroyed after its task is terminated. */
+diff --git a/device/interrupt.h b/device/interrupt.h
+new file mode 100644
+index 0000000..0de43c2
+--- /dev/null
++++ b/device/interrupt.h
+@@ -0,0 +1,14 @@
++#ifndef DEVICE_INTERRUPT_H
++#define DEVICE_INTERRUPT_H
++
++struct intr_entry;
++boolean_t queue_intr (struct intr_entry *e);
++int insert_intr_entry (int line, ipc_port_t dest, struct intr_entry **entry);
++
++int install_user_intr_handler (unsigned int line,
++ unsigned long flags,
++ struct intr_entry *entry);
++
++void intr_thread (void);
++
++#endif /* DEVICE_INTERRUPT_H */
+diff --git a/device/intr.c b/device/intr.c
+index 02e0bab..986f0ee 100644
+--- a/device/intr.c
++++ b/device/intr.c
+@@ -3,6 +3,8 @@
+ #include <kern/queue.h>
+ #include <kern/printf.h>
+
++#include "interrupt.h"
++
+ #ifndef MACH_XEN
+ // TODO this is only for x86 system
+ #define sti() __asm__ __volatile__ ("sti": : :"memory")
+@@ -35,29 +37,35 @@ search_intr (int line, ipc_port_t dest)
+ return NULL;
+ }
+
+-void intr_thread (void);
+-
+ /* This function can only be used in the interrupt handler. */
+-void
+-queue_intr (int line, ipc_port_t dest)
++boolean_t
++queue_intr (struct intr_entry *e)
+ {
+- struct intr_entry *e;
+-
++ /* The reference of the port was increased when the port was
++ * installed. If the reference is 1, it means the port should have
++ * been destroyed and I destroy it now. */
++ if (e->dest && e->dest->ip_references == 1)
++ {
++ ipc_port_release (e->dest);
++ e->dest = NULL;
++ printk ("irq handler %d: release an dead delivery port\n", e->line);
++ return FALSE;
++ }
++
+ cli ();
+- e = search_intr (line, dest);
+- assert (e);
+ e->interrupts++;
+ tot_num_intr++;
+ sti ();
+
+ thread_wakeup ((event_t) &intr_thread);
++ return TRUE;
+ }
+
+ /* insert an interrupt entry in the queue.
+ * This entry exists in the queue until
+ * the corresponding interrupt port is removed.*/
+ int
+-insert_intr_entry (int line, ipc_port_t dest)
++insert_intr_entry (int line, ipc_port_t dest, struct intr_entry **entry)
+ {
+ int err = 0;
+ struct intr_entry *e, *new;
+@@ -86,19 +94,10 @@ out:
+ sti ();
+ if (free)
+ kfree ((vm_offset_t) new, sizeof (*new));
++ *entry = new;
+ return err;
+ }
+
+-/* this function should be called when line is disabled. */
+-void mark_intr_removed (int line, ipc_port_t dest)
+-{
+- struct intr_entry *e;
+-
+- e = search_intr (line, dest);
+- if (e)
+- e->dest = NULL;
+-}
+-
+ void
+ intr_thread ()
+ {
+diff --git a/kern/startup.c b/kern/startup.c
+index 05de5e6..0a571ff 100644
+--- a/kern/startup.c
++++ b/kern/startup.c
+@@ -62,6 +62,7 @@
+ #include <machine/model_dep.h>
+ #include <mach/version.h>
+ #include <device/device_init.h>
++#include <device/interrupt.h>
+
+ #if MACH_KDB
+ #include <device/cons.h>
+@@ -79,7 +80,6 @@ boolean_t reboot_on_panic = TRUE;
+ /* XX */
+ extern vm_offset_t phys_first_addr, phys_last_addr;
+ extern char *kernel_cmdline;
+-extern void intr_thread();
+
+ /*
+ * Running in virtual memory, on the interrupt stack.
+diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c
+index b7dfa1a..15f95c3 100644
+--- a/linux/dev/arch/i386/kernel/irq.c
++++ b/linux/dev/arch/i386/kernel/irq.c
+@@ -49,6 +49,7 @@
+
+ #include <linux/dev/glue/glue.h>
+ #include <machine/machspl.h>
++#include <device/interrupt.h>
+
+ #if 0
+ /* XXX: This is the way it's done in linux 2.2. GNU Mach currently uses intr_count. It should be made using local_{bh/irq}_count instead (through hardirq_enter/exit) for SMP support. */
+@@ -83,7 +84,7 @@ struct linux_action
+ void *dev_id;
+ struct linux_action *next;
+ unsigned long flags;
+- volatile ipc_port_t delivery_port;
++ struct intr_entry *userspace_handler;
+ };
+
+ static struct linux_action *irq_action[16] =
+@@ -117,31 +118,19 @@ linux_intr (int irq)
+ {
+ // TODO I might need to check whether the interrupt belongs to
+ // the current device. But I don't do it for now.
+- if (action->delivery_port)
++ if (action->userspace_handler)
+ {
+- /* The reference of the port was increased
+- * when the port was installed.
+- * If the reference is 1, it means the port should
+- * have been destroyed and I destroy it now. */
+- if (action->delivery_port
+- && action->delivery_port->ip_references == 1)
+- {
+- mark_intr_removed (irq, action->delivery_port);
+- ipc_port_release (action->delivery_port);
+- *prev = action->next;
+- printk ("irq handler %d: release an dead delivery port\n", irq);
+- linux_kfree(action);
+- action = *prev;
+- continue;
+- }
+- else
+- {
+ /* We disable the irq here and it will be enabled
+ * after the interrupt is handled by the user space driver. */
+ disable_irq (irq);
+- queue_intr (irq, action->delivery_port);
+- }
+-
++ if (! queue_intr (action->userspace_handler))
++ {
++ *prev = action->next;
++ linux_kfree(action);
++ action = *prev;
++ enable_irq (irq);
++ continue;
++ }
+ }
+ else if (action->handler)
+ action->handler (irq, action->dev_id, &regs);
+@@ -285,26 +274,32 @@ setup_x86_irq (int irq, struct linux_action *new)
+
+ int
+ install_user_intr_handler (unsigned int irq, unsigned long flags,
+- ipc_port_t dest)
++ struct intr_entry *entry)
+ {
+ struct linux_action *action;
++#if 0
+ struct linux_action *old;
++#endif
+ int retval;
+
+ assert (irq < 16);
+
+- /* Test whether the irq handler has been set */
++#if 0
++ /* Test whether the irq handler has already been set. */
++ /* JW: Actually, that cannot happen. We test for that in
++ device_intr_register before calling this function. */
+ // TODO I need to protect the array when iterating it.
+ old = irq_action[irq];
+ while (old)
+ {
+- if (old->delivery_port == dest)
++ if (old->delivery_port == entry->dest)
+ {
+ printk ("The interrupt handler has been installed on line %d", irq);
+ return linux_to_mach_error (-EAGAIN);
+ }
+ old = old->next;
+ }
++#endif
+
+ /*
+ * Hmm... Should I use `kalloc()' ?
+@@ -319,7 +314,7 @@ install_user_intr_handler (unsigned int irq, unsigned long flags,
+ action->next = NULL;
+ action->dev_id = NULL;
+ action->flags = flags;
+- action->delivery_port = dest;
++ action->userspace_handler = entry;
+
+ retval = setup_x86_irq (irq, action);
+ if (retval)
+@@ -356,7 +351,7 @@ request_irq (unsigned int irq, void (*handler) (int, void *, struct pt_regs *),
+ action->next = NULL;
+ action->dev_id = dev_id;
+ action->flags = flags;
+- action->delivery_port = NULL;
++ action->userspace_handler = NULL;
+
+ retval = setup_x86_irq (irq, action);
+ if (retval)
+--
+2.1.4
+