Subject: nathanw_sa changes for sh3
To: None <port-sh3@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: port-sh3
Date: 06/20/2002 23:37:10
--DocE+STaALJfprDB
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Tonight I wrote the sh3-specific changes for nathanw_sa for sh3.  The
kernel links, but I have not yet booted it (my test machine will be
a Dreamcast).

I'll do a test boot tomorrow, but I'd like to get some feedback from
folks who might be more familiar w/ SH than me.

My concerns:

	* changes to locore_subr.S follow register saving
	  rules.

	* cpu_setfunc() is correct

	* cpu_exit(): I'm worried that the stack changes in
	  the middle of this function.

Anyway, if it boots on my DC, I'll check it in, and then make the
other SH ports compile.

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>

--DocE+STaALJfprDB
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=sh3-sa-patch

Index: include/cpu.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/include/cpu.h,v
retrieving revision 1.29
diff -c -r1.29 cpu.h
*** include/cpu.h	2002/05/07 04:01:59	1.29
--- include/cpu.h	2002/06/21 06:11:17
***************
*** 80,85 ****
--- 80,86 ----
   */
  #define	cpu_swapin(p)			/* nothing */
  #define	cpu_swapout(p)			panic("cpu_swapout: can't get here");
+ #define	cpu_proc_fork(p1, p2)		/* nothing */
  
  /*
   * Arguments to hardclock and gatherstats encapsulate the previous
***************
*** 111,117 ****
  do {									\
  	want_resched = 1;						\
  	if (curproc != NULL)						\
! 		aston(curproc);						\
  } while (/*CONSTCOND*/0)
  
  /*
--- 112,118 ----
  do {									\
  	want_resched = 1;						\
  	if (curproc != NULL)						\
! 		aston(curproc->l_proc);					\
  } while (/*CONSTCOND*/0)
  
  /*
Index: include/frame.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/include/frame.h,v
retrieving revision 1.8
diff -c -r1.8 frame.h
*** include/frame.h	2002/05/09 12:25:41	1.8
--- include/frame.h	2002/06/21 06:11:17
***************
*** 44,49 ****
--- 44,50 ----
  #define	_SH3_FRAME_H_
  
  #include <sys/signal.h>
+ #include <sys/sa.h>
  
  /*
   * Exception Stack Frame
***************
*** 103,108 ****
--- 104,123 ----
  	struct	sigcontext *sf_scp;
  	sig_t	sf_handler;
  	struct	sigcontext sf_sc;
+ };
+ 
+ /*
+  * Scheduler activations upcall frame
+  */
+ struct saframe {
+ #if 0 /* in registers on entry to upcallcode */
+ 	int		sa_type;	/* r4 */
+ 	struct sa_t **	sa_sas;		/* r5 */
+ 	int		sa_events;	/* r6 */
+ 	int		sa_interrupted;	/* r7 */
+ #endif
+ 	void *		sa_arg;
+ 	sa_upcall_t	sa_upcall;
  };
  
  #endif /* !_SH3_FRAME_H_ */
Index: include/locore.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/include/locore.h,v
retrieving revision 1.7
diff -c -r1.7 locore.h
*** include/locore.h	2002/05/09 12:25:41	1.7
--- include/locore.h	2002/06/21 06:11:18
***************
*** 198,206 ****
  	ldc	Rm,	sr	/* unmask all interrupt */
  
  #ifndef _LOCORE
! void sh3_switch_setup(struct proc *);
! void sh4_switch_setup(struct proc *);
! void sh3_switch_resume(struct proc *);
! void sh4_switch_resume(struct proc *);
! extern void (*__sh_switch_resume)(struct proc *);
  #endif /* !_LOCORE */
--- 198,206 ----
  	ldc	Rm,	sr	/* unmask all interrupt */
  
  #ifndef _LOCORE
! void sh3_switch_setup(struct lwp *);
! void sh4_switch_setup(struct lwp *);
! void sh3_switch_resume(struct lwp *);
! void sh4_switch_resume(struct lwp *);
! extern void (*__sh_switch_resume)(struct lwp *);
  #endif /* !_LOCORE */
Index: include/proc.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/include/proc.h,v
retrieving revision 1.4
diff -c -r1.4 proc.h
*** include/proc.h	2002/05/09 12:28:08	1.4
--- include/proc.h	2002/06/21 06:11:18
***************
*** 38,43 ****
--- 38,44 ----
  
  #ifndef _SH3_PROC_H_
  #define	_SH3_PROC_H_
+ 
  /*
   * Machine-dependent part of the proc structure for sh3.
   */
***************
*** 48,64 ****
  	u_int32_t data;
  };
  
! struct mdproc {
  	struct trapframe *md_regs;	/* user context */
  	struct pcb *md_pcb;		/* pcb access address */
  	int md_flags;			/* machine-dependent flags */
  	/* u-area PTE: *2 .. SH4 data/address data array access */
  	struct md_upte md_upte[UPAGES * 2];
- 	__volatile int md_astpending;	/* AST pending on return to userland */
  };
  
  /* md_flags */
  #define	MDP_USEDFPU	0x0001	/* has used the FPU */
  
  #ifdef _KERNEL
  #ifndef _LOCORE
--- 49,68 ----
  	u_int32_t data;
  };
  
! struct mdlwp {
  	struct trapframe *md_regs;	/* user context */
  	struct pcb *md_pcb;		/* pcb access address */
  	int md_flags;			/* machine-dependent flags */
  	/* u-area PTE: *2 .. SH4 data/address data array access */
  	struct md_upte md_upte[UPAGES * 2];
  };
  
  /* md_flags */
  #define	MDP_USEDFPU	0x0001	/* has used the FPU */
+ 
+ struct mdproc {
+ 	__volatile int md_astpending;	/* AST pending on return to userland */
+ };
  
  #ifdef _KERNEL
  #ifndef _LOCORE
Index: include/userret.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/include/userret.h,v
retrieving revision 1.3
diff -c -r1.3 userret.h
*** include/userret.h	2002/05/09 12:31:19	1.3
--- include/userret.h	2002/06/21 06:11:18
***************
*** 46,55 ****
  #define	_SH3_USERRET_H_
  
  static __inline void
! userret(struct proc *p)
  {
  
! 	curcpu()->ci_schedstate.spc_curpriority = p->p_priority = p->p_usrpri;
  }
  
  #endif /* !_SH3_USERRET_H_ */
--- 46,69 ----
  #define	_SH3_USERRET_H_
  
  static __inline void
! userret(struct lwp *l)
  {
+ 	struct proc *p = l->l_proc;
+ 	int sig;
  
! 	/* Take pending signals. */
! 	while ((sig = CURSIG(l)) != 0)
! 		postsig(sig);
! 
! 	/* Invoke per-process kernel-exit handling, if any. */
! 	if (p->p_userret)
! 		(*p->p_userret)(l, p->p_userret_arg);
! 
! 	/* Invoke any pending upcalls. */
! 	if (l->l_flag & L_SA_UPCALL)
! 		sa_upcall_userret(l);
! 
! 	curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
  }
  
  #endif /* !_SH3_USERRET_H_ */
Index: sh3/Locore.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/Locore.c,v
retrieving revision 1.12
diff -c -r1.12 Locore.c
*** sh3/Locore.c	2002/05/09 12:28:08	1.12
--- sh3/Locore.c	2002/06/21 06:11:18
***************
*** 94,101 ****
  #include <sh3/mmu_sh3.h>
  #include <sh3/mmu_sh4.h>
  
! void (*__sh_switch_resume)(struct proc *);
! struct proc *cpu_switch_search(struct proc *);
  void idle(void);
  int want_resched;
  
--- 94,101 ----
  #include <sh3/mmu_sh3.h>
  #include <sh3/mmu_sh4.h>
  
! void (*__sh_switch_resume)(struct lwp *);
! struct lwp *cpu_switch_search(struct lwp *);
  void idle(void);
  int want_resched;
  
***************
*** 111,121 ****
   * struct proc *cpu_switch_search(struct proc *oldproc):
   *	Find the highest priority process.
   */
! struct proc *
! cpu_switch_search(struct proc *oldproc)
  {
  	struct prochd *q;
! 	struct proc *p;
  
  	curproc = 0;
  
--- 111,121 ----
   * struct proc *cpu_switch_search(struct proc *oldproc):
   *	Find the highest priority process.
   */
! struct lwp *
! cpu_switch_search(struct lwp *oldlwp)
  {
  	struct prochd *q;
! 	struct lwp *l;
  
  	curproc = 0;
  
***************
*** 127,146 ****
  	}
  
  	q = &sched_qs[ffs(sched_whichqs) - 1];
! 	p = q->ph_link;
! 	remrunqueue(p);
  	want_resched = 0;
  	SCHED_UNLOCK_IDLE();
  
! 	p->p_stat = SONPROC;
  
! 	if (p != oldproc) {
! 		curpcb = p->p_md.md_pcb;
! 		pmap_activate(p);
  	}
! 	curproc = p;
  
! 	return (p);
  }
  
  /*
--- 127,146 ----
  	}
  
  	q = &sched_qs[ffs(sched_whichqs) - 1];
! 	l = q->ph_link;
! 	remrunqueue(l);
  	want_resched = 0;
  	SCHED_UNLOCK_IDLE();
  
! 	l->l_stat = LSONPROC;
  
! 	if (l != oldlwp) {
! 		curpcb = l->l_md.md_pcb;
! 		pmap_activate(l);
  	}
! 	curproc = l;
  
! 	return (l);
  }
  
  /*
***************
*** 159,176 ****
  }
  
  /*
!  * Put process p on the run queue indicated by its priority.
!  * Calls should be made at splstatclock(), and p->p_stat should be SRUN.
   */
  void
! setrunqueue(struct proc *p)
  {
  	struct prochd *q;
! 	struct proc *oldlast;
! 	int which = p->p_priority >> 2;
  
  #ifdef DIAGNOSTIC
! 	if (p->p_back || which >= 32 || which < 0)
  		panic("setrunqueue");
  #endif
  	q = &sched_qs[which];
--- 159,176 ----
  }
  
  /*
!  * Put lwp p on the run queue indicated by its priority.
!  * Calls should be made at splstatclock(), and l->l_stat should be SRUN.
   */
  void
! setrunqueue(struct lwp *l)
  {
  	struct prochd *q;
! 	struct lwp *oldlast;
! 	int which = l->l_priority >> 2;
  
  #ifdef DIAGNOSTIC
! 	if (l->l_back || which >= 32 || which < 0)
  		panic("setrunqueue");
  #endif
  	q = &sched_qs[which];
***************
*** 178,225 ****
  	if (sched_whichqs == 0) {
  		panic("setrunqueue[whichqs == 0 ]");
  	}
! 	p->p_forw = (struct proc *)q;
! 	p->p_back = oldlast = q->ph_rlink;
! 	q->ph_rlink = p;
! 	oldlast->p_forw = p;
  }
  
  /*
!  * Remove process p from its run queue, which should be the one
   * indicated by its priority.
   * Calls should be made at splstatclock().
   */
  void
! remrunqueue(struct proc *p)
  {
! 	int which = p->p_priority >> 2;
  	struct prochd *q;
  
  #ifdef DIAGNOSTIC
  	if (!(sched_whichqs & (0x00000001 << which)))
  		panic("remrunqueue");
  #endif
! 	p->p_forw->p_back = p->p_back;
! 	p->p_back->p_forw = p->p_forw;
! 	p->p_back = NULL;
  	q = &sched_qs[which];
! 	if (q->ph_link == (struct proc *)q)
  		sched_whichqs &= ~(0x00000001 << which);
  }
  
  /*
!  * void sh3_switch_setup(struct proc *p):
   *	prepare kernel stack PTE table. TLB miss handler check these.
   */
  void
! sh3_switch_setup(struct proc *p)
  {
  	pt_entry_t *pte;
! 	struct md_upte *md_upte = p->p_md.md_upte;
  	u_int32_t vpn;
  	int i;
  
! 	vpn = (u_int32_t)p->p_addr;
  	vpn &= ~PGOFSET;
  	for (i = 0; i < UPAGES; i++, vpn += NBPG, md_upte++) {
  		pte = __pmap_kpte_lookup(vpn);
--- 178,225 ----
  	if (sched_whichqs == 0) {
  		panic("setrunqueue[whichqs == 0 ]");
  	}
! 	l->l_forw = (struct lwp *)q;
! 	l->l_back = oldlast = q->ph_rlink;
! 	q->ph_rlink = l;
! 	oldlast->l_forw = l;
  }
  
  /*
!  * Remove process l from its run queue, which should be the one
   * indicated by its priority.
   * Calls should be made at splstatclock().
   */
  void
! remrunqueue(struct lwp *l)
  {
! 	int which = l->l_priority >> 2;
  	struct prochd *q;
  
  #ifdef DIAGNOSTIC
  	if (!(sched_whichqs & (0x00000001 << which)))
  		panic("remrunqueue");
  #endif
! 	l->l_forw->l_back = l->l_back;
! 	l->l_back->l_forw = l->l_forw;
! 	l->l_back = NULL;
  	q = &sched_qs[which];
! 	if (q->ph_link == (struct lwp *)q)
  		sched_whichqs &= ~(0x00000001 << which);
  }
  
  /*
!  * void sh3_switch_setup(struct lwp *l):
   *	prepare kernel stack PTE table. TLB miss handler check these.
   */
  void
! sh3_switch_setup(struct lwp *l)
  {
  	pt_entry_t *pte;
! 	struct md_upte *md_upte = l->l_md.md_upte;
  	u_int32_t vpn;
  	int i;
  
! 	vpn = (u_int32_t)l->l_addr;
  	vpn &= ~PGOFSET;
  	for (i = 0; i < UPAGES; i++, vpn += NBPG, md_upte++) {
  		pte = __pmap_kpte_lookup(vpn);
***************
*** 231,248 ****
  }
  
  /*
!  * void sh4_switch_setup(struct proc *p):
   *	prepare kernel stack PTE table. sh4_switch_resume wired this PTE.
   */
  void
! sh4_switch_setup(struct proc *p)
  {
  	pt_entry_t *pte;
! 	struct md_upte *md_upte = p->p_md.md_upte;
  	u_int32_t vpn;
  	int i, e;
  
! 	vpn = (u_int32_t)p->p_addr;
  	vpn &= ~PGOFSET;
  	e = SH4_UTLB_ENTRY - UPAGES;
  	for (i = 0; i < UPAGES; i++, e++, vpn += NBPG) {
--- 231,248 ----
  }
  
  /*
!  * void sh4_switch_setup(struct lwp *l):
   *	prepare kernel stack PTE table. sh4_switch_resume wired this PTE.
   */
  void
! sh4_switch_setup(struct lwp *l)
  {
  	pt_entry_t *pte;
! 	struct md_upte *md_upte = l->l_md.md_upte;
  	u_int32_t vpn;
  	int i, e;
  
! 	vpn = (u_int32_t)l->l_addr;
  	vpn &= ~PGOFSET;
  	e = SH4_UTLB_ENTRY - UPAGES;
  	for (i = 0; i < UPAGES; i++, e++, vpn += NBPG) {
Index: sh3/exception.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/exception.c,v
retrieving revision 1.2
diff -c -r1.2 exception.c
*** sh3/exception.c	2002/06/17 16:33:17	1.2
--- sh3/exception.c	2002/06/21 06:11:19
***************
*** 55,64 ****
--- 55,67 ----
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/proc.h>
+ #include <sys/pool.h>
  #include <sys/user.h>
  #include <sys/kernel.h>
  #include <sys/signal.h>
  #include <sys/syscall.h>
+ #include <sys/sa.h>
+ #include <sys/savar.h>
  
  #ifdef KTRACE
  #include <sys/ktrace.h>
***************
*** 100,128 ****
  };
  const int exp_types = sizeof exp_type / sizeof exp_type[0];
  
! void general_exception(struct proc *, struct trapframe *);
! void tlb_exception(struct proc *, struct trapframe *, u_int32_t);
! void syscall(struct proc *, struct trapframe *);
! void ast(struct proc *, struct trapframe *);
  
  /*
!  * void general_exception(struct proc *p, struct trapframe *tf):
!  *	p  ... curproc when exception occur.
   *	tf ... full user context.
   */
  void
! general_exception(struct proc *p, struct trapframe *tf)
  {
  	int expevt = tf->tf_expevt;
  	boolean_t usermode = !KERNELMODE(tf->tf_ssr);
  
  	uvmexp.traps++;
  
! 	if (p == NULL)
   		goto do_panic;
  
  	if (usermode) {
! 		KDASSERT(p->p_md.md_regs == tf); /* check exception depth */
  		expevt |= EXP_USER;
  	}
  
--- 103,131 ----
  };
  const int exp_types = sizeof exp_type / sizeof exp_type[0];
  
! void general_exception(struct lwp *, struct trapframe *);
! void tlb_exception(struct lwp *, struct trapframe *, u_int32_t);
! void syscall(struct lwp *, struct trapframe *);
! void ast(struct lwp *, struct trapframe *);
  
  /*
!  * void general_exception(struct lwp *l, struct trapframe *tf):
!  *	l  ... curproc when exception occur.
   *	tf ... full user context.
   */
  void
! general_exception(struct lwp *l, struct trapframe *tf)
  {
  	int expevt = tf->tf_expevt;
  	boolean_t usermode = !KERNELMODE(tf->tf_ssr);
  
  	uvmexp.traps++;
  
! 	if (l == NULL)
   		goto do_panic;
  
  	if (usermode) {
! 		KDASSERT(l->l_md.md_regs == tf); /* check exception depth */
  		expevt |= EXP_USER;
  	}
  
***************
*** 130,146 ****
  	case EXPEVT_TRAPA | EXP_USER:
  		/* Check for debugger break */
  		if (_reg_read_4(SH_(TRA)) == (_SH_TRA_BREAK << 2)) {
! 			trapsignal(p, SIGTRAP, tf->tf_expevt);
  		} else {
! 			syscall(p, tf);
  			return;
  		}
  		break;
  	case EXPEVT_ADDR_ERR_LD:
  		/*FALLTHROUGH*/
  	case EXPEVT_ADDR_ERR_ST:
! 		KDASSERT(p->p_md.md_pcb->pcb_onfault != NULL);
! 		tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
  		if (tf->tf_spc == NULL)
  			goto do_panic;
  		break;
--- 133,149 ----
  	case EXPEVT_TRAPA | EXP_USER:
  		/* Check for debugger break */
  		if (_reg_read_4(SH_(TRA)) == (_SH_TRA_BREAK << 2)) {
! 			trapsignal(l, SIGTRAP, tf->tf_expevt);
  		} else {
! 			syscall(l, tf);
  			return;
  		}
  		break;
  	case EXPEVT_ADDR_ERR_LD:
  		/*FALLTHROUGH*/
  	case EXPEVT_ADDR_ERR_ST:
! 		KDASSERT(l->l_md.md_pcb->pcb_onfault != NULL);
! 		tf->tf_spc = (int)l->l_md.md_pcb->pcb_onfault;
  		if (tf->tf_spc == NULL)
  			goto do_panic;
  		break;
***************
*** 148,171 ****
  	case EXPEVT_ADDR_ERR_LD | EXP_USER:
  		/*FALLTHROUGH*/
  	case EXPEVT_ADDR_ERR_ST | EXP_USER:
! 		trapsignal(p, SIGSEGV, tf->tf_expevt);
  		break;
  
  	case EXPEVT_RES_INST | EXP_USER:
  		/*FALLTHROUGH*/
  	case EXPEVT_SLOT_INST | EXP_USER:
! 		trapsignal(p, SIGILL, tf->tf_expevt);
  		break;
  
  	case EXPEVT_BREAK | EXP_USER:
! 		trapsignal(p, SIGTRAP, tf->tf_expevt);
  		break;
  	default:
  		goto do_panic;
  	}
  
  	if (usermode)
! 		userret(p);
  	return;
  
   do_panic:
--- 151,174 ----
  	case EXPEVT_ADDR_ERR_LD | EXP_USER:
  		/*FALLTHROUGH*/
  	case EXPEVT_ADDR_ERR_ST | EXP_USER:
! 		trapsignal(l, SIGSEGV, tf->tf_expevt);
  		break;
  
  	case EXPEVT_RES_INST | EXP_USER:
  		/*FALLTHROUGH*/
  	case EXPEVT_SLOT_INST | EXP_USER:
! 		trapsignal(l, SIGILL, tf->tf_expevt);
  		break;
  
  	case EXPEVT_BREAK | EXP_USER:
! 		trapsignal(l, SIGTRAP, tf->tf_expevt);
  		break;
  	default:
  		goto do_panic;
  	}
  
  	if (usermode)
! 		userret(l);
  	return;
  
   do_panic:
***************
*** 191,204 ****
  }
  
  /*
!  * void syscall(struct proc *p, struct trapframe *tf):
!  *	p  ... curproc when exception occur.
   *	tf ... full user context.
   *	System call request from POSIX system call gate interface to kernel.
   */
  void
! syscall(struct proc *p, struct trapframe *tf)
  {
  	caddr_t params;
  	const struct sysent *callp;
  	int error, opc, nsys;
--- 194,208 ----
  }
  
  /*
!  * void syscall(struct lwp *l, struct trapframe *tf):
!  *	l  ... curproc when exception occur.
   *	tf ... full user context.
   *	System call request from POSIX system call gate interface to kernel.
   */
  void
! syscall(struct lwp *l, struct trapframe *tf)
  {
+ 	struct proc *p = l->l_proc;
  	caddr_t params;
  	const struct sysent *callp;
  	int error, opc, nsys;
***************
*** 292,310 ****
  	if (error)
  		goto bad;
  
! 	if ((error = trace_enter(p, code, args, rval)) != 0)
  		goto bad;
  
  	rval[0] = 0;
  	rval[1] = tf->tf_r1;
! 	error = (*callp->sy_call)(p, args, rval);
  	switch (error) {
  	case 0:
- 		/*
- 		 * Reinitialize proc pointer `p' as it may be different
- 		 * if this is a child returning from fork syscall.
- 		 */
- 		p = curproc;
  		tf->tf_r0 = rval[0];
  		tf->tf_r1 = rval[1];
  		tf->tf_ssr |= PSL_TBIT;	/* T bit */
--- 296,309 ----
  	if (error)
  		goto bad;
  
! 	if ((error = trace_enter(l, code, args, rval)) != 0)
  		goto bad;
  
  	rval[0] = 0;
  	rval[1] = tf->tf_r1;
! 	error = (*callp->sy_call)(l, args, rval);
  	switch (error) {
  	case 0:
  		tf->tf_r0 = rval[0];
  		tf->tf_r1 = rval[1];
  		tf->tf_ssr |= PSL_TBIT;	/* T bit */
***************
*** 329,347 ****
  	}
  
  
! 	trace_exit(p, code, args, rval, error);
  
! 	userret(p);
  }
  
  /*
!  * void tlb_exception(struct proc *p, struct trapframe *tf, u_int32_t va):
!  *	p  ... curproc when exception occur.
   *	tf ... full user context.
   *	va ... fault address.
   */
  void
! tlb_exception(struct proc *p, struct trapframe *tf, u_int32_t va)
  {
  #define	TLB_ASSERT(assert, msg)						\
  do {									\
--- 328,346 ----
  	}
  
  
! 	trace_exit(l, code, args, rval, error);
  
! 	userret(l);
  }
  
  /*
!  * void tlb_exception(struct lwp *l, struct trapframe *tf, u_int32_t va):
!  *	l  ... curproc when exception occur.
   *	tf ... full user context.
   *	va ... fault address.
   */
  void
! tlb_exception(struct lwp *l, struct trapframe *tf, u_int32_t va)
  {
  #define	TLB_ASSERT(assert, msg)						\
  do {									\
***************
*** 382,393 ****
  		TLB_ASSERT((int)va > 0,
  		    "kernel virtual protection fault (load)");
  		if (usermode) {
! 			trapsignal(p, SIGSEGV, tf->tf_expevt);
  			goto user_fault;
  		} else {
! 			TLB_ASSERT(p && p->p_md.md_pcb->pcb_onfault != NULL,
  			    "no copyin/out fault handler (load protection)");
! 			tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
  		}
  		return;
  
--- 381,392 ----
  		TLB_ASSERT((int)va > 0,
  		    "kernel virtual protection fault (load)");
  		if (usermode) {
! 			trapsignal(l, SIGSEGV, tf->tf_expevt);
  			goto user_fault;
  		} else {
! 			TLB_ASSERT(l && l->l_md.md_pcb->pcb_onfault != NULL,
  			    "no copyin/out fault handler (load protection)");
! 			tf->tf_spc = (int)l->l_md.md_pcb->pcb_onfault;
  		}
  		return;
  
***************
*** 399,416 ****
  
  	/* Select address space */
  	if (usermode) {
! 		TLB_ASSERT(p != NULL, "no curproc");
! 		map = &p->p_vmspace->vm_map;
  		pmap = map->pmap;
  	} else {
  		if ((int)va < 0) {
  			map = kernel_map;
  			pmap = pmap_kernel();
  		} else {
! 			TLB_ASSERT(va != 0 && p != NULL &&
! 			    p->p_md.md_pcb->pcb_onfault != NULL,
  			    "invalid user-space access from kernel mode");
! 			map = &p->p_vmspace->vm_map;
  			pmap = map->pmap;
  		}
  	}
--- 398,415 ----
  
  	/* Select address space */
  	if (usermode) {
! 		TLB_ASSERT(l != NULL, "no curproc");
! 		map = &l->l_proc->p_vmspace->vm_map;
  		pmap = map->pmap;
  	} else {
  		if ((int)va < 0) {
  			map = kernel_map;
  			pmap = pmap_kernel();
  		} else {
! 			TLB_ASSERT(va != 0 && l != NULL &&
! 			    l->l_md.md_pcb->pcb_onfault != NULL,
  			    "invalid user-space access from kernel mode");
! 			map = &l->l_proc->p_vmspace->vm_map;
  			pmap = map->pmap;
  		}
  	}
***************
*** 418,433 ****
  	/* Lookup page table. if entry found, load it. */
  	if (track && __pmap_pte_load(pmap, va, track)) {
  		if (usermode)
! 			userret(p);
  		return;
  	}
  
  	/* Page not found. call fault handler */
  	if (!usermode && pmap != pmap_kernel() &&
! 	    p->p_md.md_pcb->pcb_faultbail) {
! 		TLB_ASSERT(p->p_md.md_pcb->pcb_onfault != NULL,
  		    "no copyin/out fault handler (interrupt context)");
! 		tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
  		return;
  	}
  
--- 417,432 ----
  	/* Lookup page table. if entry found, load it. */
  	if (track && __pmap_pte_load(pmap, va, track)) {
  		if (usermode)
! 			userret(l);
  		return;
  	}
  
  	/* Page not found. call fault handler */
  	if (!usermode && pmap != pmap_kernel() &&
! 	    l->l_md.md_pcb->pcb_faultbail) {
! 		TLB_ASSERT(l->l_md.md_pcb->pcb_onfault != NULL,
  		    "no copyin/out fault handler (interrupt context)");
! 		tf->tf_spc = (int)l->l_md.md_pcb->pcb_onfault;
  		return;
  	}
  
***************
*** 435,443 ****
  
  	/* User stack extension */
  	if (map != kernel_map &&
! 	    (va >= (vaddr_t)p->p_vmspace->vm_maxsaddr) && (va < USRSTACK)) {
  		if (err == 0) {
! 			struct vmspace *vm = p->p_vmspace;
  			u_int32_t nss;
  			nss = btoc(USRSTACK - va);
  			if (nss > vm->vm_ssize)
--- 434,443 ----
  
  	/* User stack extension */
  	if (map != kernel_map &&
! 	    (va >= (vaddr_t)l->l_proc->p_vmspace->vm_maxsaddr) &&
! 	    (va < USRSTACK)) {
  		if (err == 0) {
! 			struct vmspace *vm = l->l_proc->p_vmspace;
  			u_int32_t nss;
  			nss = btoc(USRSTACK - va);
  			if (nss > vm->vm_ssize)
***************
*** 452,501 ****
  		boolean_t loaded = __pmap_pte_load(pmap, va, track);
  		TLB_ASSERT(loaded, "page table entry not found");
  		if (usermode)
! 			userret(p);
  		return;
  	}
  
  	/* Page not found. */
  	if (usermode) {
! 		trapsignal(p, err == ENOMEM ? SIGKILL : SIGSEGV, tf->tf_expevt);
  		goto user_fault;
  	} else {
! 		TLB_ASSERT(p->p_md.md_pcb->pcb_onfault,
  		    "no copyin/out fault handler (page not found)");
! 		tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
  	}
  	return;
  
   user_fault:
! 	userret(p);
! 	ast(p, tf);
  	return;
  
   tlb_panic:
  	panic("tlb_handler: %s va=0x%08x, ssr=0x%08x, spc=0x%08x"
! 	    "  proc=%p onfault=%p", panic_msg, va, tf->tf_ssr, tf->tf_spc,
! 	    p, p ? p->p_md.md_pcb->pcb_onfault : 0);
  #undef	TLB_ASSERT
  }
  
  /*
!  * void ast(struct proc *p, struct trapframe *tf):
!  *	p  ... curproc when exception occur.
   *	tf ... full user context.
   *	This is called when exception return. if return from kernel to user,
   *	handle asynchronous software traps and context switch if needed.
   */
  void
! ast(struct proc *p, struct trapframe *tf)
  {
! 	int sig;
  
  	if (KERNELMODE(tf->tf_ssr))
  		return;
! 	KDASSERT(p != NULL);
! 	KDASSERT(p->p_md.md_regs == tf);
  
  	while (p->p_md.md_astpending) {
  		uvmexp.softs++;
  		p->p_md.md_astpending = 0;
--- 452,503 ----
  		boolean_t loaded = __pmap_pte_load(pmap, va, track);
  		TLB_ASSERT(loaded, "page table entry not found");
  		if (usermode)
! 			userret(l);
  		return;
  	}
  
  	/* Page not found. */
  	if (usermode) {
! 		trapsignal(l, err == ENOMEM ? SIGKILL : SIGSEGV, tf->tf_expevt);
  		goto user_fault;
  	} else {
! 		TLB_ASSERT(l->l_md.md_pcb->pcb_onfault,
  		    "no copyin/out fault handler (page not found)");
! 		tf->tf_spc = (int)l->l_md.md_pcb->pcb_onfault;
  	}
  	return;
  
   user_fault:
! 	userret(l);
! 	ast(l, tf);
  	return;
  
   tlb_panic:
  	panic("tlb_handler: %s va=0x%08x, ssr=0x%08x, spc=0x%08x"
! 	    "  lwp=%p onfault=%p", panic_msg, va, tf->tf_ssr, tf->tf_spc,
! 	    l, l ? l->l_md.md_pcb->pcb_onfault : 0);
  #undef	TLB_ASSERT
  }
  
  /*
!  * void ast(struct lwp *l, struct trapframe *tf):
!  *	l  ... curproc when exception occur.
   *	tf ... full user context.
   *	This is called when exception return. if return from kernel to user,
   *	handle asynchronous software traps and context switch if needed.
   */
  void
! ast(struct lwp *l, struct trapframe *tf)
  {
! 	struct proc *p;
  
  	if (KERNELMODE(tf->tf_ssr))
  		return;
! 	KDASSERT(l != NULL);
! 	KDASSERT(l->p_md.md_regs == tf);
  
+ 	p = l->l_proc;
+ 
  	while (p->p_md.md_astpending) {
  		uvmexp.softs++;
  		p->p_md.md_astpending = 0;
***************
*** 505,520 ****
  			ADDUPROF(p);
  		}
  
- 		/* Take pending signals. */
- 		while ((sig = CURSIG(p)) != 0)
- 			postsig(sig);
- 
  		if (want_resched) {
  			/* We are being preempted. */
  			preempt(NULL);
  		}
  
! 		userret(p);
  	}
  }
  
--- 507,518 ----
  			ADDUPROF(p);
  		}
  
  		if (want_resched) {
  			/* We are being preempted. */
  			preempt(NULL);
  		}
  
! 		userret(l);
  	}
  }
  
***************
*** 527,541 ****
  void
  child_return(void *arg)
  {
! 	struct proc *p = arg;
! 	struct trapframe *tf = p->p_md.md_regs;
  
  	tf->tf_r0 = 0;
  	tf->tf_ssr |= PSL_TBIT; /* This indicates no error. */
  
! 	userret(p);
  #ifdef KTRACE
  	if (KTRPOINT(p, KTR_SYSRET))
  		ktrsysret(p, SYS_fork, 0, 0);
  #endif
  }
--- 525,577 ----
  void
  child_return(void *arg)
  {
! 	struct lwp *l = arg;
! #ifdef KTRACE
! 	struct proc *p = l->l_proc;
! #endif
! 	struct trapframe *tf = l->l_md.md_regs;
  
  	tf->tf_r0 = 0;
  	tf->tf_ssr |= PSL_TBIT; /* This indicates no error. */
  
! 	userret(l);
  #ifdef KTRACE
  	if (KTRPOINT(p, KTR_SYSRET))
  		ktrsysret(p, SYS_fork, 0, 0);
  #endif
+ }
+ 
+ /*
+  * void startlwp(void *arg):
+  *
+  *	Start a new LWP.
+  */
+ void
+ startlwp(void *arg)
+ {
+ 	ucontext_t *uc = arg;
+ 	struct lwp *l = curproc;
+ 	int error;
+ 
+ 	error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
+ #ifdef DIAGNOSTIC
+ 	if (error)
+ 		printf("startlwp: error %d from cpu_setmcontext()", error);
+ #endif
+ 	pool_put(&lwp_uc_pool, uc);
+ 
+ 	userret(l);
+ }
+ 
+ /*
+  * void upcallret(struct lwp *l):
+  *
+  *	Perform userret() for an LWP.
+  *	XXX This is a terrible name.
+  */
+ void
+ upcallret(struct lwp *l)
+ {
+ 
+ 	userret(l);
  }
Index: sh3/genassym.cf
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/genassym.cf,v
retrieving revision 1.5
diff -c -r1.5 genassym.cf
*** sh3/genassym.cf	2002/05/09 12:29:16	1.5
--- sh3/genassym.cf	2002/06/21 06:11:19
***************
*** 67,82 ****
  define	TF_R0			offsetof(struct trapframe, tf_r0)
  define	TF_R15			offsetof(struct trapframe, tf_r15)
  
! define	P_ADDR			offsetof(struct proc, p_addr)
! define	P_BACK			offsetof(struct proc, p_back)
! define	P_FORW			offsetof(struct proc, p_forw)
! define	P_STAT			offsetof(struct proc, p_stat)
! define	P_WCHAN			offsetof(struct proc, p_wchan)
! define	P_MD			offsetof(struct proc, p_md)
  
! define	MD_UPTE			offsetof(struct mdproc, md_upte)
! define	MD_PCB			offsetof(struct mdproc,	md_pcb)
  
  define	SF_SIZE			sizeof(struct switchframe)
  define	SF_SR			offsetof(struct switchframe, sf_sr)
  define	SF_R15			offsetof(struct switchframe, sf_r15)
--- 67,85 ----
  define	TF_R0			offsetof(struct trapframe, tf_r0)
  define	TF_R15			offsetof(struct trapframe, tf_r15)
  
! define	L_ADDR			offsetof(struct lwp, l_addr)
! define	L_BACK			offsetof(struct lwp, l_back)
! define	L_FORW			offsetof(struct lwp, l_forw)
! define	L_STAT			offsetof(struct lwp, l_stat)
! define	L_WCHAN			offsetof(struct lwp, l_wchan)
  
! define	L_MD_UPTE		offsetof(struct lwp, l_md.md_upte)
! define	L_MD_PCB		offsetof(struct lwp, l_md.md_pcb)
  
+ #define	P_MD			offsetof(struct proc, p_md)
+ #define	MD_UPTE			offsetof(struct mdproc, md_upte)
+ #define	MD_PCB			offsetof(struct mdproc,	md_pcb)
+ 
  define	SF_SIZE			sizeof(struct switchframe)
  define	SF_SR			offsetof(struct switchframe, sf_sr)
  define	SF_R15			offsetof(struct switchframe, sf_r15)
***************
*** 93,102 ****
  define	SIGF_HANDLER		offsetof(struct sigframe, sf_handler)
  define	SIGF_SC			offsetof(struct sigframe, sf_sc)
  define	SC_EFLAGS		offsetof(struct sigcontext, sc_ssr)
  
! # can't include sys/proc.h directly.
! define	SONPROC			SONPROC
! define	SRUN			SRUN
  
  define	UVMEXP_INTRS		offsetof(struct uvmexp, intrs)
  
--- 96,106 ----
  define	SIGF_HANDLER		offsetof(struct sigframe, sf_handler)
  define	SIGF_SC			offsetof(struct sigframe, sf_sc)
  define	SC_EFLAGS		offsetof(struct sigcontext, sc_ssr)
+ 
+ define	SAF_UPCALL		offsetof(struct saframe, sa_upcall)
  
! define	LSONPROC		LSONPROC
! define	LSRUN			LSRUN
  
  define	UVMEXP_INTRS		offsetof(struct uvmexp, intrs)
  
Index: sh3/locore_subr.S
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/locore_subr.S,v
retrieving revision 1.10
diff -c -r1.10 locore_subr.S
*** sh3/locore_subr.S	2002/05/09 12:28:08	1.10
--- sh3/locore_subr.S	2002/06/21 06:11:19
***************
*** 48,54 ****
  	.text
  	.align 5	/* align cache line size (32B) */
  /*
!  * void cpu_switch(struct proc *):
   *	Find a runnable process and switch to it.  Wait if necessary.
   */
  ENTRY(cpu_switch)
--- 48,54 ----
  	.text
  	.align 5	/* align cache line size (32B) */
  /*
!  * void cpu_switch(struct lwp *):
   *	Find a runnable process and switch to it.  Wait if necessary.
   */
  ENTRY(cpu_switch)
***************
*** 79,84 ****
--- 79,85 ----
  	bt/s	1f
  	 mov	r0,	r4	/* new proc */
  
+ _L.doswitch:
  	/* Setup kernel stack */
  	mov.l	_L.SF,	r0
  	mov.l	@(r0, r4), r1		/* switch frame */
***************
*** 100,107 ****
  	__EXCEPTION_UNBLOCK(r0, r1)
  	/* Now OK to use kernel stack. */
  
  	/* Restore new process's context from switchframe */
! 1:	mov.l	_L.SF,	r0
  	mov.l	@(r0, r4), r1
  	add	#4,	r1		/* r15 already restored */
  	mov.l	@r1+,	r14
--- 101,116 ----
  	__EXCEPTION_UNBLOCK(r0, r1)
  	/* Now OK to use kernel stack. */
  
+ 	/* Return 1 indicating "we switched". */
+ 	bra	2f
+ 	 mov	#1, r2
+ 
+ 1:	/* Return 0 indicating "didn't switch". */
+ 	mov	#0, r2
+ 
  	/* Restore new process's context from switchframe */
! 	/* NOTE: r2 has return value! */
! 2:	mov.l	_L.SF,	r0
  	mov.l	@(r0, r4), r1
  	add	#4,	r1		/* r15 already restored */
  	mov.l	@r1+,	r14
***************
*** 114,126 ****
  	lds.l	@r1+,	pr
  	add	#4,	r1		/* r6_bank already restored */
  	ldc.l	@r1+,	sr
  	rts
! 	 nop
  	.align	2
! _L.SF:			.long	(P_MD + MD_PCB)
  _L.cpu_switch_search:	.long	_C_LABEL(cpu_switch_search)
  FUNC_SYMBOL(switch_resume)
  
  #ifdef SH3
  /*
   * void sh3_switch_resume(sturct proc *p)
--- 123,182 ----
  	lds.l	@r1+,	pr
  	add	#4,	r1		/* r6_bank already restored */
  	ldc.l	@r1+,	sr
+ 
+ 	/* r2 has the return value; stuff it into r0 now. */
  	rts
! 	 mov	r2, r0
  	.align	2
! _L.SF:			.long	(L_MD_PCB)
  _L.cpu_switch_search:	.long	_C_LABEL(cpu_switch_search)
  FUNC_SYMBOL(switch_resume)
  
+ /*
+  * void cpu_preempt(struct lwp *current, struct lwp *next)
+  *	Switch to the specified next LWP.
+  */
+ ENTRY(cpu_preempt)
+ 	/* Save current process's context to switchframe. */
+ 	mov.l	_L.SFp,	r0
+ 	mov.l	@(r0, r4), r1
+ 	add	#SF_SIZE, r1
+ 	stc.l	r7_bank,@-r1
+ 	stc.l	sr,	@-r1
+ 	stc.l	r6_bank,@-r1
+ 	sts.l	pr,	@-r1
+ 	mov.l	r8,	@-r1
+ 	mov.l	r9,	@-r1
+ 	mov.l	r10,	@-r1
+ 	mov.l	r11,	@-r1
+ 	mov.l	r12,	@-r1
+ 	mov.l	r13,	@-r1
+ 	mov.l	r14,	@-r1
+ 	mov.l	r15,	@-r1
+ 
+ 	/*
+ 	 * Don't need the outgoing LWP anymore.  Stash the incoming
+ 	 * LWP into a callee-saved register.
+ 	 */
+ 	mov	r5, r8
+ 
+ 	/* Unlink the new LWP from its run queue. */
+ 	mov.l	_L.remrunqueue, r0
+ 	jsr	@r0
+ 	 mov	r8, r4
+ 
+ 	/*
+ 	 * Put the incoming proc in r4 and jump into the middle
+ 	 * of cpu_switch(), and let it do the work to restore the
+ 	 * incoming LWP's context.
+ 	 */
+ 	bra	_L.doswitch
+ 	 mov	r8, r4
+ 
+ 	.align	2
+ _L.SFp:			.long	(L_MD_PCB)
+ _L.remrunqueue:		.long	_C_LABEL(remrunqueue)
+ 
  #ifdef SH3
  /*
   * void sh3_switch_resume(sturct proc *p)
***************
*** 211,217 ****
  _L.VPN_MASK:		.long	0xfffff000
  _L.P2BASE:		.long	0xa0000000
  #endif /* SH4 */
! _L.UPTE:		.long	(P_MD + MD_UPTE)
  
  /*
   * int _cpu_intr_raise(int s):
--- 267,273 ----
  _L.VPN_MASK:		.long	0xfffff000
  _L.P2BASE:		.long	0xa0000000
  #endif /* SH4 */
! _L.UPTE:		.long	(L_MD_UPTE)
  
  /*
   * int _cpu_intr_raise(int s):
***************
*** 356,361 ****
--- 412,436 ----
  	trapa	#0x80			/* exit if sigreturn fails */
  	.align	2
  _L.SYS___sigreturn14:	.long	SYS___sigreturn14
+ 
+ /*
+  * upcallcode:
+  *	Scheduler activation upcall trampoline.
+  *
+  * r4-r7 are the first 4 upcall arguments.  The rest of the arguments
+  * are on the stack in the right places.  Pointer to the upcall routine
+  * follows args.
+  */
+ NENTRY(upcallcode)
+ 	mov.l	@(SAF_UPCALL,r15), r0	/* fetch upcall routine.. */
+ 	jsr	@r0			/* ..and call it! */
+ 	 nop
+ 
+ 	/* Returned?!  Die! */
+ 	mov.l	_L.SYS_exit, r0
+ 	trapa	#0x80
+ 
+ 	.align	2
  _L.SYS_exit:		.long	SYS_exit
  	.globl	_C_LABEL(esigcode)
  _C_LABEL(esigcode):
Index: sh3/mem.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/mem.c,v
retrieving revision 1.11
diff -c -r1.11 mem.c
*** sh3/mem.c	2002/05/09 12:29:48	1.11
--- sh3/mem.c	2002/06/21 06:11:19
***************
*** 159,165 ****
  paddr_t
  mmmmap(dev_t dev, off_t off, int prot)
  {
! 	struct proc *p = curproc;
  
  	if (minor(dev) != DEV_MEM)
  		return (-1);
--- 159,165 ----
  paddr_t
  mmmmap(dev_t dev, off_t off, int prot)
  {
! 	struct proc *p = curproc->l_proc;
  
  	if (minor(dev) != DEV_MEM)
  		return (-1);
Index: sh3/pmap.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/pmap.c,v
retrieving revision 1.40
diff -c -r1.40 pmap.c
*** sh3/pmap.c	2002/05/09 12:28:08	1.40
--- sh3/pmap.c	2002/06/21 06:11:20
***************
*** 293,301 ****
  }
  
  void
! pmap_activate(struct proc *p)
  {
! 	pmap_t pmap = p->p_vmspace->vm_map.pmap;
  
  	if (pmap->pm_asid == -1)
  		pmap->pm_asid = __pmap_asid_alloc();
--- 293,301 ----
  }
  
  void
! pmap_activate(struct lwp *l)
  {
! 	pmap_t pmap = l->l_proc->p_vmspace->vm_map.pmap;
  
  	if (pmap->pm_asid == -1)
  		pmap->pm_asid = __pmap_asid_alloc();
***************
*** 305,311 ****
  }
  
  void
! pmap_deactivate(struct proc *p)
  {
  
  	/* Nothing to do */
--- 305,311 ----
  }
  
  void
! pmap_deactivate(struct lwp *l)
  {
  
  	/* Nothing to do */
Index: sh3/process_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/process_machdep.c,v
retrieving revision 1.5
diff -c -r1.5 process_machdep.c
*** sh3/process_machdep.c	2002/04/29 09:33:30	1.5
--- sh3/process_machdep.c	2002/06/21 06:11:20
***************
*** 76,94 ****
  #include <machine/psl.h>
  #include <machine/reg.h>
  
- static __inline struct trapframe *process_frame(struct proc *);
- 
  static __inline struct trapframe *
! process_frame(struct proc *p)
  {
  
! 	return (p->p_md.md_regs);
  }
  
  int
! process_read_regs(struct proc *p, struct reg *regs)
  {
! 	struct trapframe *tf = process_frame(p);
  
  	regs->r_spc = tf->tf_spc;
  	regs->r_ssr = tf->tf_ssr;
--- 76,92 ----
  #include <machine/psl.h>
  #include <machine/reg.h>
  
  static __inline struct trapframe *
! process_frame(struct lwp *l)
  {
  
! 	return (l->l_md.md_regs);
  }
  
  int
! process_read_regs(struct lwp *l, struct reg *regs)
  {
! 	struct trapframe *tf = process_frame(l);
  
  	regs->r_spc = tf->tf_spc;
  	regs->r_ssr = tf->tf_ssr;
***************
*** 116,124 ****
  }
  
  int
! process_write_regs(struct proc *p, struct reg *regs)
  {
! 	struct trapframe *tf = process_frame(p);
  
  	/*
  	 * Check for security violations.
--- 114,122 ----
  }
  
  int
! process_write_regs(struct lwp *l, struct reg *regs)
  {
! 	struct trapframe *tf = process_frame(l);
  
  	/*
  	 * Check for security violations.
***************
*** 154,161 ****
  }
  
  int
! process_sstep(p, sstep)
! 	struct proc *p;
  {
  
  	if (sstep)
--- 152,159 ----
  }
  
  int
! process_sstep(l, sstep)
! 	struct lwp *l;
  {
  
  	if (sstep)
***************
*** 165,173 ****
  }
  
  int
! process_set_pc(struct proc *p, caddr_t addr)
  {
! 	struct trapframe *tf = process_frame(p);
  
  	tf->tf_spc = (int)addr;
  
--- 163,171 ----
  }
  
  int
! process_set_pc(struct lwp *l, caddr_t addr)
  {
! 	struct trapframe *tf = process_frame(l);
  
  	tf->tf_spc = (int)addr;
  
Index: sh3/sh3_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/sh3_machdep.c,v
retrieving revision 1.41.6.1
diff -c -r1.41.6.1 sh3_machdep.c
*** sh3/sh3_machdep.c	2002/06/20 23:00:51	1.41.6.1
--- sh3/sh3_machdep.c	2002/06/21 06:11:20
***************
*** 90,95 ****
--- 90,97 ----
  #include <sys/mount.h>
  #include <sys/proc.h>
  #include <sys/signalvar.h>
+ #include <sys/sa.h>
+ #include <sys/savar.h>
  #include <sys/syscallargs.h>
  #include <sys/ucontext.h>
  #include <sys/user.h>
***************
*** 217,223 ****
  
  	/* Setup proc0 */
  	proc0paddr = (struct user *)u;
! 	proc0.p_addr = proc0paddr;
  	/*
  	 * u-area map:
  	 * |user| .... | ............... |
--- 219,225 ----
  
  	/* Setup proc0 */
  	proc0paddr = (struct user *)u;
! 	lwp0.l_addr = proc0paddr;
  	/*
  	 * u-area map:
  	 * |user| .... | ............... |
***************
*** 227,234 ****
  	 * stack top     ... r7_bank
  	 * current stack ... r15
  	 */
! 	curpcb = proc0.p_md.md_pcb = &proc0.p_addr->u_pcb;
! 	curupte = proc0.p_md.md_upte;
  
  	sf = &curpcb->pcb_sf;
  	sf->sf_r6_bank = u + NBPG;
--- 229,236 ----
  	 * stack top     ... r7_bank
  	 * current stack ... r15
  	 */
! 	curpcb = lwp0.l_md.md_pcb = &lwp0.l_addr->u_pcb;
! 	curupte = lwp0.l_md.md_upte;
  
  	sf = &curpcb->pcb_sf;
  	sf->sf_r6_bank = u + NBPG;
***************
*** 236,242 ****
  	__asm__ __volatile__("ldc %0, r6_bank" :: "r"(sf->sf_r6_bank));
  	__asm__ __volatile__("ldc %0, r7_bank" :: "r"(sf->sf_r7_bank));
  
! 	proc0.p_md.md_regs = (struct trapframe *)sf->sf_r6_bank - 1;
  #ifdef KSTACK_DEBUG
  	memset((char *)(u + sizeof(struct user)), 0x5a,
  	    NBPG - sizeof(struct user));
--- 238,244 ----
  	__asm__ __volatile__("ldc %0, r6_bank" :: "r"(sf->sf_r6_bank));
  	__asm__ __volatile__("ldc %0, r7_bank" :: "r"(sf->sf_r7_bank));
  
! 	lwp0.l_md.md_regs = (struct trapframe *)sf->sf_r6_bank - 1;
  #ifdef KSTACK_DEBUG
  	memset((char *)(u + sizeof(struct user)), 0x5a,
  	    NBPG - sizeof(struct user));
***************
*** 363,368 ****
--- 365,414 ----
  }
  
  /*
+  * void cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted,
+  *     void *sas, void *ap, void *sp, sa_upcall_t upcall):
+  *
+  * Send an upcall to userland.
+  */
+ void
+ cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted, void *sas,
+     void *ap, void *sp, sa_upcall_t upcall)
+ {
+ 	struct proc *p = l->l_proc;
+ 	struct trapframe *tf;
+ 	struct saframe *sf, frame;
+ 	extern char sigcode[], upcallcode[];
+ 
+ 	tf = l->l_md.md_regs;
+ 
+ 	/* Build the stack frame. */
+ #if 0 /* First 4 args in regs (see below). */
+ 	frame.sa_type = type;
+ 	frame.sa_sas = sas;
+ 	frame.sa_events = nevents;
+ 	frame.sa_interrupted = ninterrupted;
+ #endif
+ 	frame.sa_arg = ap;
+ 	frame.sa_upcall = upcall;
+ 
+ 	sf = (struct saframe *)sp - 1;
+ 	if (copyout(&frame, sf, sizeof(frame)) != 0) {
+ 		/* Copying onto the stack didn't work.  Die. */
+ 		sigexit(l, SIGILL);
+ 		/* NOTREACHED */
+ 	}
+ 
+ 	tf->tf_r4 = type;
+ 	tf->tf_r5 = (int) sas;
+ 	tf->tf_r6 = nevents;
+ 	tf->tf_r7 = ninterrupted;
+ 
+ 	tf->tf_spc = (int) ((caddr_t)p->p_sigctx.ps_sigcode +
+ 	    ((caddr_t)upcallcode - (caddr_t)sigcode));
+ 	tf->tf_r15 = (int) sf;
+ }
+ 
+ /*
   * Send an interrupt to process.
   *
   * Stack is set up to allow sigcode stored
***************
*** 375,386 ****
  void
  sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
  {
! 	struct proc *p = curproc;
  	struct trapframe *tf;
  	struct sigframe *fp, frame;
  	int onstack;
  
! 	tf = p->p_md.md_regs;
  
  	/* Do we need to jump onto the signal stack? */
  	onstack =
--- 421,433 ----
  void
  sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
  {
! 	struct lwp *l = curproc;
! 	struct proc *p = l->l_proc;
  	struct trapframe *tf;
  	struct sigframe *fp, frame;
  	int onstack;
  
! 	tf = l->l_md.md_regs;
  
  	/* Do we need to jump onto the signal stack? */
  	onstack =
***************
*** 434,440 ****
  		 * Process has trashed its stack; give it an illegal
  		 * instruction to halt it in its tracks.
  		 */
! 		sigexit(p, SIGILL);
  		/* NOTREACHED */
  	}
  
--- 481,487 ----
  		 * Process has trashed its stack; give it an illegal
  		 * instruction to halt it in its tracks.
  		 */
! 		sigexit(l, SIGILL);
  		/* NOTREACHED */
  	}
  
***************
*** 460,472 ****
   * a machine fault.
   */
  int
! sys___sigreturn14(struct proc *p, void *v, register_t *retval)
  {
  	struct sys___sigreturn14_args /* {
  		syscallarg(struct sigcontext *) sigcntxp;
  	} */ *uap = v;
  	struct sigcontext *scp, context;
  	struct trapframe *tf;
  
  	/*
  	 * The trampoline code hands us the context.
--- 507,520 ----
   * a machine fault.
   */
  int
! sys___sigreturn14(struct lwp *l, void *v, register_t *retval)
  {
  	struct sys___sigreturn14_args /* {
  		syscallarg(struct sigcontext *) sigcntxp;
  	} */ *uap = v;
  	struct sigcontext *scp, context;
  	struct trapframe *tf;
+ 	struct proc *p = l->l_proc;
  
  	/*
  	 * The trampoline code hands us the context.
***************
*** 478,484 ****
  		return (EFAULT);
  
  	/* Restore signal context. */
! 	tf = p->p_md.md_regs;
  
  	/* Check for security violations. */
  	if (((context.sc_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0)
--- 526,532 ----
  		return (EFAULT);
  
  	/* Restore signal context. */
! 	tf = l->l_md.md_regs;
  
  	/* Check for security violations. */
  	if (((context.sc_ssr ^ tf->tf_ssr) & PSL_USERSTATIC) != 0)
***************
*** 517,532 ****
  }
  
  void
! cpu_getmcontext(p, mcp, flags)
! 	struct proc *p;
  	mcontext_t *mcp;
  	unsigned int *flags;
  {
! 	const struct trapframe *tf = p->p_md.md_regs;
  	__greg_t *gr = mcp->__gregs;
  
  	/* Save register context. */
! 	gr[_REG_EXPEVT] = tf->tf_trapno;
  	gr[_REG_PC]     = tf->tf_spc;
  	gr[_REG_SR]     = tf->tf_ssr;
  	gr[_REG_MACL]   = tf->tf_macl;
--- 565,580 ----
  }
  
  void
! cpu_getmcontext(l, mcp, flags)
! 	struct lwp *l;
  	mcontext_t *mcp;
  	unsigned int *flags;
  {
! 	const struct trapframe *tf = l->l_md.md_regs;
  	__greg_t *gr = mcp->__gregs;
  
  	/* Save register context. */
! 	gr[_REG_EXPEVT] = tf->tf_expevt;
  	gr[_REG_PC]     = tf->tf_spc;
  	gr[_REG_SR]     = tf->tf_ssr;
  	gr[_REG_MACL]   = tf->tf_macl;
***************
*** 555,566 ****
  }
  
  int
! cpu_setmcontext(p, mcp, flags)
! 	struct proc *p;
  	const mcontext_t *mcp;
  	unsigned int flags;
  {
! 	struct trapframe *tf = p->p_md.md_regs;
  	const __greg_t *gr = mcp->__gregs;
  
  	/* Restore register context, if any. */
--- 603,614 ----
  }
  
  int
! cpu_setmcontext(l, mcp, flags)
! 	struct lwp *l;
  	const mcontext_t *mcp;
  	unsigned int flags;
  {
! 	struct trapframe *tf = l->l_md.md_regs;
  	const __greg_t *gr = mcp->__gregs;
  
  	/* Restore register context, if any. */
***************
*** 600,612 ****
   * Clear registers on exec
   */
  void
! setregs(struct proc *p, struct exec_package *pack, u_long stack)
  {
  	struct trapframe *tf;
  
! 	p->p_md.md_flags &= ~MDP_USEDFPU;
  
! 	tf = p->p_md.md_regs;
  
  	tf->tf_r0 = 0;
  	tf->tf_r1 = 0;
--- 648,660 ----
   * Clear registers on exec
   */
  void
! setregs(struct lwp *l, struct exec_package *pack, u_long stack)
  {
  	struct trapframe *tf;
  
! 	l->l_md.md_flags &= ~MDP_USEDFPU;
  
! 	tf = l->l_md.md_regs;
  
  	tf->tf_r0 = 0;
  	tf->tf_r1 = 0;
***************
*** 617,623 ****
  	tf->tf_r6 = stack + 4 * tf->tf_r4 + 8;	/* envp */
  	tf->tf_r7 = 0;
  	tf->tf_r8 = 0;
! 	tf->tf_r9 = (int)p->p_psstr;
  	tf->tf_r10 = 0;
  	tf->tf_r11 = 0;
  	tf->tf_r12 = 0;
--- 665,671 ----
  	tf->tf_r6 = stack + 4 * tf->tf_r4 + 8;	/* envp */
  	tf->tf_r7 = 0;
  	tf->tf_r8 = 0;
! 	tf->tf_r9 = (int)l->l_proc->p_psstr;
  	tf->tf_r10 = 0;
  	tf->tf_r11 = 0;
  	tf->tf_r12 = 0;
Index: sh3/sys_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/sys_machdep.c,v
retrieving revision 1.7
diff -c -r1.7 sys_machdep.c
*** sh3/sys_machdep.c	2002/05/10 15:28:45	1.7
--- sh3/sys_machdep.c	2002/06/21 06:11:20
***************
*** 43,52 ****
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/mount.h>
  #include <sys/syscallargs.h>
  
  int
! sys_sysarch(struct proc *p, void *v, register_t *retval)
  {
  	struct sys_sysarch_args __attribute__((__unused__)) *uap = v;
  
--- 43,53 ----
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/mount.h>
+ #include <sys/sa.h>
  #include <sys/syscallargs.h>
  
  int
! sys_sysarch(struct lwp *l, void *v, register_t *retval)
  {
  	struct sys_sysarch_args __attribute__((__unused__)) *uap = v;
  
Index: sh3/vm_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/sh3/vm_machdep.c,v
retrieving revision 1.33
diff -c -r1.33 vm_machdep.c
*** sh3/vm_machdep.c	2002/05/09 12:28:09	1.33
--- sh3/vm_machdep.c	2002/06/21 06:11:21
***************
*** 67,72 ****
--- 67,74 ----
  #include <sh3/mmu.h>
  #include <sh3/cache.h>
  
+ extern void proc_trampoline(void);
+ 
  /*
   * Finish a fork operation, with process p2 nearly set up.
   * Copy and update the pcb and trap frame, making the child ready to run.
***************
*** 86,105 ****
   * accordingly.
   */
  void
! cpu_fork(struct proc *p1, struct proc *p2, void *stack,
      size_t stacksize, void (*func)(void *), void *arg)
  {
- 	extern void proc_trampoline(void);
  	struct pcb *pcb;
  	struct trapframe *tf;
  	struct switchframe *sf;
  	vaddr_t spbase, fptop;
  #define	P1ADDR(x)	(SH3_PHYS_TO_P1SEG(*__pmap_kpte_lookup(x) & PG_PPN))
  
! 	KDASSERT(!(p1 != curproc && p1 != &proc0));
  
  	/* Copy flags */
! 	p2->p_md.md_flags = p1->p_md.md_flags;
  
  #ifdef SH3
  	/*
--- 88,106 ----
   * accordingly.
   */
  void
! cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack,
      size_t stacksize, void (*func)(void *), void *arg)
  {
  	struct pcb *pcb;
  	struct trapframe *tf;
  	struct switchframe *sf;
  	vaddr_t spbase, fptop;
  #define	P1ADDR(x)	(SH3_PHYS_TO_P1SEG(*__pmap_kpte_lookup(x) & PG_PPN))
  
! 	KDASSERT(!(l1 != curproc && l1 != &lwp0));
  
  	/* Copy flags */
! 	l2->l_md.md_flags = l1->l_md.md_flags;
  
  #ifdef SH3
  	/*
***************
*** 109,130 ****
  	 * cause virtual-aliasing.
  	 */
  	if (CPU_IS_SH3) {
! 		pcb = (struct pcb *)P1ADDR((vaddr_t)&p2->p_addr->u_pcb);
! 		p2->p_md.md_pcb = pcb;
  		fptop = (vaddr_t)pcb + NBPG;
  	}
  #endif /* SH3 */
  #ifdef SH4
  	/* SH4 can make wired entry, no need to convert to P1. */
  	if (CPU_IS_SH4) {
! 		pcb = &p2->p_addr->u_pcb;
! 		p2->p_md.md_pcb = pcb;
  		fptop = (vaddr_t)pcb + NBPG;
  	}
  #endif /* SH4 */
  
  	/* set up the kernel stack pointer */
! 	spbase = (vaddr_t)p2->p_addr + NBPG;
  #ifdef P1_STACK
  	/* Convert to P1 from P3 */
  	/*
--- 110,131 ----
  	 * cause virtual-aliasing.
  	 */
  	if (CPU_IS_SH3) {
! 		pcb = (struct pcb *)P1ADDR((vaddr_t)&l2->l_addr->u_pcb);
! 		l2->l_md.md_pcb = pcb;
  		fptop = (vaddr_t)pcb + NBPG;
  	}
  #endif /* SH3 */
  #ifdef SH4
  	/* SH4 can make wired entry, no need to convert to P1. */
  	if (CPU_IS_SH4) {
! 		pcb = &l2->l_addr->u_pcb;
! 		l2->l_md.md_pcb = pcb;
  		fptop = (vaddr_t)pcb + NBPG;
  	}
  #endif /* SH4 */
  
  	/* set up the kernel stack pointer */
! 	spbase = (vaddr_t)l2->l_addr + NBPG;
  #ifdef P1_STACK
  	/* Convert to P1 from P3 */
  	/*
***************
*** 132,148 ****
  	 * is accessed from P1 instead of P3.
  	 */
  	if (SH_HAS_VIRTUAL_ALIAS)
! 		sh_dcache_wbinv_range((vaddr_t)p2->p_addr, USPACE);
  	spbase = P1ADDR(spbase);
  #else /* P1_STACK */
  	/* Prepare u-area PTEs */
  #ifdef SH3
  	if (CPU_IS_SH3)
! 		sh3_switch_setup(p2);
  #endif
  #ifdef SH4
  	if (CPU_IS_SH4)
! 		sh4_switch_setup(p2);
  #endif
  #endif /* P1_STACK */
  
--- 133,149 ----
  	 * is accessed from P1 instead of P3.
  	 */
  	if (SH_HAS_VIRTUAL_ALIAS)
! 		sh_dcache_wbinv_range((vaddr_t)l2->l_addr, USPACE);
  	spbase = P1ADDR(spbase);
  #else /* P1_STACK */
  	/* Prepare u-area PTEs */
  #ifdef SH3
  	if (CPU_IS_SH3)
! 		sh3_switch_setup(l2);
  #endif
  #ifdef SH4
  	if (CPU_IS_SH4)
! 		sh4_switch_setup(l2);
  #endif
  #endif /* P1_STACK */
  
***************
*** 157,164 ****
  	/*
  	 * Copy the user context.
  	 */
! 	p2->p_md.md_regs = tf = (struct trapframe *)fptop - 1;
! 	memcpy(tf, p1->p_md.md_regs, sizeof(struct trapframe));
  
  	/*
  	 * If specified, give the child a different stack.
--- 158,165 ----
  	/*
  	 * Copy the user context.
  	 */
! 	l2->l_md.md_regs = tf = (struct trapframe *)fptop - 1;
! 	memcpy(tf, l1->l_md.md_regs, sizeof(struct trapframe));
  
  	/*
  	 * If specified, give the child a different stack.
***************
*** 182,204 ****
  	sf->sf_sr = PSL_MD;		/* kernel mode, interrupt enable */
  }
  
  /*
!  * void cpu_exit(sturct proc *p):
!  *	+ Change kernel context to proc0's one.
!  *	+ Schedule freeing process 'p' resources.
   *	+ switch to another process.
   */
  void
! cpu_exit(struct proc *p)
  {
  	struct switchframe *sf;
  
  	splsched();
  	uvmexp.swtch++;
  
! 	/* Switch to proc0 stack */
  	curproc = 0;
! 	curpcb = proc0.p_md.md_pcb;
  	sf = &curpcb->pcb_sf;
  	__asm__ __volatile__(
  		"mov	%0, r15;"	/* current stack */
--- 183,272 ----
  	sf->sf_sr = PSL_MD;		/* kernel mode, interrupt enable */
  }
  
+ /*
+  * void cpu_setfunc(struct lwp *l, void (*func)(void *), void *arg):
+  *	+ Reset the stack pointer for the process.
+  *	+ Arrange to the process to call the specified func
+  *	  with argument via the proc_trampoline.
+  *
+  *	XXX There is a lot of duplicated code here (with cpu_lwp_fork()).
+  */
+ void
+ cpu_setfunc(struct lwp *l, void (*func)(void *), void *arg)
+ {
+ 	struct pcb *pcb;
+ 	struct trapframe *tf;
+ 	struct switchframe *sf;
+ 	vaddr_t spbase;
+ 
+ #ifdef SH3
+ 	/*
+ 	 * Convert frame pointer top to P1. because SH3 can't make
+ 	 * wired TLB entry, context store space accessing must not cause
+ 	 * exception. For SH3, we are 4K page, P3/P1 conversion don't
+ 	 * cause virtual-aliasing.
+ 	 */
+ 	if (CPU_IS_SH3) {
+ 		pcb = (struct pcb *)P1ADDR((vaddr_t)&l->l_addr->u_pcb);
+ 	}
+ #endif /* SH3 */
+ #ifdef SH4
+ 	/* SH4 can make wired entry, no need to convert to P1. */
+ 	if (CPU_IS_SH4) {
+ 		pcb = &l->l_addr->u_pcb;
+ 	}
+ #endif /* SH4 */
+ 
+ 	/* set up the kernel stack pointer */
+ 	spbase = (vaddr_t)l->l_addr + NBPG;
+ #ifdef P1_STACK
+ 	/* Convert to P1 from P3 */
+ 	/*
+ 	 * wbinv u-area to avoid cache-aliasing, since kernel stack
+ 	 * is accessed from P1 instead of P3.
+ 	 *
+ 	 * XXX Is this needed here?
+ 	 */
+ 	if (SH_HAS_VIRTUAL_ALIAS)
+ 		sh_dcache_wbinv_range((vaddr_t)l2->l_addr, USPACE);
+ 	spbase = P1ADDR(spbase);
+ #else /* P1_STACK */
+ 	/* Don't need to set up u-area PTEs again. */
+ #endif /* P1_STACK */
+ 
+ 	/* Setup switch frame */
+ 	sf = &pcb->pcb_sf;
+ 	sf->sf_r11 = (int)arg;		/* proc_trampoline hook func */
+ 	sf->sf_r12 = (int)func;		/* proc_trampoline hook func's arg */
+ 	sf->sf_r15 = spbase + USPACE - NBPG;	/* current stack pointer */
+ 	sf->sf_r7_bank = sf->sf_r15;	/* stack top */
+ 	sf->sf_r6_bank = (vaddr_t)tf;	/* current frame pointer */
+ 	/* when switch to me, jump to proc_trampoline */
+ 	sf->sf_pr  = (int)proc_trampoline;
+ 	/*
+ 	 * Enable interrupt when switch frame is restored, since
+ 	 * kernel thread begin to run without restoring trapframe.
+ 	 */
+ 	sf->sf_sr = PSL_MD;		/* kernel mode, interrupt enable */
+ }
+ 
  /*
!  * void cpu_exit(struct lwp *l):
!  *	+ Change kernel context to lwp0's one.
!  *	+ Schedule freeing process 'l' resources.
   *	+ switch to another process.
   */
  void
! cpu_exit(struct lwp *l, int proc)
  {
  	struct switchframe *sf;
  
  	splsched();
  	uvmexp.swtch++;
  
! 	/* Switch to lwp0 stack */
  	curproc = 0;
! 	curpcb = lwp0.l_md.md_pcb;
  	sf = &curpcb->pcb_sf;
  	__asm__ __volatile__(
  		"mov	%0, r15;"	/* current stack */
***************
*** 210,218 ****
  		"r"(sf->sf_r7_bank));
  
  	/* Schedule freeing process resources */
! 	exit2(p);
  
! 	cpu_switch(p);
  	/* NOTREACHED */
  }
  
--- 278,289 ----
  		"r"(sf->sf_r7_bank));
  
  	/* Schedule freeing process resources */
! 	if (proc)
! 		exit2(l);
! 	else
! 		lwp_exit2(l);
  
! 	cpu_switch(l);
  	/* NOTREACHED */
  }
  
***************
*** 224,230 ****
  };
  
  int
! cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
      struct core *chdr)
  {
  	struct md_core md_core;
--- 295,301 ----
  };
  
  int
! cpu_coredump(struct lwp *l, struct vnode *vp, struct ucred *cred,
      struct core *chdr)
  {
  	struct md_core md_core;
***************
*** 237,243 ****
  	chdr->c_cpusize = sizeof(md_core);
  
  	/* Save integer registers. */
! 	error = process_read_regs(p, &md_core.intreg);
  	if (error)
  		return error;
  
--- 308,314 ----
  	chdr->c_cpusize = sizeof(md_core);
  
  	/* Save integer registers. */
! 	error = process_read_regs(l, &md_core.intreg);
  	if (error)
  		return error;
  
***************
*** 248,260 ****
  
  	error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
  	    (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
! 	    (int *)0, p);
  	if (error)
  		return error;
  
  	error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
  	    (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
! 	    IO_NODELOCKED|IO_UNIT, cred, (int *)0, p);
  	if (error)
  		return error;
  
--- 319,331 ----
  
  	error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
  	    (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
! 	    (int *)0, l->l_proc);
  	if (error)
  		return error;
  
  	error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
  	    (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
! 	    IO_NODELOCKED|IO_UNIT, cred, (int *)0, l->l_proc);
  	if (error)
  		return error;
  

--DocE+STaALJfprDB--