diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index b65fcb5fdd46..311321e8e75c 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.215 2006/03/22 01:14:46 matt Exp $ */ +/* $NetBSD: kern_exec.c,v 1.216 2006/03/29 23:02:31 cube Exp $ */ /*- * Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou @@ -33,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.215 2006/03/22 01:14:46 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.216 2006/03/29 23:02:31 cube Exp $"); #include "opt_ktrace.h" #include "opt_syscall_debug.h" @@ -142,6 +142,17 @@ struct uvm_object *emul_netbsd_object; void syscall(void); #endif +static const struct sa_emul saemul_netbsd = { + sizeof(ucontext_t), + sizeof(struct sa_t), + sizeof(struct sa_t *), + NULL, + NULL, + cpu_upcall, + (void (*)(struct lwp *, void *))getucontext, + sa_ucsp +}; + /* NetBSD emul struct */ const struct emul emul_netbsd = { "netbsd", @@ -185,6 +196,8 @@ const struct emul emul_netbsd = { NULL, uvm_default_mapaddr, + NULL, + &saemul_netbsd, }; #ifdef LKM diff --git a/sys/kern/kern_lwp.c b/sys/kern/kern_lwp.c index 40de11be258d..9884e431a8ba 100644 --- a/sys/kern/kern_lwp.c +++ b/sys/kern/kern_lwp.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_lwp.c,v 1.33 2005/11/12 02:28:31 chs Exp $ */ +/* $NetBSD: kern_lwp.c,v 1.34 2006/03/29 23:02:31 cube Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.33 2005/11/12 02:28:31 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.34 2006/03/29 23:02:31 cube Exp $"); #include "opt_multiprocessor.h" @@ -87,7 +87,8 @@ sys__lwp_create(struct lwp *l, void *v, register_t *retval) newuc = pool_get(&lwp_uc_pool, PR_WAITOK); - error = copyin(SCARG(uap, ucp), newuc, sizeof(*newuc)); + error = copyin(SCARG(uap, ucp), newuc, + l->l_proc->p_emul->e_sa->sae_ucsize); if (error) return (error); diff --git a/sys/kern/kern_sa.c b/sys/kern/kern_sa.c index fad3566f5b83..764cb69bd1f1 100644 --- a/sys/kern/kern_sa.c +++ b/sys/kern/kern_sa.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sa.c,v 1.70 2005/12/24 19:12:23 perry Exp $ */ +/* $NetBSD: kern_sa.c,v 1.71 2006/03/29 23:02:31 cube Exp $ */ /*- * Copyright (c) 2001, 2004, 2005 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ #include #include "opt_ktrace.h" -__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.70 2005/12/24 19:12:23 perry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.71 2006/03/29 23:02:31 cube Exp $"); #include #include @@ -187,10 +187,26 @@ sys_sa_register(struct lwp *l, void *v, register_t *retval) syscallarg(int) flags; syscallarg(ssize_t) stackinfo_offset; } */ *uap = v; + int error; + sa_upcall_t prev; + + error = dosa_register(l, SCARG(uap, new), &prev, SCARG(uap, flags), + SCARG(uap, stackinfo_offset)); + if (error) + return error; + + if (SCARG(uap, old)) + return copyout(&prev, SCARG(uap, old), + sizeof(prev)); + return 0; +} + +int +dosa_register(struct lwp *l, sa_upcall_t new, sa_upcall_t *prev, int flags, + ssize_t stackinfo_offset) +{ struct proc *p = l->l_proc; struct sadata *sa; - sa_upcall_t prev; - int error; if (p->p_sa == NULL) { /* Allocate scheduler activations data structure */ @@ -198,13 +214,13 @@ sys_sa_register(struct lwp *l, void *v, register_t *retval) /* Initialize. */ memset(sa, 0, sizeof(*sa)); simple_lock_init(&sa->sa_lock); - sa->sa_flag = SCARG(uap, flags) & SA_FLAG_ALL; + sa->sa_flag = flags & SA_FLAG_ALL; sa->sa_maxconcurrency = 1; sa->sa_concurrency = 1; SPLAY_INIT(&sa->sa_stackstree); sa->sa_stacknext = NULL; - if (SCARG(uap, flags) & SA_FLAG_STACKINFO) - sa->sa_stackinfo_offset = SCARG(uap, stackinfo_offset); + if (flags & SA_FLAG_STACKINFO) + sa->sa_stackinfo_offset = stackinfo_offset; else sa->sa_stackinfo_offset = 0; sa->sa_nstacks = 0; @@ -217,14 +233,8 @@ sys_sa_register(struct lwp *l, void *v, register_t *retval) sa_newcachelwp(l); } - prev = p->p_sa->sa_upcall; - p->p_sa->sa_upcall = SCARG(uap, new); - if (SCARG(uap, old)) { - error = copyout(&prev, SCARG(uap, old), - sizeof(prev)); - if (error) - return (error); - } + *prev = p->p_sa->sa_upcall; + p->p_sa->sa_upcall = new; return (0); } @@ -268,6 +278,7 @@ sa_stackused(struct sastack *sast, struct sadata *sa) { unsigned int gen; + /* COMPAT_NETBSD32: believe it or not, but the following is ok */ if (copyin((void *)&((struct sa_stackinfo_t *) ((char *)sast->sast_stack.ss_sp + sa->sa_stackinfo_offset))->sasi_stackgen, @@ -285,6 +296,7 @@ static inline void sa_setstackfree(struct sastack *sast, struct sadata *sa) { + /* COMPAT_NETBSD32: believe it or not, but the following is ok */ if (copyin((void *)&((struct sa_stackinfo_t *) ((char *)sast->sast_stack.ss_sp + sa->sa_stackinfo_offset))->sasi_stackgen, @@ -354,6 +366,12 @@ sast_compare(struct sastack *a, struct sastack *b) return (0); } +static int +sa_copyin_stack(stack_t *stacks, int index, stack_t *dest) +{ + return copyin(stacks + index, dest, sizeof(stack_t)); +} + int sys_sa_stacks(struct lwp *l, void *v, register_t *retval) { @@ -361,6 +379,14 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval) syscallarg(int) num; syscallarg(stack_t *) stacks; } */ *uap = v; + + return sa_stacks1(l, retval, SCARG(uap, num), SCARG(uap, stacks), sa_copyin_stack); +} + +int +sa_stacks1(struct lwp *l, register_t *retval, int num, stack_t *stacks, + sa_copyin_stack_t do_sa_copyin_stack) +{ struct sadata *sa = l->l_proc->p_sa; struct sastack *sast, newsast; int count, error, f, i; @@ -369,7 +395,7 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval) if (sa == NULL) return (EINVAL); - count = SCARG(uap, num); + count = num; if (count < 0) return (EINVAL); @@ -378,8 +404,7 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval) error = 0; for (i = 0; i < count; i++) { - error = copyin(SCARG(uap, stacks) + i, &newsast.sast_stack, - sizeof(stack_t)); + error = do_sa_copyin_stack(stacks, i, &newsast.sast_stack); if (error) { count = i; break; @@ -736,7 +761,7 @@ sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted, struct sadata *sa = l->l_proc->p_sa; struct sadata_vp *vp = l->l_savp; struct sastack *sast; - int f; + int f, error; /* XXX prevent recursive upcalls if we sleep for memory */ SA_LWP_STATE_LOCK(l, f); @@ -748,6 +773,13 @@ sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted, DPRINTFN(9,("sa_upcall(%d.%d) using stack %p\n", l->l_proc->p_pid, l->l_lid, sast->sast_stack.ss_sp)); + if (l->l_proc->p_emul->e_sa->sae_upcallconv) { + error = (*l->l_proc->p_emul->e_sa->sae_upcallconv)(l, type, + &argsize, &arg, &func); + if (error) + return error; + } + SA_LWP_STATE_LOCK(l, f); sau = sadata_upcall_alloc(1); SA_LWP_STATE_UNLOCK(l, f); @@ -786,6 +818,13 @@ sa_upcall0(struct sadata_upcall *sau, int type, struct lwp *event, sau->sau_argfreefunc = func; } +void * +sa_ucsp(void *arg) +{ + ucontext_t *uc = arg; + + return (void *)(uintptr_t)_UC_MACHINE_SP(uc); +} static void sa_upcall_getstate(union sau_state *ss, struct lwp *l) @@ -795,12 +834,15 @@ sa_upcall_getstate(union sau_state *ss, struct lwp *l) if (l) { l->l_flag |= L_SA_SWITCHING; - getucontext(l, &ss->ss_captured.ss_ctx); + (*l->l_proc->p_emul->e_sa->sae_getucontext)(l, + (void *)&ss->ss_captured.ss_ctx); l->l_flag &= ~L_SA_SWITCHING; - sp = (void *) - ((intptr_t)_UC_MACHINE_SP(&ss->ss_captured.ss_ctx)); + sp = (*l->l_proc->p_emul->e_sa->sae_ucsp) + (&ss->ss_captured.ss_ctx); + /* XXX COMPAT_NETBSD32: _UC_UCONTEXT_ALIGN */ sp = STACK_ALIGN(sp, ~_UC_UCONTEXT_ALIGN); - ucsize = roundup(sizeof(ucontext_t), (~_UC_UCONTEXT_ALIGN) + 1); + ucsize = roundup(l->l_proc->p_emul->e_sa->sae_ucsize, + (~_UC_UCONTEXT_ALIGN) + 1); ss->ss_captured.ss_sa.sa_context = (ucontext_t *) STACK_ALLOC(sp, ucsize); ss->ss_captured.ss_sa.sa_id = l->l_lid; @@ -837,7 +879,7 @@ sa_pagefault(struct lwp *l, ucontext_t *l_ctx) return 1; } - sast.sast_stack.ss_sp = (void *)(intptr_t)_UC_MACHINE_SP(l_ctx); + sast.sast_stack.ss_sp = (*p->p_emul->e_sa->sae_ucsp)(l_ctx); sast.sast_stack.ss_size = 1; if (SPLAY_FIND(sasttree, &sa->sa_stackstree, &sast)) { @@ -1307,21 +1349,24 @@ sa_makeupcalls(struct lwp *l) { struct lwp *l2, *eventq; struct proc *p; + const struct sa_emul *sae; struct sadata *sa; struct sadata_vp *vp; - struct sa_t **sapp, *sap; + uintptr_t sapp, sap; struct sa_t self_sa; struct sa_t *sas[3], *sasp; struct sadata_upcall *sau; union sau_state e_ss; void *stack, *ap; ucontext_t u, *up; - size_t sz; - int i, nint, nevents, s, type; + size_t sz, ucsize; + int i, nint, nevents, s, type, error; p = l->l_proc; + sae = p->p_emul->e_sa; sa = p->p_sa; vp = l->l_savp; + ucsize = sae->sae_ucsize; sau = SIMPLEQ_FIRST(&vp->savp_upcalls); SIMPLEQ_REMOVE_HEAD(&vp->savp_upcalls, sau_next); @@ -1348,7 +1393,7 @@ sa_makeupcalls(struct lwp *l) if (sau->sau_event.ss_captured.ss_sa.sa_context != NULL) { if (copyout(&sau->sau_event.ss_captured.ss_ctx, sau->sau_event.ss_captured.ss_sa.sa_context, - sizeof(ucontext_t)) != 0) { + ucsize) != 0) { #ifdef DIAGNOSTIC printf("sa_makeupcalls(%d.%d): couldn't copyout" " context of event LWP %d\n", @@ -1366,7 +1411,7 @@ sa_makeupcalls(struct lwp *l) sau->sau_event.ss_captured.ss_sa.sa_context); if (copyout(&sau->sau_interrupted.ss_captured.ss_ctx, sau->sau_interrupted.ss_captured.ss_sa.sa_context, - sizeof(ucontext_t)) != 0) { + ucsize) != 0) { #ifdef DIAGNOSTIC printf("sa_makeupcalls(%d.%d): couldn't copyout" " context of interrupted LWP %d\n", @@ -1396,10 +1441,14 @@ sa_makeupcalls(struct lwp *l) u.uc_stack = sau->sau_stack; u.uc_flags = _UC_STACK; - up = (void *)STACK_ALLOC(stack, sizeof(ucontext_t)); - stack = STACK_GROW(stack, sizeof(ucontext_t)); + up = (void *)STACK_ALLOC(stack, ucsize); + stack = STACK_GROW(stack, ucsize); - if (copyout(&u, up, sizeof(ucontext_t)) != 0) { + if (sae->sae_sacopyout != NULL) + error = (*sae->sae_sacopyout)(SAOUT_UCONTEXT, &u, up); + else + error = copyout(&u, up, ucsize); + if (error) { sadata_upcall_free(sau); #ifdef DIAGNOSTIC printf("sa_makeupcalls: couldn't copyout activation" @@ -1413,20 +1462,20 @@ sa_makeupcalls(struct lwp *l) /* Next, copy out the sa_t's and pointers to them. */ - sz = (1 + nevents + nint) * sizeof(struct sa_t); - sap = (void *)STACK_ALLOC(stack, sz); - sap += 1 + nevents + nint; + sz = (1 + nevents + nint) * sae->sae_sasize; + sap = (uintptr_t)STACK_ALLOC(stack, sz); + sap += sz; stack = STACK_GROW(stack, sz); - sz = (1 + nevents + nint) * sizeof(struct sa_t *); - sapp = (void *)STACK_ALLOC(stack, sz); - sapp += 1 + nevents + nint; + sz = (1 + nevents + nint) * sae->sae_sapsize; + sapp = (uintptr_t)STACK_ALLOC(stack, sz); + sapp += sz; stack = STACK_GROW(stack, sz); KDASSERT(nint <= 1); for (i = nevents + nint; i >= 0; i--) { - sap--; - sapp--; + sap -= sae->sae_sasize; + sapp -= sae->sae_sapsize; if (i == 1 + nevents) /* interrupted sa */ sasp = sas[2]; else if (i <= 1) /* self_sa and event sa */ @@ -1447,7 +1496,7 @@ sa_makeupcalls(struct lwp *l) if (copyout(&e_ss.ss_captured.ss_ctx, e_ss.ss_captured.ss_sa.sa_context, - sizeof(ucontext_t)) != 0) { + ucsize) != 0) { #ifdef DIAGNOSTIC printf("sa_makeupcalls(%d.%d): couldn't copyout" " context of event LWP %d\n", @@ -1458,8 +1507,12 @@ sa_makeupcalls(struct lwp *l) } sasp = &e_ss.ss_captured.ss_sa; } - if ((copyout(sasp, sap, sizeof(struct sa_t)) != 0) || - (copyout(&sap, sapp, sizeof(struct sa_t *)) != 0)) { + if ((sae->sae_sacopyout != NULL && + ((*sae->sae_sacopyout)(SAOUT_SA_T, sasp, (void *)sap) || + (*sae->sae_sacopyout)(SAOUT_SAP_T, &sap, (void *)sapp))) || + (sae->sae_sacopyout == NULL && + (copyout(sasp, (void *)sap, sizeof(struct sa_t)) || + copyout(&sap, (void *)sapp, sizeof(struct sa_t *))))) { /* Copying onto the stack didn't work. Die. */ sadata_upcall_free(sau); #ifdef DIAGNOSTIC @@ -1506,9 +1559,10 @@ sa_makeupcalls(struct lwp *l) #ifdef KTRACE if (KTRPOINT(p, KTR_SAUPCALL)) - ktrsaupcall(l, type, nevents, nint, sapp, ap); + ktrsaupcall(l, type, nevents, nint, (void *)sapp, ap); #endif - cpu_upcall(l, type, nevents, nint, sapp, ap, stack, sa->sa_upcall); + (*sae->sae_upcall)(l, type, nevents, nint, (void *)sapp, ap, stack, + sa->sa_upcall); l->l_flag &= ~L_SA_YIELD; } diff --git a/sys/sys/lwp.h b/sys/sys/lwp.h index 49b08637fcdc..20268f60c11d 100644 --- a/sys/sys/lwp.h +++ b/sys/sys/lwp.h @@ -1,4 +1,4 @@ -/* $NetBSD: lwp.h,v 1.33 2006/02/16 20:17:20 perry Exp $ */ +/* $NetBSD: lwp.h,v 1.34 2006/03/29 23:02:31 cube Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -180,6 +180,7 @@ void lwp_exit (struct lwp *); void lwp_exit2 (struct lwp *); struct lwp *proc_representative_lwp(struct proc *); __inline int lwp_suspend(struct lwp *, struct lwp *); +int lwp_create1(struct lwp *, const void *, size_t, u_long, lwpid_t *); #endif /* _KERNEL */ /* Flags for _lwp_create(), as per Solaris. */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 06f627fc0896..be241bee75a2 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.217 2006/03/20 13:14:37 drochner Exp $ */ +/* $NetBSD: proc.h,v 1.218 2006/03/29 23:02:31 cube Exp $ */ /*- * Copyright (c) 1986, 1989, 1991, 1993 @@ -86,6 +86,7 @@ struct pgrp { struct exec_package; struct ps_strings; struct ras; +struct sa_emul; struct emul { const char *e_name; /* Symbolic name */ @@ -131,6 +132,9 @@ struct emul { /* Emulation-specific hook for userspace page faults */ int (*e_usertrap)(struct lwp *, vaddr_t, void *); + + /* SA-related information */ + const struct sa_emul *e_sa; }; /* diff --git a/sys/sys/savar.h b/sys/sys/savar.h index 799842ec264a..e268223379ec 100644 --- a/sys/sys/savar.h +++ b/sys/sys/savar.h @@ -1,4 +1,4 @@ -/* $NetBSD: savar.h,v 1.17 2005/12/03 17:10:46 christos Exp $ */ +/* $NetBSD: savar.h,v 1.18 2006/03/29 23:02:31 cube Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -57,6 +57,19 @@ union sau_state { } ss_deferred; }; +struct sa_emul { + size_t sae_ucsize; /* Size of ucontext_t */ + size_t sae_sasize; /* Size of sa_t */ + size_t sae_sapsize; /* Size of (sa_t *) */ + int (*sae_sacopyout)(int, const void *, void *); + int (*sae_upcallconv)(struct lwp *, int, size_t *, void **, + void (**)(void *)); + void (*sae_upcall)(struct lwp *, int, int, int, void *, + void *, void *, sa_upcall_t); + void (*sae_getucontext)(struct lwp *, void *); + void *(*sae_ucsp)(void *); /* Stack ptr from an ucontext_t */ +}; + struct sadata_upcall { SIMPLEQ_ENTRY(sadata_upcall) sau_next; int sau_flags; @@ -146,4 +159,15 @@ void sa_unblock_userret(struct lwp *); void sa_upcall_userret(struct lwp *); void cpu_upcall(struct lwp *, int, int, int, void *, void *, void *, sa_upcall_t); +typedef int (*sa_copyin_stack_t)(stack_t *, int, stack_t *); +int sa_stacks1(struct lwp *, register_t *, int, stack_t *, + sa_copyin_stack_t); +int dosa_register(struct lwp *, sa_upcall_t, sa_upcall_t *, int, ssize_t); + +void *sa_ucsp(void *); + +#define SAOUT_UCONTEXT 0 +#define SAOUT_SA_T 1 +#define SAOUT_SAP_T 2 + #endif /* !_SYS_SAVAR_H_ */