[PATCH v8 1/2 hurd] libirqhelp: Add library

2024-03-07 Thread Damien Zammit
Add a helper library for attaching interrupt handlers in userspace.

---
 Makefile |   1 +
 libirqhelp/Makefile  |  28 
 libirqhelp/irqhelp.c | 359 +++
 libirqhelp/irqhelp.h |  49 ++
 4 files changed, 437 insertions(+)
 create mode 100644 libirqhelp/Makefile
 create mode 100644 libirqhelp/irqhelp.c
 create mode 100644 libirqhelp/irqhelp.h

diff --git a/Makefile b/Makefile
index 874349c06..4d8482219 100644
--- a/Makefile
+++ b/Makefile
@@ -32,6 +32,7 @@ lib-subdirs = libshouldbeinlibc libihash libiohelp libports \
  libhurd-slab \
  libbpf \
  libmachdev \
+ libirqhelp \
 
 # Hurd programs
 prog-subdirs = auth proc exec term \
diff --git a/libirqhelp/Makefile b/libirqhelp/Makefile
new file mode 100644
index 0..c32632abe
--- /dev/null
+++ b/libirqhelp/Makefile
@@ -0,0 +1,28 @@
+# Copyright (C) 2022 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := libirqhelp
+makemode := library
+
+SRCS = irqhelp.c acpiUser.c
+
+OBJS = $(SRCS:.c=.o)
+HURDLIBS =
+LDLIBS += -lpthread
+libname = libirqhelp
+installhdrs = irqhelp.h
+
+include ../Makeconf
diff --git a/libirqhelp/irqhelp.c b/libirqhelp/irqhelp.c
new file mode 100644
index 0..2e8bfcd37
--- /dev/null
+++ b/libirqhelp/irqhelp.c
@@ -0,0 +1,359 @@
+/* Library providing helper functions for userspace irq handling.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "irqhelp.h"
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "acpi_U.h"
+#include 
+#include 
+
+#define IRQ_THREAD_PRIORITY2
+#define log_error(fmt...)  fprintf(stderr, ## fmt)
+
+struct irq {
+  void (*handler)(void *);
+  void *context;
+  int gsi;
+  mach_port_t port;
+  bool enabled;
+  bool shutdown;
+  pthread_mutex_t irqlock;
+  pthread_cond_t irqcond;
+};
+
+static mach_port_t irqdev = MACH_PORT_NULL;
+static mach_port_t acpidev = MACH_PORT_NULL;
+
+static error_t
+get_acpi(void)
+{
+  error_t err = 0;
+  mach_port_t tryacpi, device_master;
+
+  err = get_privileged_ports (0, &device_master);
+  if (!err)
+{
+  err = device_open (device_master, D_READ, "acpi", &tryacpi);
+  mach_port_deallocate (mach_task_self (), device_master);
+  if (!err)
+   {
+ acpidev = tryacpi;
+ return 0;
+   }
+}
+
+  tryacpi = file_name_lookup (_SERVERS_ACPI, O_RDONLY, 0);
+  if (tryacpi == MACH_PORT_NULL)
+return ENODEV;
+
+  acpidev = tryacpi;
+  return 0;
+}
+
+static error_t
+get_irq(void)
+{
+  error_t err = 0;
+  mach_port_t tryirq, device_master;
+
+  err = get_privileged_ports (0, &device_master);
+  if (err)
+return err;
+
+  err = device_open (device_master, D_READ|D_WRITE, "irq", &tryirq);
+  mach_port_deallocate (mach_task_self (), device_master);
+  if (err)
+return err;
+
+  irqdev = tryirq;
+  return err;
+}
+
+static void
+toggle_irq(struct irq *irq, bool on)
+{
+  pthread_mutex_lock (&irq->irqlock);
+  irq->enabled = on;
+  pthread_mutex_unlock (&irq->irqlock);
+
+  if (on)
+pthread_cond_signal (&irq->irqcond);
+}
+
+error_t
+irqhelp_init(void)
+{
+  static bool inited = false;
+  error_t err;
+
+  if (inited)
+{
+  log_error("already inited\n");
+  return 0;
+}
+
+  err = get_irq();
+  if (err)
+{
+  log_error("cannot grab irq device\n");
+  return err;
+}
+
+  err = get_acpi();
+  if (err)
+{
+  log_error("cannot grab acpi device\n");
+  return err;
+}
+
+  inited = true;
+  return 0;
+}
+
+void
+irqhelp

[PATCH v8 0/2 hurd] Add irqhelp and clean up ddekit

2024-03-07 Thread Damien Zammit
Hi,

I think we need to allow the irq handler to be called one more time,
because we don't know if there is a pending interrupt until we need
to handle one.  Once we enable the irq one more time, it is necessary
to handle the last interrupt before quitting the handler.

I tested this behaviour and it works on netdde.static to ifup and ifdown,
and send a large file over ssh.

Damien





[PATCH v8 2/2 hurd] ddekit: Use libirqhelp for interrupt registration

2024-03-07 Thread Damien Zammit
Use the new irqhelp library in ddekit and clean up.

---
 libddekit/Makefile|   2 +-
 libddekit/interrupt.c | 208 ++
 2 files changed, 28 insertions(+), 182 deletions(-)

diff --git a/libddekit/Makefile b/libddekit/Makefile
index 88a0c8909..c74ec1128 100644
--- a/libddekit/Makefile
+++ b/libddekit/Makefile
@@ -39,7 +39,7 @@ LCLHDRS = $(installhdrs)  \
 
 OBJS = $(sort $(SRCS:.c=.o))
 
-HURDLIBS = ports shouldbeinlibc hurd-slab
+HURDLIBS = ports shouldbeinlibc hurd-slab irqhelp
 LDLIBS += -lpthread
 
 MIGCOMSFLAGS = -prefix dde_
diff --git a/libddekit/interrupt.c b/libddekit/interrupt.c
index 35f95a68c..fa6631f83 100644
--- a/libddekit/interrupt.c
+++ b/libddekit/interrupt.c
@@ -4,8 +4,6 @@
  * \author  Christian Helmuth 
  * \date2007-01-22
  *
- * FIXME could intloop_param freed after startup?
- * FIXME use consume flag to indicate IRQ was handled
  */
 
 #include 
@@ -13,153 +11,25 @@
 #include 
 #include 
 
-#include 
-#include 
+#include "libirqhelp/irqhelp.h"
 
-#include "ddekit/interrupt.h"
 #include "ddekit/semaphore.h"
+#include "ddekit/thread.h"
+#include "ddekit/interrupt.h"
 #include "ddekit/printf.h"
-#include "ddekit/memory.h"
-#include "ddekit/condvar.h"
-
-#define DEBUG_INTERRUPTS  0
 
 #define MAX_INTERRUPTS   32
 
-#define BLOCK_IRQ 0
-
-/*
- * Internal type for interrupt loop parameters
- */
-struct intloop_params
-{
-   unsigned  irq;   /* irq number */
-   int   shared;/* irq sharing supported? */
-   void(*thread_init)(void *);  /* thread initialization */
-   void(*handler)(void *);  /* IRQ handler function */
-   void *priv;  /* private token */ 
-   mach_port_t   irqport;   /* delivery port for notifications */
-   ddekit_sem_t *started;
-
-   int   start_err;
-};
-
 static struct
 {
int  handle_irq; /* nested irq disable count */
ddekit_lock_tirqlock;
-   struct ddekit_condvar   *cond;
-   ddekit_thread_t  *irq_thread; /* thread ID for detaching from IRQ later 
on */
-   boolean_tthread_exit;
thread_t mach_thread;
+   ddekit_thread_t  *irq_thread;
+   ddekit_sem_t *started;
+   void *irqhelp;   /* irqhelp instance for detaching from IRQ 
*/
 } ddekit_irq_ctrl[MAX_INTERRUPTS];
 
-static mach_port_t master_host;
-static mach_port_t master_device;
-static device_t irq_dev;
-
-/**
- * Interrupt service loop
- *
- */
-static void intloop(void *arg)
-{
-   kern_return_t ret;
-   struct intloop_params *params = arg;
-   mach_port_t delivery_port;
-   mach_port_t pset, psetcntl;
-   int my_index;
-
-   ret = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
- &delivery_port);
-   if (ret)
- error (2, ret, "mach_port_allocate");
-
-   my_index = params->irq;
-   params->irqport = delivery_port;
-   ddekit_irq_ctrl[my_index].mach_thread = mach_thread_self ();
-   ret = thread_get_assignment (mach_thread_self (), &pset);
-   if (ret)
-   error (0, ret, "thread_get_assignment");
-   ret = host_processor_set_priv (master_host, pset, &psetcntl);
-   if (ret)
-   error (0, ret, "host_processor_set_priv");
-   thread_max_priority (mach_thread_self (), psetcntl, 0);
-   ret = thread_priority (mach_thread_self (), DDEKIT_IRQ_PRIO, 0);
-   if (ret)
-   error (0, ret, "thread_priority");
-
-   // TODO the flags for shared irq should be indicated by params->shared.
-   // Flags needs to be 0 for new irq interface for now.
-   // Otherwise, the interrupt handler cannot be installed in the kernel.
-   ret = device_intr_register (irq_dev, my_index,
- 0, delivery_port,
- MACH_MSG_TYPE_MAKE_SEND);
-   ddekit_printf ("device_intr_register returns %d\n", ret);
-   if (ret) {
-   /* inform thread creator of error */
-   /* XXX does omega0 error code have any meaning to DDEKit users? 
*/
-   params->start_err = ret;
-   ddekit_sem_up(params->started);
-   ddekit_printf ("cannot install irq %d\n", my_index);
-   return;
-   }
-
-#if 0
-   /* 
-* Setup an exit fn. This will make sure that we clean up everything,
-* before shutting down an IRQ thread.
-*/
-   if (l4thread_on_exit(&exit_fn, (void *)my_index) < 0)
-   ddekit_panic("Could not set exit handler for IRQ fn.");
-#endif
-
-   /* after successful initialization call thread_init() before doing 
anything
-* else here */
-   if (params->thread_init) params->thread_init(params->priv);
-
-   /* save handle + inform thread creator of success */
-   params->start_err = 0;
-   ddekit_sem_up(params->started);
-
-   int irq_