From: Matthias Kruk Date: Tue, 14 Jan 2020 12:23:45 +0000 (+0900) Subject: Implement mechanism to deliver hardware interrupts to userspace processes by X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=b18e30fb75e90608f9daf8cd2d05f92216ca9d0b;p=corax Implement mechanism to deliver hardware interrupts to userspace processes by 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. --- diff --git a/config.h b/config.h index 758607f..6c9834b 100644 --- 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 diff --git a/kernel/arch/interrupt.c b/kernel/arch/interrupt.c index 3b0bdf0..14b8cc1 100644 --- a/kernel/arch/interrupt.c +++ b/kernel/arch/interrupt.c @@ -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[] = { diff --git a/kernel/core/Makefile b/kernel/core/Makefile index 0421f3f..4d13743 100644 --- a/kernel/core/Makefile +++ b/kernel/core/Makefile @@ -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) diff --git a/kernel/core/posixcall.c b/kernel/core/posixcall.c index 7fe4b57..2f47e9f 100644 --- a/kernel/core/posixcall.c +++ b/kernel/core/posixcall.c @@ -10,6 +10,8 @@ #include #include +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); diff --git a/kernel/core/process.c b/kernel/core/process.c index 3102317..068c758 100644 --- a/kernel/core/process.c +++ b/kernel/core/process.c @@ -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 index 0000000..eae38f8 --- /dev/null +++ b/kernel/core/signal.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include + +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); +}