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