Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/usermode/usermode Clean up userret/ast handling. No...



details:   https://anonhg.NetBSD.org/src/rev/793035107b0a
branches:  trunk
changeset: 772840:793035107b0a
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Tue Jan 17 19:46:55 2012 +0000

description:
Clean up userret/ast handling. Now called ONLY when its 100% clear that it is
returning to userland.

diffstat:

 sys/arch/usermode/usermode/trap.c |  106 ++++++++++++++++++-------------------
 1 files changed, 52 insertions(+), 54 deletions(-)

diffs (233 lines):

diff -r 4d7149dbd40a -r 793035107b0a sys/arch/usermode/usermode/trap.c
--- a/sys/arch/usermode/usermode/trap.c Tue Jan 17 19:40:08 2012 +0000
+++ b/sys/arch/usermode/usermode/trap.c Tue Jan 17 19:46:55 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.57 2012/01/14 21:45:28 reinoud Exp $ */
+/* $NetBSD: trap.c,v 1.58 2012/01/17 19:46:55 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2011 Reinoud Zandijk <reinoud%netbsd.org@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.57 2012/01/14 21:45:28 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.58 2012/01/17 19:46:55 reinoud Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -50,14 +50,13 @@
 /* forwards and externals */
 void setup_signal_handlers(void);
 void stop_all_signal_handlers(void);
-void userret(struct lwp *l);
 
 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 void pagefault(vaddr_t pc, vaddr_t va);
-static void illegal_instruction(void);
+static void pagefault(vaddr_t from_userland, vaddr_t pc, vaddr_t va);
+static void illegal_instruction(vaddr_t from_userland);
 
 bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype);
 
@@ -120,6 +119,33 @@
 }
 
 
+/* ast and userret */
+void
+userret(struct lwp *l)
+{
+       /* invoke MI userret code */
+       mi_userret(l);
+
+       while (astpending) {
+               astpending = 0;
+
+               curcpu()->ci_data.cpu_ntrap++;
+#if 0
+               /* 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);
+       }
+}
+
+
 /* signal handler switching to a pagefault context */
 static void
 mem_access_handler(int sig, siginfo_t *info, void *ctx)
@@ -128,6 +154,7 @@
        struct lwp *l;
        struct pcb *pcb;
        vaddr_t va, sp, pc, fp;
+       int from_userland;
 
        assert((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS));
 
@@ -176,9 +203,12 @@
 #endif
 
        /* 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;
+               if (pc < kmem_user_end)
+                       from_userland = 1;
        } else {
                /* stack grows down */
                fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */
@@ -198,56 +228,13 @@
 
        pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
        thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) pagefault,
-               2, (void *) pc, (void *) va, NULL);
+               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));
 }
 
 
-/* ast and userret */
-void
-userret(struct lwp *l)
-{
-       struct pcb *pcb;
-       ucontext_t ucp, *nucp;
-       vaddr_t pc;
-       
-       KASSERT(l);
-
-       /* are we going back to userland? */
-       pcb = lwp_getpcb(l);
-       KASSERT(pcb);
-
-       /* where are we going back to ? */
-       thunk_getcontext(&ucp);
-       nucp = (ucontext_t *) ucp.uc_link;
-       pc = md_get_pc(nucp);
-
-       if (pc >= kmem_k_start)
-               return;
-
-       /* ok, going to userland, proceed! */
-       if (astpending) {
-               astpending = 0;
-
-               curcpu()->ci_data.cpu_ntrap++;
-#if 0
-               /* 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();
-       }
-
-       /* invoke MI userret code */
-       mi_userret(l);
-}
-
 /* signal handler switching to a illegal instruction context */
 static void
 illegal_instruction_handler(int sig, siginfo_t *info, void *ctx)
@@ -255,7 +242,8 @@
        ucontext_t *ucp = ctx;
        struct lwp *l;
        struct pcb *pcb;
-       vaddr_t sp, fp;
+       vaddr_t sp, pc, fp;
+       int from_userland;
 
        assert(info->si_signo == SIGILL);
 #if 0
@@ -291,14 +279,21 @@
        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);
 
        /* 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
@@ -321,7 +316,7 @@
 
        pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
        thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) illegal_instruction,
-               0, NULL, NULL, NULL);
+               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));
@@ -333,7 +328,7 @@
  * pmap reference fault or let uvm handle it.
  */
 static void
-pagefault(vaddr_t pc, vaddr_t va)
+pagefault(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
 {
        struct proc *p;
        struct lwp *l;
@@ -435,7 +430,8 @@
 
 //     thunk_printf("pagefault leave\n");
 out:
-       userret(l);
+       if (from_userland)
+               userret(l);
 out_quick:
        thunk_seterrno(lwp_errno);
        pcb->pcb_errno = lwp_errno;
@@ -445,7 +441,7 @@
  * Context for handing illegal instruction from the sigill handler
  */
 static void
-illegal_instruction(void)
+illegal_instruction(vaddr_t from_userland)
 {
        struct lwp *l = curlwp;
        struct pcb *pcb = lwp_getpcb(l);
@@ -457,6 +453,7 @@
        if (md_syscall_check_opcode(ucp)) {
                syscall();
 //             thunk_printf("illegal instruction leave\n");
+               KASSERT(from_userland);
                userret(l);
                return;
        }
@@ -475,6 +472,7 @@
 #else
        trapsignal(l, &ksi);
 #endif
+       KASSERT(from_userland);
        userret(l);
 }
 



Home | Main Index | Thread Index | Old Index