Sat Jan 21 22:09:57 2012 UTC ()
Complete rewrite of the signal and spl framework for NetBSD/usermode
Signals are now moved from the sigaltstack ASAP and stacked on a replacement
stack for each processes.
Preemption now works though could be enhanced a bit more
(reinoud)
diff -r1.25 -r1.26 src/sys/arch/usermode/dev/clock.c
diff -r1.68 -r1.69 src/sys/arch/usermode/dev/cpu.c
diff -r1.4 -r1.5 src/sys/arch/usermode/dev/if_veth.c
diff -r1.29 -r1.30 src/sys/arch/usermode/dev/ld_thunkbus.c
diff -r1.17 -r1.18 src/sys/arch/usermode/dev/ttycons.c
diff -r1.6 -r1.7 src/sys/arch/usermode/include/intr.h
diff -r1.14 -r1.15 src/sys/arch/usermode/usermode/intr.c
diff -r1.60 -r1.61 src/sys/arch/usermode/usermode/trap.c
--- src/sys/arch/usermode/dev/clock.c 2012/01/14 21:42:51 1.25
+++ src/sys/arch/usermode/dev/clock.c 2012/01/21 22:09:56 1.26
@@ -1,4 +1,4 @@
-/* $NetBSD: clock.c,v 1.25 2012/01/14 21:42:51 reinoud Exp $ */
+/* $NetBSD: clock.c,v 1.26 2012/01/21 22:09:56 reinoud Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@@ -29,7 +29,7 @@
#include "opt_hz.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.25 2012/01/14 21:42:51 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.26 2012/01/21 22:09:56 reinoud Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -50,11 +50,14 @@
static int clock_match(device_t, cfdata_t, void *);
static void clock_attach(device_t, device_t, void *);
-static void clock_signal(int sig, siginfo_t *info, void *ctx);
static unsigned int clock_getcounter(struct timecounter *);
static int clock_todr_gettime(struct todr_chip_handle *, struct timeval *);
+extern void setup_clock_intr(void);
+void clock_intr(void *priv);
+
+
struct clock_softc {
device_t sc_dev;
struct todr_chip_handle sc_todr;
@@ -72,6 +75,7 @@
};
timer_t clock_timerid;
+int clock_running = 0;
CFATTACH_DECL_NEW(clock, sizeof(struct clock_softc),
clock_match, clock_attach, NULL, NULL);
@@ -90,7 +94,6 @@
static void
clock_attach(device_t parent, device_t self, void *opaque)
{
- static struct sigaction sa;
struct clock_softc *sc = device_private(self);
aprint_naive("\n");
@@ -101,21 +104,15 @@
sc->sc_todr.todr_gettime = clock_todr_gettime;
todr_attach(&sc->sc_todr);
- memset(&sa, 0, sizeof(sa));
- thunk_sigemptyset(&sa.sa_mask);
- sa.sa_sigaction = clock_signal;
- sa.sa_flags = SA_RESTART | SA_ONSTACK;
- if (thunk_sigaction(SIGALRM, &sa, NULL) == -1)
- panic("couldn't register SIGALRM handler : %d",
- thunk_geterrno());
-
clock_timerid = thunk_timer_attach();
-
clock_timecounter.tc_quality = 1000;
tc_init(&clock_timecounter);
+
+ setup_clock_intr();
+ clock_running = 1;
}
-static void
+void
clock_intr(void *priv)
{
struct clockframe cf;
@@ -126,13 +123,6 @@
}
}
-static void
-clock_signal(int sig, siginfo_t *info, void *ctx)
-{
- curcpu()->ci_idepth++;
- spl_intr(IPL_SOFTCLOCK, clock_intr, NULL);
- curcpu()->ci_idepth--;
-}
static unsigned int
clock_getcounter(struct timecounter *tc)
--- src/sys/arch/usermode/dev/cpu.c 2012/01/18 19:17:02 1.68
+++ src/sys/arch/usermode/dev/cpu.c 2012/01/21 22:09:56 1.69
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.68 2012/01/18 19:17:02 reinoud Exp $ */
+/* $NetBSD: cpu.c,v 1.69 2012/01/21 22:09:56 reinoud Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@@ -30,7 +30,7 @@
#include "opt_hz.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.68 2012/01/18 19:17:02 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.69 2012/01/21 22:09:56 reinoud Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -244,12 +244,13 @@
thunk_makecontext(&sc->sc_ucp, (void (*)(void)) cpu_switchto_atomic,
2, oldlwp, newlwp, NULL);
- if (!oldpcb) {
- thunk_setcontext(&sc->sc_ucp);
- /* never returns */
- } else {
+ KASSERT(sc);
+ if (oldpcb) {
thunk_swapcontext(&oldpcb->pcb_ucp, &sc->sc_ucp);
/* returns here */
+ } else {
+ thunk_setcontext(&sc->sc_ucp);
+ /* never returns */
}
#ifdef CPU_DEBUG
@@ -374,8 +375,10 @@
/* get l2 its own stack */
pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack;
pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack;
- pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp;
+
+ thunk_sigemptyset(&pcb2->pcb_ucp.uc_sigmask);
+ pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
thunk_makecontext(&pcb2->pcb_ucp,
(void (*)(void)) cpu_lwp_trampoline,
3, &pcb2->pcb_ucp, func, arg);
@@ -412,7 +415,9 @@
/* init lwp0 */
memset(&lwp0pcb, 0, sizeof(lwp0pcb));
thunk_getcontext(&lwp0pcb.pcb_ucp);
+ thunk_sigemptyset(&lwp0pcb.pcb_ucp.uc_sigmask);
lwp0pcb.pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
+
uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb);
memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
--- src/sys/arch/usermode/dev/if_veth.c 2012/01/15 10:51:12 1.4
+++ src/sys/arch/usermode/dev/if_veth.c 2012/01/21 22:09:56 1.5
@@ -1,4 +1,4 @@
-/* $NetBSD: if_veth.c,v 1.4 2012/01/15 10:51:12 jmcneill Exp $ */
+/* $NetBSD: if_veth.c,v 1.5 2012/01/21 22:09:56 reinoud Exp $ */
/*-
* Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_veth.c,v 1.4 2012/01/15 10:51:12 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_veth.c,v 1.5 2012/01/21 22:09:56 reinoud Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -189,10 +189,7 @@
{
struct veth_softc *sc = priv;
- curcpu()->ci_idepth++;
- spl_intr(IPL_NET, softint_schedule, sc->sc_rx_intr);
- curcpu()->ci_idepth--;
-
+ softint_schedule(sc->sc_rx_intr);
return 0;
}
--- src/sys/arch/usermode/dev/ld_thunkbus.c 2012/01/09 21:01:31 1.29
+++ src/sys/arch/usermode/dev/ld_thunkbus.c 2012/01/21 22:09:57 1.30
@@ -1,4 +1,4 @@
-/* $NetBSD: ld_thunkbus.c,v 1.29 2012/01/09 21:01:31 reinoud Exp $ */
+/* $NetBSD: ld_thunkbus.c,v 1.30 2012/01/21 22:09:57 reinoud Exp $ */
/*-
* Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_thunkbus.c,v 1.29 2012/01/09 21:01:31 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_thunkbus.c,v 1.30 2012/01/21 22:09:57 reinoud Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -145,9 +145,7 @@
struct ld_softc *ld = arg;
struct ld_thunkbus_softc *sc = (struct ld_thunkbus_softc *)ld;
- curcpu()->ci_idepth++;
- spl_intr(IPL_BIO, softint_schedule, sc->sc_ih);
- curcpu()->ci_idepth--;
+ softint_schedule(sc->sc_ih);
return 0;
}
@@ -250,7 +248,7 @@
/* let the softint do the work */
sc->busy = true;
- spl_intr(IPL_BIO, softint_schedule, sc->sc_ih);
+ softint_schedule(sc->sc_ih);
return 0;
}
--- src/sys/arch/usermode/dev/ttycons.c 2011/12/27 20:59:45 1.17
+++ src/sys/arch/usermode/dev/ttycons.c 2012/01/21 22:09:57 1.18
@@ -1,4 +1,4 @@
-/* $NetBSD: ttycons.c,v 1.17 2011/12/27 20:59:45 jmcneill Exp $ */
+/* $NetBSD: ttycons.c,v 1.18 2012/01/21 22:09:57 reinoud Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ttycons.c,v 1.17 2011/12/27 20:59:45 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ttycons.c,v 1.18 2012/01/21 22:09:57 reinoud Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -103,9 +103,9 @@
static int ttycons_intr(void *);
static void ttycons_softintr(void *);
-static void ttycons_ctrlc(int);
+static sigfunc_t ttycons_ctrlc;
static void ttycons_softctrlc(void *);
-static void ttycons_ctrlz(int);
+static sigfunc_t ttycons_ctrlz;
static void ttycons_softctrlz(void *);
static int
@@ -154,8 +154,9 @@
panic("couldn't establish ttycons ctrlz handler\n");
sigio_intr_establish(ttycons_intr, sc);
- thunk_signal(SIGINT, ttycons_ctrlc);
- thunk_signal(SIGTSTP, ttycons_ctrlz);
+ signal_intr_establish(SIGINT, ttycons_ctrlc);
+ signal_intr_establish(SIGTSTP, ttycons_ctrlz);
+
if (thunk_set_stdin_sigio(true) != 0)
panic("couldn't enable stdin async mode");
}
@@ -361,9 +362,7 @@
{
struct ttycons_softc *sc = priv;
- curcpu()->ci_idepth++;
- spl_intr(IPL_SERIAL, softint_schedule, sc->sc_rd_sih);
- curcpu()->ci_idepth--;
+ softint_schedule(sc->sc_rd_sih);
return 0;
}
@@ -383,17 +382,20 @@
}
}
+
+/*
+ * handle SIGINT signal from trap.c
+ *
+ * argument 'pc' and 'va' are not used.
+ */
static void
-ttycons_ctrlc(int sig)
+ttycons_ctrlc(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
{
struct ttycons_softc *sc;
- curcpu()->ci_idepth++;
sc = device_lookup_private(&ttycons_cd, minor(cn_tab->cn_dev));
- if (sc) {
- spl_intr(IPL_SERIAL, softint_schedule, sc->sc_ctrlc_sih);
- }
- curcpu()->ci_idepth--;
+ if (sc)
+ softint_schedule(sc->sc_ctrlc_sih);
}
@@ -408,18 +410,19 @@
t->t_linesw->l_rint(ch, t);
}
+/*
+ * handle SIGTSTP signal from trap.c
+ *
+ * argument 'pc' and 'va' are not used.
+ */
static void
-ttycons_ctrlz(int sig)
+ttycons_ctrlz(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
{
struct ttycons_softc *sc;
- curcpu()->ci_idepth++;
sc = device_lookup_private(&ttycons_cd, minor(cn_tab->cn_dev));
- if (sc) {
- spl_intr(IPL_SERIAL, softint_schedule, sc->sc_ctrlz_sih);
- }
- curcpu()->ci_idepth--;
-
+ if (sc)
+ softint_schedule(sc->sc_ctrlz_sih);
}
static void
--- src/sys/arch/usermode/include/intr.h 2011/12/26 22:04:35 1.6
+++ src/sys/arch/usermode/include/intr.h 2012/01/21 22:09:57 1.7
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.6 2011/12/26 22:04:35 jmcneill Exp $ */
+/* $NetBSD: intr.h,v 1.7 2012/01/21 22:09:57 reinoud Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@@ -32,9 +32,7 @@
#include <machine/intrdefs.h>
#include <sys/siginfo.h>
-void sigio_signal_handler(int, siginfo_t *, void *);
-void * sigio_intr_establish(int (*)(void *), void *);
-
+/* spl */
void splinit(void);
int splraise(int);
void spllower(int);
@@ -43,6 +41,13 @@
#define spl0() spllower(IPL_NONE)
#define splx(x) spllower(x)
+/* traps */
+typedef void (sigfunc_t)(vaddr_t from_userland, vaddr_t pc, vaddr_t va);
+extern void setup_signal_handlers(void);
+extern void signal_intr_establish(int sig, sigfunc_t f);
+extern void *sigio_intr_establish(int (*)(void *), void *);
+
+/* spl implementation */
typedef uint8_t ipl_t;
typedef struct {
ipl_t _ipl;
@@ -61,5 +66,7 @@
}
#include <sys/spl.h>
+
+/* for trap.c */
#endif /* !_ARCH_USERMODE_INCLUDE_INTR_H */
--- src/sys/arch/usermode/usermode/intr.c 2012/01/09 22:20:53 1.14
+++ src/sys/arch/usermode/usermode/intr.c 2012/01/21 22:09:57 1.15
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.14 2012/01/09 22:20:53 reinoud Exp $ */
+/* $NetBSD: intr.c,v 1.15 2012/01/21 22:09:57 reinoud Exp $ */
/*-
* Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,152 +27,36 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.14 2012/01/09 22:20:53 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.15 2012/01/21 22:09:57 reinoud Exp $");
#include <sys/types.h>
#include <machine/intr.h>
#include <machine/thunk.h>
-struct intr_handler {
- int (*func)(void *);
- void *arg;
-};
+int usermode_x = IPL_NONE;
-#define SIGIO_MAX_HANDLERS 8
-
-static struct intr_handler sigio_intr_handler[SIGIO_MAX_HANDLERS];
-
-//#define INTR_USE_SIGPROCMASK
-
-#define MAX_QUEUED_EVENTS 128
-
-static int usermode_x = IPL_NONE;
-
-#ifdef INTR_USE_SIGPROCMASK
-static bool block_sigalrm = false;
-#endif
-
-
-struct spl_intr_event {
- void (*func)(void *);
- void *arg;
-};
-
-struct spl_intr_event spl_intrs[IPL_HIGH+1][MAX_QUEUED_EVENTS];
-int spl_intr_wr[IPL_HIGH+1];
-int spl_intr_rd[IPL_HIGH+1];
-
void
splinit(void)
{
- int i;
- for (i = 0; i <= IPL_HIGH; i++) {
- spl_intr_rd[i] = 1;
- spl_intr_wr[i] = 1;
- }
+ /* nothing */
}
-void
-spl_intr(int x, void (*func)(void *), void *arg)
-{
- struct spl_intr_event *spli;
-
- if (x >= usermode_x) {
- func(arg);
- return;
- }
-
-// dprintf_debug("spl_intr: queue %d when %d\n", x, usermode_x);
- spli = &spl_intrs[x][spl_intr_wr[x]];
- spli->func = func;
- spli->arg = arg;
-
- spl_intr_wr[x] = (spl_intr_wr[x] + 1) % MAX_QUEUED_EVENTS;
- if (spl_intr_wr[x] == spl_intr_rd[x]) {
- thunk_printf("%s: spl list %d full!\n", __func__, x);
- panic("%s: spl list %d full!\n", __func__, x);
- }
-}
-
int
splraise(int x)
{
int oldx = usermode_x;
- if (x > usermode_x) {
+ if (x > usermode_x)
usermode_x = x;
- }
-#ifdef INTR_USE_SIGPROCMASK
- if (x >= IPL_SCHED && !block_sigalrm) {
- thunk_sigblock(SIGALRM);
- block_sigalrm = true;
- }
-#endif
-
return oldx;
}
void
spllower(int x)
{
- struct spl_intr_event *spli;
- int y;
-
- /* `eat' interrupts that came by until we got back to x */
- if (usermode_x > x) {
-//restart:
- for (y = usermode_x; y >= x; y--) {
- while (spl_intr_rd[y] != spl_intr_wr[y]) {
-// dprintf_debug("spl y %d firing\n", y);
- spli = &spl_intrs[y][spl_intr_rd[y]];
- if (!spli->func)
- panic("%s: spli->func is NULL for ipl %d, rd %d, wr %d\n",
- __func__, y, spl_intr_rd[y], spl_intr_wr[y]);
- spli->func(spli->arg);
- spl_intr_rd[y] = (spl_intr_rd[y] + 1) % MAX_QUEUED_EVENTS;
-// goto restart;
- }
- }
+ if (usermode_x > x)
usermode_x = x;
- }
-
-#ifdef INTR_USE_SIGPROCMASK
- if (x < IPL_SCHED && block_sigalrm) {
- thunk_sigunblock(SIGALRM);
- block_sigalrm = false;
- }
-#endif
}
-void
-sigio_signal_handler(int sig, siginfo_t *info, void *ctx)
-{
- struct intr_handler *sih;
- unsigned int n;
-
- for (n = 0; n < SIGIO_MAX_HANDLERS; n++) {
- sih = &sigio_intr_handler[n];
- if (sih->func)
- sih->func(sih->arg);
- }
-}
-
-void *
-sigio_intr_establish(int (*func)(void *), void *arg)
-{
- struct intr_handler *sih;
- unsigned int n;
-
- for (n = 0; n < SIGIO_MAX_HANDLERS; n++) {
- sih = &sigio_intr_handler[n];
- if (sih->func == NULL) {
- sih->func = func;
- sih->arg = arg;
- return sih;
- }
- }
-
- panic("increase SIGIO_MAX_HANDLERS");
-}
--- src/sys/arch/usermode/usermode/trap.c 2012/01/18 12:39:45 1.60
+++ src/sys/arch/usermode/usermode/trap.c 2012/01/21 22:09:57 1.61
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.60 2012/01/18 12:39:45 reinoud Exp $ */
+/* $NetBSD: trap.c,v 1.61 2012/01/21 22:09:57 reinoud Exp $ */
/*-
* Copyright (c) 2011 Reinoud Zandijk <reinoud@netbsd.org>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.60 2012/01/18 12:39:45 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.61 2012/01/21 22:09:57 reinoud Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -46,24 +46,49 @@
#include <machine/intr.h>
#include <machine/thunk.h>
+/* define maximum signal number */
+#ifndef NSIG
+#define NSIG 64
+#endif
/* forwards and externals */
void setup_signal_handlers(void);
void stop_all_signal_handlers(void);
-static void mem_access_handler(int sig, siginfo_t *info, void *ctx);
-static void illegal_instruction_handler(int sig, siginfo_t *info, void *ctx);
-extern int errno;
+static sigfunc_t pagefault;
+static sigfunc_t illegal_instruction;
+static sigfunc_t alarm;
+static sigfunc_t sigio;
-static void pagefault(vaddr_t from_userland, vaddr_t pc, vaddr_t va);
-static void illegal_instruction(vaddr_t from_userland);
+/* raw signal handlers */
+static stack_t sigstk;
+ucontext_t jump_ucp;
-bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype);
+sigfunc_t *sig_funcs[NSIG];
-static stack_t sigstk;
+/* segv, bus */
+extern bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype);
+/* alarm */
+void setup_clock_intr(void);
+extern void clock_intr(void *priv);
+
+extern int clock_running;
+void *alrm_ih;
+
+/* sigio handlers */
+struct intr_handler {
+ int (*func)(void *);
+ void *arg;
+};
+#define SIGIO_MAX_HANDLERS 8
+static struct intr_handler sigio_intr_handler[SIGIO_MAX_HANDLERS];
+
+/* misc */
int astpending = 0;
+
+/* XXX why is it here ? */
void
startlwp(void *arg)
{
@@ -74,8 +99,14 @@
void
setup_signal_handlers(void)
{
- static struct sigaction sa;
+ int i;
+ /*
+ * Set up the alternative signal stack. This prevents signals to be
+ * pushed on the NetBSD/usermode userland's stack with all desastrous
+ * effects. Especially ld.so and friends have such tiny stacks that
+ * its not feasable.
+ */
if ((sigstk.ss_sp = thunk_malloc(SIGSTKSZ)) == NULL)
panic("can't allocate signal stack space\n");
sigstk.ss_size = SIGSTKSZ;
@@ -84,68 +115,106 @@
panic("can't set alternate stacksize: %d",
thunk_geterrno());
- /* SIGBUS and SIGSEGV need to be reentrant hence the SA_NODEFER */
- sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
- sa.sa_sigaction = mem_access_handler;
- thunk_sigemptyset(&sa.sa_mask);
- if (thunk_sigaction(SIGSEGV, &sa, NULL) == -1)
- panic("couldn't register SIGSEGV handler: %d",
- thunk_geterrno());
- if (thunk_sigaction(SIGBUS, &sa, NULL) == -1)
- panic("couldn't register SIGBUS handler: %d", thunk_geterrno());
+ for (i = 0; i < NSIG; i++)
+ sig_funcs[i] = NULL;
- sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sa.sa_sigaction = illegal_instruction_handler;
- thunk_sigemptyset(&sa.sa_mask);
- if (thunk_sigaction(SIGILL, &sa, NULL) == -1)
- panic("couldn't register SIGILL handler: %d", thunk_geterrno());
-
- sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
- sa.sa_sigaction = sigio_signal_handler;
- thunk_sigemptyset(&sa.sa_mask);
- if (thunk_sigaction(SIGIO, &sa, NULL) == -1)
- panic("couldn't register SIGIO handler: %d", thunk_geterrno());
+ /* HUP */
+ /* INT */ /* ttycons ^C */
+ /* QUIT */
+ signal_intr_establish(SIGILL, illegal_instruction);
+ /* TRAP */
+ /* ABRT */
+ /* SIGEMT */
+ /* SIGFPE XXX! */
+ /* KILL */
+ signal_intr_establish(SIGBUS, pagefault);
+ signal_intr_establish(SIGSEGV, pagefault);
+ /* SYS */
+ /* PIPE */
+ signal_intr_establish(SIGALRM, alarm);
+ /* TERM */
+ /* URG */
+ /* STOP */
+ /* TSTP */ /* ttycons ^Z */
+ /* CONT */
+ /* CHLD */
+ /* GTTIN */
+ /* TTOU */
+ signal_intr_establish(SIGIO, sigio);
+ /* XCPU */
+ /* XFSZ */
+ /* VTALRM */
+ /* PROF */
+ /* WINCH */
+ /* INFO */
+ /* USR1 */
+ /* USR2 */
+ /* PWR */
}
+/* XXX yes this is blunt */
void
stop_all_signal_handlers(void)
{
- thunk_sigblock(SIGALRM);
- thunk_sigblock(SIGIO);
- thunk_sigblock(SIGILL);
- thunk_sigblock(SIGSEGV);
- thunk_sigblock(SIGBUS);
+ int i;
+ for (i = 0; i < NSIG; i++)
+ if (sig_funcs[i])
+ thunk_sigblock(i);
}
-/* ast and userret */
void
-userret(struct lwp *l)
+setup_clock_intr(void)
{
- /* invoke MI userret code */
- mi_userret(l);
+ /* setup soft interrupt handler */
+ alrm_ih = softint_establish(SOFTINT_CLOCK,
+ clock_intr, NULL);
+}
- while (astpending) {
- astpending = 0;
- curcpu()->ci_data.cpu_ntrap++;
+/* ast and userret */
+static void
+ast(struct lwp *l)
+{
+ struct pcb *pcb;
+
+ if (!astpending)
+ return;
+
+ astpending = 0;
+ curcpu()->ci_data.cpu_ntrap++;
+
#if 0
- /* profiling */
- if (l->l_pflag & LP_OWEUPC) {
- l->l_pflag &= ~LP_OWEUPC;
- ADDUPROF(l);
- }
+ /* profiling */
+ if (l->l_pflag & LP_OWEUPC) {
+ l->l_pflag &= ~LP_OWEUPC;
+ ADDUPROF(l);
+ }
#endif
- /* allow a forced task switch */
- if (l->l_cpu->ci_want_resched)
- preempt();
- mi_userret(l);
+ /* allow a forced task switch */
+ if (curcpu()->ci_want_resched) {
+ curcpu()->ci_want_resched = 0;
+ preempt();
+ /* returns here! */
}
+ KASSERT(l == curlwp); KASSERT(l);
+ pcb = lwp_getpcb(l); KASSERT(pcb);
+ mi_userret(l);
}
+void
+userret(struct lwp *l)
+{
+ /* invoke MI userret code */
+ mi_userret(l);
+
+ ast(l);
+}
+
+
#ifdef DEBUG
/*
* Uncomment the following if you want to receive information about what
@@ -175,11 +244,8 @@
#endif
#if 0
- printf("memaccess error, pc %p, va %p, "
- "sys_stack %p, sp %p, stack top %p\n",
- (void *) pc, (void *) va,
- (void *) pcb->sys_stack, (void *) sp,
- (void *) pcb->sys_stack_top);
+ thunk_printf("memaccess error, pc %p, va %p, sp %p\n",
+ (void *) pc, (void *) va, (void *) sp);
#endif
}
@@ -220,6 +286,10 @@
thunk_printf("%02x ", *((uint8_t *) info->si_addr + i));
thunk_printf("\n");
#endif
+
+#if 0
+ thunk_printf("sigill\n");
+#endif
}
#else /* DEBUG */
#define print_mem_access_siginfo(s, i, c, p, v, sp)
@@ -227,40 +297,47 @@
#endif /* DEBUG */
-/* signal handler switching to a pagefault context */
static void
-mem_access_handler(int sig, siginfo_t *info, void *ctx)
+handle_signal(int sig, siginfo_t *info, void *ctx)
{
+ sigfunc_t *f;
ucontext_t *ucp = ctx;
struct lwp *l;
struct pcb *pcb;
vaddr_t va, sp, pc, fp;
int from_userland;
- assert((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS));
+ if (sig == SIGBUS || sig == SIGSEGV || sig == SIGILL) {
+ if (info->si_code == SI_NOINFO)
+ panic("received signal %d with no info",
+ info->si_signo);
+ }
- if (info->si_code == SI_NOINFO)
- panic("received signal %d with no info",
- info->si_signo);
+ f = sig_funcs[sig];
+ KASSERT(f);
- l = curlwp;
- pcb = lwp_getpcb(l);
+ l = curlwp; KASSERT(l);
+ pcb = lwp_getpcb(l); KASSERT(pcb);
- /* get address of faulted memory access and make it page aligned */
+ /* get address of possible faulted memory access and page aligne it */
va = (vaddr_t) info->si_addr;
va = trunc_page(va);
- /* get PC address of faulted memory instruction */
+ /* get PC address of possibly faulted instruction */
pc = md_get_pc(ctx);
- /* setup for pagefault context */
+ /* nest it on the stack */
sp = md_get_sp(ctx);
- print_mem_access_siginfo(sig, info, ctx, pc, va, sp);
+ if (sig == SIGBUS || sig == SIGSEGV)
+ print_mem_access_siginfo(sig, info, ctx, pc, va, sp);
+ if (sig == SIGILL)
+ print_illegal_instruction_siginfo(sig, info, ctx, pc, va, sp);
/* if we're running on a stack of our own, use the system stack */
from_userland = 0;
- if ((sp < (vaddr_t) pcb->sys_stack) || (sp > (vaddr_t) pcb->sys_stack_top)) {
+ if ((sp < (vaddr_t) pcb->sys_stack) ||
+ (sp > (vaddr_t) pcb->sys_stack_top)) {
sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t);
fp = (vaddr_t) &pcb->pcb_userret_ucp;
if (pc < kmem_user_end)
@@ -276,79 +353,38 @@
}
memcpy((void *) fp, ucp, sizeof(ucontext_t));
+ memcpy(&jump_ucp, ucp, sizeof(ucontext_t));
- /* create context for pagefault */
- pcb->pcb_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack;
- pcb->pcb_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack;
- pcb->pcb_ucp.uc_link = (void *) fp; /* link to old frame on stack */
+ /* create context */
+ jump_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack;
+ jump_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack;
+ jump_ucp.uc_link = (void *) fp; /* link to old frame on stack */
- pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
- thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) pagefault,
+ thunk_sigemptyset(&jump_ucp.uc_sigmask);
+ jump_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
+ thunk_makecontext(&jump_ucp,
+ (void (*)(void)) f,
3, (void *) from_userland, (void *) pc, (void *) va);
- /* switch to the new pagefault entry on return from signal */
- memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t));
+ /* switch to the new context on return from signal */
+ thunk_setcontext(&jump_ucp);
+// memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t));
}
-/* signal handler switching to a illegal instruction context */
-static void
-illegal_instruction_handler(int sig, siginfo_t *info, void *ctx)
+void
+signal_intr_establish(int sig, sigfunc_t f)
{
- ucontext_t *ucp = ctx;
- struct lwp *l;
- struct pcb *pcb;
- vaddr_t sp, pc, fp;
- int from_userland;
+ static struct sigaction sa;
- assert(info->si_signo == SIGILL);
+ sig_funcs[sig] = f;
- l = curlwp;
- pcb = lwp_getpcb(l);
-
- /* get PC address of faulted instruction */
- pc = md_get_pc(ctx);
-
- /* setup for illegal_instruction context */
- sp = md_get_sp(ctx);
-
- print_illegal_instruction_siginfo(sig, info, ctx, pc, 0, sp);
-
- /* if we're running on a stack of our own, use the system stack */
- from_userland = 0;
- if ((sp < (vaddr_t) pcb->sys_stack) ||
- (sp > (vaddr_t) pcb->sys_stack_top)) {
- sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t);
- fp = (vaddr_t) &pcb->pcb_userret_ucp;
-
- KASSERT(pc < kmem_user_end);
- from_userland = 1;
- } else {
- panic("illegal instruction inside kernel?");
-#if 0
- /* stack grows down */
- fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */
- sp = fp - sizeof(register_t); /* slack */
-
- /* sanity check before copying */
- if (fp - 2*PAGE_SIZE < (vaddr_t) pcb->sys_stack)
- panic("%s: out of system stack", __func__);
-#endif
- }
-
- memcpy((void *) fp, ucp, sizeof(ucontext_t));
-
- /* create context for illegal instruction */
- pcb->pcb_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack;
- pcb->pcb_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack;
- pcb->pcb_ucp.uc_link = (void *) fp; /* link to old frame on stack */
-
- pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
- thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) illegal_instruction,
- 1, (void *) from_userland, NULL, NULL);
-
- /* switch to the new illegal instruction entry on return from signal */
- memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t));
+ sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+ sa.sa_sigaction = (void *) handle_signal;
+ thunk_sigfillset(&sa.sa_mask);
+ if (thunk_sigaction(sig, &sa, NULL) == -1)
+ panic("couldn't register SIG%d handler: %d", sig,
+ thunk_geterrno());
}
@@ -377,18 +413,17 @@
lwp_errno = thunk_geterrno();
vm_map = &vm->vm_map;
- from_kernel = (pc >= kmem_k_start);
+ from_kernel = (pc >= kmem_k_start) && (!from_userland);
if (from_kernel && (va >= VM_MIN_KERNEL_ADDRESS))
vm_map = kernel_map;
#if 0
- thunk_printf("pagefault : pc %p, va %p\n",
- (void *) pc, (void *) va);
+ thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb);
+ thunk_printf("\tpc %p, va %p\n", (void *) pc, (void *) va);
#endif
/* can pmap handle it? on its own? (r/m) emulation */
if (pmap_fault(vm_map->pmap, va, &atype)) {
-// thunk_printf("pagefault leave (pmap)\n");
/* no use doing anything else here */
goto out_quick;
}
@@ -416,8 +451,8 @@
}
/* something got wrong */
- thunk_printf("%s: uvm fault %d, pc %p, from_kernel %d\n",
- __func__, error, (void *) pc, from_kernel);
+ thunk_printf("%s: uvm fault %d, pc %p, va %p, from_kernel %d\n",
+ __func__, error, (void *) pc, (void *) va, from_kernel);
/* check if its from copyin/copyout */
if (onfault) {
@@ -437,6 +472,7 @@
/* send signal */
thunk_printf("giving signal to userland\n");
+ KASSERT(from_userland);
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGSEGV;
ksi.ksi_trap = 0; /* XXX */
@@ -468,28 +504,32 @@
/*
- * Context for handing illegal instruction from the sigill handler
+ * handle an illegal instruction.
+ *
+ * arguments 'pc' and 'va' are ignored here
*/
static void
-illegal_instruction(vaddr_t from_userland)
+illegal_instruction(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
{
struct lwp *l = curlwp;
struct pcb *pcb = lwp_getpcb(l);
ucontext_t *ucp = &pcb->pcb_userret_ucp;
ksiginfo_t ksi;
-// thunk_printf("illegal instruction\n");
+// thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb);
+
+ KASSERT(from_userland);
+
/* if its a syscall ... */
if (md_syscall_check_opcode(ucp)) {
syscall();
-// thunk_printf("illegal instruction leave\n");
- KASSERT(from_userland);
userret(l);
return;
}
thunk_printf("%s: giving SIGILL (TRAP)\n", __func__);
+ KASSERT(from_userland);
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGILL;
ksi.ksi_trap = 0; /* XXX */
@@ -502,7 +542,75 @@
#else
trapsignal(l, &ksi);
#endif
- KASSERT(from_userland);
userret(l);
+}
+
+
+/*
+ * handle alarm, a clock ticker.
+ *
+ * arguments 'pc' and 'va' are ignored here
+ */
+static void
+alarm(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
+{
+ struct lwp *l = curlwp;
+ struct pcb *pcb = lwp_getpcb(l); KASSERT(pcb);
+
+ if (!clock_running)
+ return;
+// thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb);
+
+ softint_schedule(alrm_ih);
+
+ KASSERT(l == curlwp);
+ if (from_userland)
+ userret(l);
+}
+
+
+/*
+ * handle sigio, a mux for all io operations.
+ *
+ * arguments 'pc' and 'va' are ignored here
+ */
+static void
+sigio(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
+{
+ struct lwp *l = curlwp;
+ struct pcb *pcb = lwp_getpcb(l); KASSERT(pcb);
+ struct intr_handler *sih;
+ unsigned int n;
+
+// thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb);
+ for (n = 0; n < SIGIO_MAX_HANDLERS; n++) {
+ sih = &sigio_intr_handler[n];
+ if (sih->func)
+ sih->func(sih->arg);
+ }
+
+ KASSERT(l == curlwp);
+ if (from_userland)
+ userret(l); /* or ast? */
+}
+
+
+/* sigio register function */
+void *
+sigio_intr_establish(int (*func)(void *), void *arg)
+{
+ struct intr_handler *sih;
+ unsigned int n;
+
+ for (n = 0; n < SIGIO_MAX_HANDLERS; n++) {
+ sih = &sigio_intr_handler[n];
+ if (sih->func == NULL) {
+ sih->func = func;
+ sih->arg = arg;
+ return sih;
+ }
+ }
+
+ panic("increase SIGIO_MAX_HANDLERS");
}