Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/usermode Revamp the NetBSD/usermode pagefault and i...



details:   https://anonhg.NetBSD.org/src/rev/bd14d6274a5b
branches:  trunk
changeset: 772728:bd14d6274a5b
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Sat Jan 14 17:42:51 2012 +0000

description:
Revamp the NetBSD/usermode pagefault and illegal instruction handing. It now
can handle recursive entry and is a lot more memory tight compared to the old
implementation. Performance wise:

* slightly less number of syscalls/sec possible though could be optimized
* a lot faster context creation / destruction making overall operation faster.

diffstat:

 sys/arch/usermode/dev/cpu.c                  |   93 ++-------
 sys/arch/usermode/include/pcb.h              |   28 +--
 sys/arch/usermode/target/i386/cpu_i386.c     |   39 ++-
 sys/arch/usermode/target/x86_64/cpu_x86_64.c |   23 +-
 sys/arch/usermode/usermode/copy.c            |    9 +-
 sys/arch/usermode/usermode/pmap.c            |   20 +-
 sys/arch/usermode/usermode/syscall.c         |   45 ++--
 sys/arch/usermode/usermode/thunk.c           |    8 +-
 sys/arch/usermode/usermode/trap.c            |  251 +++++++++++++++++++-------
 9 files changed, 303 insertions(+), 213 deletions(-)

diffs (truncated from 1023 to 300 lines):

diff -r 0b1f01527952 -r bd14d6274a5b sys/arch/usermode/dev/cpu.c
--- a/sys/arch/usermode/dev/cpu.c       Sat Jan 14 17:36:32 2012 +0000
+++ b/sys/arch/usermode/dev/cpu.c       Sat Jan 14 17:42:51 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.63 2012/01/12 13:28:54 reinoud Exp $ */
+/* $NetBSD: cpu.c,v 1.64 2012/01/14 17:42:51 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -30,7 +30,7 @@
 #include "opt_hz.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.63 2012/01/12 13:28:54 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.64 2012/01/14 17:42:51 reinoud Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -78,9 +78,13 @@
        struct cpu_info *sc_ci;
 } cpu_softc_t;
 
+
+/* statics */
 static struct pcb lwp0pcb;
 static void *um_msgbuf;
 
+
+/* attachment */
 CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL);
 
 static int
@@ -115,6 +119,8 @@
        spl0();
 }
 
+
+/* main guts */
 void
 cpu_reboot(int howto, char *bootstr)
 {
@@ -226,7 +232,7 @@
 {
        struct pcb *pcb = lwp_getpcb(l);
        ucontext_t *ucp = &pcb->pcb_userret_ucp;
-
+       
 #ifdef CPU_DEBUG
        thunk_printf_debug("cpu_getmcontext\n");
 #endif
@@ -277,25 +283,7 @@
 
        if (pcb == NULL)
                return;
-
-       if (pcb->pcb_stack_userland) {
-               free(pcb->pcb_stack_userland, M_TEMP);
-               pcb->pcb_stack_userland = NULL;
-               pcb->pcb_ucp.uc_stack.ss_sp = NULL;
-               pcb->pcb_ucp.uc_stack.ss_size = 0;
-       }
-
-       if (pcb->pcb_stack_syscall) {
-               free(pcb->pcb_stack_syscall, M_TEMP);
-               pcb->pcb_syscall_ucp.uc_stack.ss_sp = NULL;
-               pcb->pcb_syscall_ucp.uc_stack.ss_size = 0;
-       }
-
-       if (pcb->pcb_stack_pagefault) {
-               free(pcb->pcb_stack_pagefault, M_TEMP);
-               pcb->pcb_pagefault_ucp.uc_stack.ss_sp = NULL;
-               pcb->pcb_pagefault_ucp.uc_stack.ss_size = 0;
-       }
+       /* XXX nothing to do? */
 }
 
 static void
@@ -332,42 +320,21 @@
        /* copy the PCB and its switchframes from parent */
        memcpy(pcb2, pcb1, sizeof(struct pcb));
 
-       stacksize = 2*PAGE_SIZE;
-       pcb2->pcb_stack_userland  = malloc(stacksize, M_TEMP, M_WAITOK | M_ZERO);
-       pcb2->pcb_stack_syscall   = malloc(stacksize, M_TEMP, M_WAITOK | M_ZERO);
-       pcb2->pcb_stack_pagefault = malloc(stacksize, M_TEMP, M_WAITOK | M_ZERO);
-
-       KASSERT(pcb2->pcb_stack_userland);
-       KASSERT(pcb2->pcb_stack_syscall);
-       KASSERT(pcb2->pcb_stack_pagefault);
-
+       /* refresh context */
        if (thunk_getcontext(&pcb2->pcb_ucp))
                panic("getcontext failed");
 
-       /* set up the ucontext for the userland switch */
-       pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->pcb_stack_userland;
-       pcb2->pcb_ucp.uc_stack.ss_size = stacksize;
+       /* recalculate the system stack top */
+       pcb2->sys_stack_top = pcb2->sys_stack + TRAPSTACKSIZE;
+
+       /* 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;
        pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp;
        thunk_makecontext(&pcb2->pcb_ucp,
            (void (*)(void)) cpu_lwp_trampoline,
            3, &pcb2->pcb_ucp, func, arg);
-
-       /* set up the ucontext for the syscall */
-       pcb2->pcb_syscall_ucp.uc_stack.ss_sp = pcb2->pcb_stack_syscall;
-       pcb2->pcb_syscall_ucp.uc_stack.ss_size = stacksize;
-       pcb2->pcb_syscall_ucp.uc_flags = _UC_STACK | _UC_CPU;
-       pcb2->pcb_syscall_ucp.uc_link = &pcb2->pcb_userret_ucp;
-       thunk_makecontext(&pcb2->pcb_syscall_ucp, (void (*)(void)) syscall,
-           0, NULL, NULL, NULL);
-
-       /* set up the ucontext for the pagefault */
-       pcb2->pcb_pagefault_ucp.uc_stack.ss_sp = pcb2->pcb_stack_pagefault;
-       pcb2->pcb_pagefault_ucp.uc_stack.ss_size = stacksize;
-       pcb2->pcb_pagefault_ucp.uc_flags = _UC_STACK | _UC_CPU;
-       pcb2->pcb_pagefault_ucp.uc_link = &pcb2->pcb_trapret_ucp;
-       thunk_makecontext(&pcb2->pcb_pagefault_ucp, (void (*)(void)) pagefault,
-           0, NULL, NULL, NULL);
 }
 
 void
@@ -382,7 +349,7 @@
 cpu_startup(void)
 {
        vaddr_t minaddr, maxaddr;
-       size_t stacksize, msgbufsize = 32 * 1024;
+       size_t msgbufsize = 32 * 1024;
 
        /* get ourself a message buffer */
        um_msgbuf = kmem_zalloc(msgbufsize, KM_SLEEP);
@@ -400,26 +367,12 @@
 
        /* init lwp0 */
        memset(&lwp0pcb, 0, sizeof(lwp0pcb));
-       if (thunk_getcontext(&lwp0pcb.pcb_ucp))
-               panic("getcontext failed");
-       uvm_lwp_setuarea(&lwp0, (vaddr_t)&lwp0pcb);
-
-       /* init trapframes (going nowhere!), maybe a panic func? */
-       memcpy(&lwp0pcb.pcb_syscall_ucp,   &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
-       memcpy(&lwp0pcb.pcb_userret_ucp,   &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
-       memcpy(&lwp0pcb.pcb_pagefault_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
-       memcpy(&lwp0pcb.pcb_trapret_ucp,   &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
+       thunk_getcontext(&lwp0pcb.pcb_ucp);
+       uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb);
+       memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
 
-       /* set up the ucontext for the pagefault */
-       stacksize = 2*PAGE_SIZE;
-       lwp0pcb.pcb_stack_pagefault = malloc(stacksize, M_TEMP, M_WAITOK | M_ZERO);
-
-       lwp0pcb.pcb_pagefault_ucp.uc_stack.ss_sp = lwp0pcb.pcb_stack_pagefault;
-       lwp0pcb.pcb_pagefault_ucp.uc_stack.ss_size = stacksize;
-       lwp0pcb.pcb_pagefault_ucp.uc_flags = _UC_STACK | _UC_CPU;
-       lwp0pcb.pcb_pagefault_ucp.uc_link = &lwp0pcb.pcb_userret_ucp;
-       thunk_makecontext(&lwp0pcb.pcb_pagefault_ucp, (void (*)(void)) pagefault,
-           0, NULL, NULL, NULL);
+       /* set stack top */
+       lwp0pcb.sys_stack_top = lwp0pcb.sys_stack + TRAPSTACKSIZE;
 }
 
 void
diff -r 0b1f01527952 -r bd14d6274a5b sys/arch/usermode/include/pcb.h
--- a/sys/arch/usermode/include/pcb.h   Sat Jan 14 17:36:32 2012 +0000
+++ b/sys/arch/usermode/include/pcb.h   Sat Jan 14 17:42:51 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pcb.h,v 1.16 2012/01/06 12:54:59 reinoud Exp $ */
+/* $NetBSD: pcb.h,v 1.17 2012/01/14 17:42:51 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -31,30 +31,20 @@
 
 #include <sys/cdefs.h>
 #include <sys/ucontext.h>
+#include <sys/queue.h>
 
-/*
- * Trap frame.  Pushed onto the kernel stack on a trap (synchronous exception).
- * XXX move to frame.h?
- */
 
-//typedef ucontext_t trapframe;
-
+#define TRAPSTACKSIZE (USPACE -2*sizeof(ucontext_t) - 3*sizeof(register_t))
 struct pcb {
-       void            *pcb_stack_userland;
-       void            *pcb_stack_syscall;
-       void            *pcb_stack_pagefault;
+       ucontext_t pcb_ucp;             /* switchframe */
+       ucontext_t pcb_userret_ucp;
 
-       ucontext_t       pcb_ucp;               /* lwp switchframe */
-       ucontext_t       pcb_syscall_ucp;       /* syscall context */
-       ucontext_t       pcb_userret_ucp;       /* return to userland context */
-       ucontext_t       pcb_pagefault_ucp;     /* pagefault context */
-       ucontext_t       pcb_trapret_ucp;
+       uint8_t *sys_stack_top;         /* points at free point in sys_stack */
+       uint8_t  sys_stack[TRAPSTACKSIZE];
 
-       void *           pcb_onfault;           /* on fault handler */
+       void    *pcb_onfault;           /* on fault handler */
 
-       int              pcb_errno;             /* save/restore place */
-       vaddr_t          pcb_fault_addr;        /* save place for fault addr */
-       vaddr_t          pcb_fault_pc;          /* save place for fault PC */
+       int      pcb_errno;             /* save/restore place */
 };
 
 #endif /* !_ARCH_USERMODE_INCLUDE_PCB_H */
diff -r 0b1f01527952 -r bd14d6274a5b sys/arch/usermode/target/i386/cpu_i386.c
--- a/sys/arch/usermode/target/i386/cpu_i386.c  Sat Jan 14 17:36:32 2012 +0000
+++ b/sys/arch/usermode/target/i386/cpu_i386.c  Sat Jan 14 17:42:51 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_i386.c,v 1.1 2012/01/07 20:07:01 reinoud Exp $ */
+/* $NetBSD: cpu_i386.c,v 1.2 2012/01/14 17:42:52 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2011 Reinoud Zandijk <reinoud%netbsd.org@localhost>
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu_i386.c,v 1.1 2012/01/07 20:07:01 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_i386.c,v 1.2 2012/01/14 17:42:52 reinoud Exp $");
 
 #include <sys/types.h>
 #include <sys/systm.h>
@@ -55,6 +55,8 @@
 #include <machine/machdep.h>
 #include <machine/thunk.h>
 
+#include "opt_exec.h"
+
 #if 0
 static void dump_regs(register_t *reg);;
 
@@ -108,16 +110,18 @@
        struct sigframe_siginfo *fp, frame;
        int sig = ksi->ksi_signo;
        sig_t catcher = SIGACTION(p, sig).sa_handler;
-       ucontext_t *ucp = &pcb->pcb_userret_ucp;
-       register_t *reg = (register_t *) &ucp->uc_mcontext;
+       ucontext_t *ucp;
+       register_t *reg;
        int onstack, error;
 
        KASSERT(mutex_owned(p->p_lock));
 
+       ucp = &pcb->pcb_userret_ucp;
+       reg = (register_t *) &ucp->uc_mcontext;
 #if 0
-       printf("%s: ", __func__);
-       printf("flags %d, ", (int) ksi->ksi_flags);
-       printf("to lwp %d, signo %d, code %d, errno %d\n",
+       thunk_printf("%s: ", __func__);
+       thunk_printf("flags %d, ", (int) ksi->ksi_flags);
+       thunk_printf("to lwp %d, signo %d, code %d, errno %d\n",
                (int) ksi->ksi_lid,
                ksi->ksi_signo,
                ksi->ksi_code,
@@ -179,7 +183,7 @@
 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
 {
        struct pcb *pcb = lwp_getpcb(l);
-       ucontext_t *ucp = &pcb->pcb_userret_ucp;
+       ucontext_t *ucp;
        uint *reg, i;
 
 #ifdef DEBUG_EXEC
@@ -190,16 +194,15 @@
                pcb->pcb_ucp.uc_stack.ss_sp);
        printf("\tpcb->pcb_ucp.uc_stack.ss_size = %d\n",
                (int) pcb->pcb_ucp.uc_stack.ss_size);
-       printf("\tpcb->pcb_userret_ucp.uc_stack.ss_sp   = %p\n",
-               pcb->pcb_userret_ucp.uc_stack.ss_sp);
-       printf("\tpcb->pcb_userret_ucp.uc_stack.ss_size = %d\n",
-               (int) pcb->pcb_userret_ucp.uc_stack.ss_size);
 #endif
 
+       /* set up the user context */
+       ucp = &pcb->pcb_userret_ucp;
        reg = (int *) &ucp->uc_mcontext;
        for (i = 4; i < 11; i++)
                reg[i] = 0;
 
+       /* use given stack */
        ucp->uc_stack.ss_sp = (void *) (stack-4);       /* to prevent clearing */
        ucp->uc_stack.ss_size = 0; //pack->ep_ssize;
        thunk_makecontext(ucp, (void *) pack->ep_entry, 0, NULL, NULL, NULL);
@@ -216,10 +219,6 @@
                pcb->pcb_ucp.uc_stack.ss_sp);
        printf("\tpcb->pcb_ucp.uc_stack.ss_size = %d\n",
                (int) pcb->pcb_ucp.uc_stack.ss_size);



Home | Main Index | Thread Index | Old Index