]> git.corax.cc Git - corax/commitdiff
Implement mechanism to deliver hardware interrupts to userspace processes by
authorMatthias Kruk <m@m10k.eu>
Tue, 14 Jan 2020 12:23:45 +0000 (21:23 +0900)
committerMatthias Kruk <m@m10k.eu>
Tue, 14 Jan 2020 12:23:45 +0000 (21:23 +0900)
co-opting the sigaction() syscall in combination with a new signal, SIGHWINT.
The signal mask that is passed to sigaction() by means of a struct sigaction
is used to notify the kernel which interrupts the process would like to receive.
Processes that choose to use the same handler for multiple hardware interrupts
should set the SA_SIGINFO flag in the sigaction structure. The interrupt handler
will then be passed an additional siginfo_t structure (and a struct ucontext*)
which can be used to find out the hardware interrupt number by inspecting the
siginfo_t structure's si_trapno member.

config.h
kernel/arch/interrupt.c
kernel/core/Makefile
kernel/core/posixcall.c
kernel/core/process.c
kernel/core/signal.c [new file with mode: 0644]

index 758607f3e1d4c75e412233f6e212d52198306a7e..6c9834b76d6f1fbe8b9459155259fc10754b8485 100644 (file)
--- a/config.h
+++ b/config.h
@@ -37,6 +37,8 @@
 #define CONFIG_SMP      0
 #define CONFIG_SMP_CPUS 1
 
+#define CONFIG_IRQ_QLEN 2
+
 #define CONFIG_POSIX    1
 
 #define CONFIG_PAGING_DIR_MAXREGIONS 16
index 3b0bdf0ee98c1bcccb92eb537a99a5c735cef2db..14b8cc19d52b0e9cb635b1841dbef344fc319566 100644 (file)
@@ -35,8 +35,7 @@ extern int sys_cxnet(long, long, long, long, long, long, long);
 extern int sys_cxipc(long, long, long);
 #if FEATURE(POSIX)
 extern int sys_posixcall(stack_frame_t*);
-/* extern void _sig_hwint_deliver(const int); */
-#define _sig_hwint_deliver(foo)
+extern void _sig_hwint_deliver(const int);
 #endif /* FEATURE(POSIX) */
 
 static const char *_exc_name[] = {
index 0421f3fa7bbf530ffc0d137953d63b1bb2d559a5..4d13743669b2bff82d0c55edafa089f33f608307 100644 (file)
@@ -1,4 +1,4 @@
-OBJECTS = main.o process.o sched.o cxipc.o syscall.o posixcall.o net.o stdio.o
+OBJECTS = main.o process.o sched.o cxipc.o syscall.o posixcall.o net.o signal.o
 OUTPUT = core.o
 INCLUDES = -I../include -I../../include -I../..
 CFLAGS += $(INCLUDES)
index 7fe4b57b446d3a3e02fab38ae7fa209f3d8605b1..2f47e9fd145b7c75a3b0272ce419b400feed6149 100644 (file)
@@ -10,6 +10,8 @@
 #include <debug.h>
 #include <string.h>
 
+int sys_sigaction(stack_frame_t*);
+
 int sys_exit(int status)
 {
        process_t *proc;
@@ -492,6 +494,10 @@ int sys_posixcall(stack_frame_t *stk)
                ret_val = sys_outb(stk);
                break;
 
+       case SYS_SIGACTION:
+               ret_val = sys_sigaction(stk);
+               break;
+
 #if FEATURE(DEBUG_SYSDEBUG)
        case SYS_DEBUG:
                ret_val = sys_debug((const char*)stk->ebx, (u32_t)stk->ecx);
index 3102317a8ee4fd21e3ab1d6793e61ea870f59443..068c75868629ae0a1393e026a8ce86ec3a062309 100644 (file)
@@ -1044,3 +1044,16 @@ void* process_get_sighandler(process_t *proc, int signal)
 
        return((void*)proc->p_sighandler[signal]);
 }
+
+void _process_hwint_deliver(pid_t pid, int irq)
+{
+       process_t *proc;
+
+       proc = process_lookup(pid);
+
+       if(proc) {
+               process_signal_deliver(proc, SIGHWINT);
+       }
+
+       return;
+}
diff --git a/kernel/core/signal.c b/kernel/core/signal.c
new file mode 100644 (file)
index 0000000..eae38f8
--- /dev/null
@@ -0,0 +1,103 @@
+#include <config.h>
+#include <corax/types.h>
+#include <corax/errno.h>
+#include <arch.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <process.h>
+
+struct intq {
+       pid_t handlers[CONFIG_IRQ_QLEN];
+};
+
+struct intq _int_q[32];
+
+void _process_hwint_deliver(pid_t, int);
+
+void _sig_hwint_deliver(const int irq)
+{
+       struct intq *q;
+       int i;
+
+       /* make sure we don't make invalid accesses to _int_q */
+       if(irq < 1 || irq >= (sizeof(_int_q) / sizeof(_int_q[0]))) {
+               return;
+       }
+
+       q = &(_int_q[irq]);
+
+       for(i = 0; i < (sizeof(q->handlers) / sizeof(q->handlers[0])); i++) {
+
+               /* we're at the end of the queue if the entry is invalid */
+               if(q->handlers[i] <= 0) {
+                       break;
+               }
+
+               /* deliver hardware interrupt to process */
+               _process_hwint_deliver(q->handlers[i], irq);
+       }
+
+       return;
+}
+
+int sys_sigaction(stack_frame_t *stk)
+{
+       int signum;
+       struct sigaction new;
+       struct sigaction *old;
+       process_t *cproc;
+       int ret_val;
+
+       cproc = process_get_current();
+
+       /* get the user-provided data */
+       signum = (int)stk->ebx;
+       old = (struct sigaction*)stk->edx;
+       process_memcpy_ptok(cproc, &new, (void*)stk->ecx, sizeof(new));
+
+       switch(signum) {
+       case SIGHWINT:
+               /* this is the Corax way to notify processes about hardware interrupts */
+
+               ret_val = 0;
+               break;
+
+               /* filter signals the user is not supposed to override */
+       default:
+       case SIGHUP:
+       case SIGINT:
+       case SIGQUIT:
+       case SIGILL:
+       case SIGTRAP:
+       case SIGABRT:
+       case SIGBUS:
+       case SIGFPE:
+       case SIGKILL:
+       case SIGUSR1:
+       case SIGSEGV:
+       case SIGUSR2:
+       case SIGPIPE:
+       case SIGALRM:
+       case SIGTERM:
+       case SIGSTKFLT:
+       case SIGCHLD:
+       case SIGCONT:
+       case SIGSTOP:
+       case SIGTSTP:
+       case SIGTTIN:
+       case SIGTTOU:
+       case SIGURG:
+       case SIGXCPU:
+       case SIGXFSZ:
+       case SIGVTALRM:
+       case SIGPROF:
+       case SIGWINCH:
+       case SIGIO:
+       case SIGPWR:
+       case SIGSYS:
+               ret_val = -EINVAL;
+               break;
+       }
+
+       return(ret_val);
+}