Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 Apr 2003 13:56:05 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 29537 for review
Message-ID:  <200304232056.h3NKu5VU060332@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=29537

Change 29537 by marcel@marcel_nfs on 2003/04/23 13:55:54

	Get signal delivery working for the "legacy" syscalls. This brings
	us back online with a world from HEAD and an EPC based kernel.
	Note that since we have a gateway page, we don't have to copy signal
	trampoline code onto the stack when we exec. We have the trampoline
	code in the gateway page now. Not only does this remove the pressure
	on the size of the trampoline code, it also means we can stop using
	executable stacks.
	
	Some additional work needs to be done to handle the less common
	cases. This is delayed until the signal delivery for EPC syscalls
	has been implemented. Both syscall paths will share a lot of code
	WRT signal delivery, so it's better to have the rudimentary support
	for the EPC syscalls in place before working on the hairy details.
	Things that need to be done are:
	o  Save the preserved registers so that we can safely sigreturn
	   from anywhere the process pleases, rather than by returning
	   from the signal handler. Restoring the preserved registers can
	   be tricky as it involves unwinding.
	o  Make sure the kernel backing store doesn't have more than 0x200
	   bytes worth of dirty registers (including NaT collections).
	   We need to be able to return to the original stack, which means
	   that we need to be able to discard the current register stack.
	   This mimics the problem of exec'ing. See also exec_setregs().

Affected files ...

.. //depot/projects/ia64_epc/sys/ia64/ia64/elf_machdep.c#4 edit
.. //depot/projects/ia64_epc/sys/ia64/ia64/locore.s#15 edit
.. //depot/projects/ia64_epc/sys/ia64/ia64/machdep.c#17 edit
.. //depot/projects/ia64_epc/sys/ia64/ia64/syscall.s#10 edit

Differences ...

==== //depot/projects/ia64_epc/sys/ia64/ia64/elf_machdep.c#4 (text+ko) ====

@@ -59,8 +59,8 @@
 	NULL,
 	__elfN(freebsd_fixup),
 	sendsig,
-	sigcode,
-	&szsigcode,
+	NULL,		/* sigcode */
+	NULL,		/* &szsigcode */
 	NULL,
 	"FreeBSD ELF64",
 	__elfN(coredump),

==== //depot/projects/ia64_epc/sys/ia64/ia64/locore.s#15 (text+ko) ====

@@ -295,84 +295,6 @@
 
 #endif /* !SMP */
 
-/**************************************************************************/
-
-/*
- * Signal "trampoline" code. Invoked from RTE setup by sendsig().
- *
- * On entry, registers look like:
- *
- *      r14	signal number
- *      r15	pointer to siginfo_t
- *	r16	pointer to signal context frame (scp)
- *      r17	address of handler function descriptor
- *	r18	address of new backing store (if any)
- *      sp+16	pointer to sigframe
- */
-
-ENTRY(sigcode,0)
-	ld8	r8=[r17],8		// function address
-	;;
-	ld8	gp=[r17]		// function's gp value
-	mov	b6=r8			// transfer to a branch register
-	cover
-	;;
-	add	r8=UC_MCONTEXT+MC_SPECIAL_BSPSTORE,r16 // address or mc_ar_bsp
-	mov	r9=ar.bsp		// save ar.bsp
-	;;
-	st8	[r8]=r9
-	cmp.eq	p1,p2=r0,r18		// check for new bs
-(p1)	br.cond.sptk.few 1f		// branch if not switching
-	flushrs				// flush out to old bs
-	mov	ar.rsc=0		// switch off RSE
-	add	r8=UC_MCONTEXT+MC_SPECIAL_RNAT,r16 // address of mc_ar_rnat
-	;;
-	mov	r9=ar.rnat		// value of ar.rnat after flush
-	mov	ar.bspstore=r18		// point at new bs
-	;;
-	st8	[r8]=r9			// remember ar.rnat
-	mov	ar.rsc=15		// XXX bogus value - check
-	invala
-	;; 
-1:	alloc	r5=ar.pfs,0,0,3,0	// register frame for call
-	;;
-	mov	out0=r14		// signal number
-	mov	out1=r15		// siginfo
-	mov	out2=r16		// ucontext
-	mov	r4=r16			// save from call
-	br.call.sptk.few rp=b6		// call the signal handler
-	;; 
-	alloc	r14=ar.pfs,0,0,0,0	// discard call frame
-	;; 
-	flushrs
-	;; 
-(p1)	br.cond.sptk.few 2f		// note: p1 is preserved
-	mov	ar.rsc=0
-	add	r8=UC_MCONTEXT+MC_SPECIAL_RNAT,r4 // address of mc_ar_rnat
-	;;
-	ld8	r9=[r8]
-	;; 
-	add	r8=UC_MCONTEXT+MC_SPECIAL_BSPSTORE,r4 // address of mc_ar_bsp
-	;;
-	ld8	r10=[r8]
-	;;
-	mov	ar.bspstore=r10
-	;;
-	mov	ar.rnat=r9
-	mov	ar.rsc=15
-	;; 
-2:	CALLSYS_NOERROR(sigreturn)	// call sigreturn()
-	alloc	r14=ar.pfs,0,0,1,0 ;;
-	mov	out0=ret0		// if that failed, get error code
-	CALLSYS_NOERROR(exit)		// and call exit() with it.
-XENTRY(esigcode)
-	END(sigcode)
-
-	.data
-	EXPORT(szsigcode)
-	.quad	esigcode-sigcode
-	.text
-
 /*
  * Create a default interrupt name table. The first entry (vector 0) is
  * hardwaired to the clock interrupt.

==== //depot/projects/ia64_epc/sys/ia64/ia64/machdep.c#17 (text+ko) ====

@@ -106,6 +106,8 @@
 extern u_int64_t kernel_text[], _end[];
 
 extern u_int64_t ia64_gateway_page[];
+extern u_int64_t break_sigtramp[];
+extern u_int64_t epc_sigtramp[];
 
 FPSWA_INTERFACE *fpswa_interface;
 
@@ -808,35 +810,28 @@
 }
 
 /*
- * Send an interrupt to process.
- *
- * Stack is set up to allow sigcode stored
- * at top to call routine, followed by kcall
- * to sigreturn routine below.  After sigreturn
- * resets the signal mask, the stack, and the
- * frame pointer, it returns to the user
- * specified pc, psl.
+ * Send an interrupt (signal) to a process.
  */
 void
 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
 {
 	struct proc *p;
 	struct thread *td;
-	struct trapframe *frame;
+	struct trapframe *tf;
 	struct sigacts *psp;
 	struct sigframe sf, *sfp;
 	mcontext_t *mc;
-	u_int64_t sbs = 0, sp;
-	int oonstack, rndfsize;
+	u_int64_t sbs, sp;
+	int oonstack;
 
 	td = curthread;
 	p = td->td_proc;
 	PROC_LOCK_ASSERT(p, MA_OWNED);
 	psp = p->p_sigacts;
-	frame = td->td_frame;
-	sp = frame->tf_special.sp;
+	tf = td->td_frame;
+	sp = tf->tf_special.sp;
 	oonstack = sigonstack(sp);
-	rndfsize = ((sizeof(sf) + 15) / 16) * 16;
+	sbs = 0;
 
 	/* save user context */
 	bzero(&sf, sizeof(struct sigframe));
@@ -845,27 +840,7 @@
 	sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
 	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
 
-	mc = &sf.sf_uc.uc_mcontext;
-	mc->mc_special = frame->tf_special;
-	if ((frame->tf_flags & FRAME_SYSCALL) == 0) {
-		mc->mc_flags |= IA64_MC_FLAGS_SCRATCH_VALID;
-		mc->mc_scratch = frame->tf_scratch;
-		mc->mc_scratch_fp = frame->tf_scratch_fp;
-		/*
-		 * XXX High FP. If the process has never used the high FP,
-		 * mark the high FP as valid (zero defaults). If the process
-		 * did use the high FP, then store them in the PCB if not
-		 * already there (ie get them from the CPU that has them)
-		 * and write them in the context.
-		 */
-	}
-
 	/*
-	 * XXX preserved registers. We don't have the preserved registers
-	 * in the trapframe. We don't worry about it now.
-	 */
-
-	/*
 	 * Allocate and validate space for the signal handler
 	 * context. Note that if the stack is in P0 space, the
 	 * call to grow() is a nop, and the useracc() check
@@ -874,32 +849,43 @@
 	 */
 	if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
 	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
-		sbs = (u_int64_t) p->p_sigstk.ss_sp;
-		sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp +
-		    p->p_sigstk.ss_size - rndfsize);
-		/* Align sp and bsp. */
+		sbs = (u_int64_t)p->p_sigstk.ss_sp;
 		sbs = (sbs + 15) & ~15;
-		sfp = (struct sigframe *)((u_int64_t)sfp & ~15);
+		sfp = (struct sigframe *)(sbs + p->p_sigstk.ss_size);
 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 		p->p_sigstk.ss_flags |= SS_ONSTACK;
 #endif
 	} else
-		sfp = (struct sigframe *)(sp - rndfsize);
+		sfp = (struct sigframe *)sp;
+	sfp = (struct sigframe *)((u_int64_t)(sfp - 1) & ~15);
+
+	/* Fill in the siginfo structure for POSIX handlers. */
+	if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+		sf.sf_si.si_signo = sig;
+		sf.sf_si.si_code = code;
+		sf.sf_si.si_addr = (void*)tf->tf_special.ifa;
+		code = (u_int64_t)&sfp->sf_si;
+	}
+
 	PROC_UNLOCK(p);
 
-#ifdef DEBUG
-	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
-		printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
-		    sig, &sf, sfp);
-#endif
+	mc = &sf.sf_uc.uc_mcontext;
+	mc->mc_special = tf->tf_special;
+	mc->mc_scratch = tf->tf_scratch;
+	if ((tf->tf_flags & FRAME_SYSCALL) == 0) {
+		mc->mc_flags |= IA64_MC_FLAGS_SCRATCH_VALID;
+		mc->mc_scratch_fp = tf->tf_scratch_fp;
+		/*
+		 * XXX High FP. If the process has never used the high FP,
+		 * mark the high FP as valid (zero defaults). If the process
+		 * did use the high FP, then store them in the PCB if not
+		 * already there (ie get them from the CPU that has them)
+		 * and write them in the context.
+		 */
+	}
 
 	/* Copy the frame out to userland. */
-	if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) {
-#ifdef DEBUG
-		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
-			printf("sendsig(%d): copyout failed on sig %d\n",
-			    p->p_pid, sig);
-#endif
+	if (copyout(&sf, sfp, sizeof(sf)) != 0) {
 		/*
 		 * Process has trashed its stack; give it an illegal
 		 * instruction to halt it in its tracks.
@@ -908,41 +894,31 @@
 		sigexit(td, SIGILL);
 		return;
 	}
-#ifdef DEBUG
-	if (sigdebug & SDB_FOLLOW)
-		printf("sendsig(%d): sig %d sfp %p code %lx\n", p->p_pid, sig,
-		    sfp, code);
-#endif
 
-	/* Set up the registers to return to sigcode. */
-	frame->tf_special.psr &= ~IA64_PSR_RI;
-	frame->tf_special.iip = PS_STRINGS - (esigcode - sigcode);
-	frame->tf_special.gp = sig;
-	PROC_LOCK(p);
-	if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
-		frame->tf_scratch.gr15 = (u_int64_t)&(sfp->sf_si);
-
-		/* Fill in POSIX parts */
-		sf.sf_si.si_signo = sig;
-		sf.sf_si.si_code = code;
-		sf.sf_si.si_addr = (void*)frame->tf_special.ifa;
+	if ((tf->tf_flags & FRAME_SYSCALL) == 0) {
+		tf->tf_special.psr &= ~IA64_PSR_RI;
+		tf->tf_special.iip = ia64_get_k5() +
+		    ((uint64_t)break_sigtramp - (uint64_t)ia64_gateway_page);
 	} else
-		frame->tf_scratch.gr15 = code;
+		tf->tf_special.rp = ia64_get_k5() +
+		    ((uint64_t)epc_sigtramp - (uint64_t)ia64_gateway_page);
 
-	frame->tf_special.sp = (u_int64_t)sfp - 16;
-	frame->tf_scratch.gr14 = sig;
-	frame->tf_scratch.gr16 = (u_int64_t) &sfp->sf_uc;
-	frame->tf_scratch.gr17 = (u_int64_t)catcher;
-	frame->tf_scratch.gr18 = sbs;
+	/*
+	 * Setup the trapframe to return to the signal trampoline. We pass
+	 * information to the trampoline in the following registers:
+	 *
+	 *	gp	new backing store or NULL
+	 *	r8	signal number
+	 *	r9	signal code or siginfo pointer
+	 *	r10	signal handler (function descriptor)
+	 */
+	tf->tf_special.sp = (u_int64_t)sfp - 16;
+	tf->tf_special.gp = sbs;
+	tf->tf_scratch.gr8 = sig;
+	tf->tf_scratch.gr9 = code;
+	tf->tf_scratch.gr10 = (u_int64_t)catcher;
 
-#ifdef DEBUG
-	if (sigdebug & SDB_FOLLOW)
-		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
-		    frame->tf_cr_iip, frame->tf_scratch.gr17);
-	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
-		printf("sendsig(%d): sig %d returns\n",
-		    p->p_pid, sig);
-#endif
+	PROC_LOCK(p);
 }
 
 /*
@@ -963,23 +939,15 @@
 	} */ *uap)
 {
 	ucontext_t uc;
-	struct trapframe *frame;
+	struct trapframe *tf;
 	struct __mcontext *mc;
 	struct proc *p;
 	struct pcb *pcb;
 
-	frame = td->td_frame;
+	tf = td->td_frame;
 	p = td->td_proc;
 	pcb = td->td_pcb;
 
-#ifdef DEBUG
-	if (sigdebug & SDB_FOLLOW)
-	    printf("sigreturn: pid %d, scp %p\n", p->p_pid, uap->sigcntxp);
-#endif
-
-	/* Throw away the high FP registers. */
-	ia64_highfp_drop(td);
-
 	/*
 	 * Fetch the entire context structure at once for speed.
 	 * We don't use a normal argument to simplify RSE handling.
@@ -988,37 +956,35 @@
 		return (EFAULT);
 
 	/*
+	 * XXX make sure ndirty in the current trapframe is less than
+	 * 0x1f8 so that if we throw away the current register stack,
+	 * we have reached the bottom of the kernel register stack.
+	 * See also exec_setregs.
+	 */
+
+	/*
 	 * Restore the user-supplied information
 	 */
 	mc = &uc.uc_mcontext;
-	frame->tf_special = mc->mc_special;
+	tf->tf_special = mc->mc_special;
+	tf->tf_scratch = mc->mc_scratch;
 	if ((mc->mc_flags & IA64_MC_FLAGS_SCRATCH_VALID) != 0) {
-		frame->tf_scratch = mc->mc_scratch;
-		frame->tf_scratch_fp = mc->mc_scratch_fp;
+		tf->tf_scratch_fp = mc->mc_scratch_fp;
+		/* XXX high FP. */
 	}
 
-	/*
-	 * XXX preserved registers.
-	 * XXX High FP.
-	 */
-
 	PROC_LOCK(p);
 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
-	if (sigonstack(frame->tf_special.sp))
+	if (sigonstack(tf->tf_special.sp))
 		p->p_sigstk.ss_flags |= SS_ONSTACK;
 	else
 		p->p_sigstk.ss_flags &= ~SS_ONSTACK;
 #endif
-
 	td->td_sigmask = uc.uc_sigmask;
 	SIG_CANTMASK(td->td_sigmask);
 	signotify(td);
 	PROC_UNLOCK(p);
 
-#ifdef DEBUG
-	if (sigdebug & SDB_FOLLOW)
-		printf("sigreturn(%d): returns\n", p->p_pid);
-#endif
 	return (EJUSTRETURN);
 }
 

==== //depot/projects/ia64_epc/sys/ia64/ia64/syscall.s#10 (text+ko) ====

@@ -26,6 +26,7 @@
  * $FreeBSD$
  */
 
+#include <sys/syscall.h>
 #include <machine/asm.h>
 #include <assym.s>
 
@@ -92,14 +93,80 @@
 	;;
 }
 
+ENTRY(break_sigtramp, 0)
+{	.mib
+	mov		ar.rsc=0
+	cmp.ne		p15,p0=0,gp
+	cover
+	;;
+}
+{	.mmi
+	flushrs
+(p15)	invala
+	add		r16=16+UC_MCONTEXT+MC_SPECIAL,sp
+	;;
+}
+{	.mmi
+	mov		r17=ar.bsp
+	mov		r18=ar.rnat
+	add		r14=40,r16
+	;;
+}
+{	.mmi
+	st8		[r14]=r17,64		// bspstore
+(p15)	mov		ar.bspstore=gp
+	add		r15=48,r16
+	;;
+}
+{	.mmi
+	st8		[r15]=r18		// rnat
+	st8		[r14]=r0		// ndirty
+	nop		0
+	;;
+}
+{	.mmi
+	alloc		r14=ar.pfs, 0, 0, 3, 0
+	mov		ar.rsc=15
+	mov		out0=r8
+	;;
+}
+{	.mmi
+	ld8		r16=[r10],8		// function address
+	;;
+	ld8		gp=[r10]		// function's gp value
+	mov		b7=r16
+	;;
+}
+{	.mib
+	mov		out1=r9
+	add		out2=16,sp
+	br.call.sptk	rp=b7
+	;;
+}
+{	.mmi
+	mov		r15=SYS_sigreturn
+	add		out0=16,sp
+	break		0x100000
+	;;
+}
+{	.mmi
+	mov		r15=SYS_exit
+	mov		out0=ret0
+	break		0x100000
+	;;
+}
+END(break_sigtramp)
+
+ENTRY(epc_sigtramp, 0)
+	break		0x80100
+	;;
+END(epc_sigtramp)
+
 	.align		PAGE_SIZE
 
+	.section	.text.syscall, "ax"
 
-	.section	.text.syscall, "ax"
-	.global		epc_syscall
-	.proc		epc_syscall
-	.regstk		8,0,0,0
-epc_syscall:
+ENTRY(epc_syscall, 8)
 {	.mmi
 	mov		r16=ar.rsc
 	mov		ar.rsc=0
@@ -358,4 +425,4 @@
 	br.ret.sptk	b7
 	;;
 }
-	.endp		epc_syscall
+END(epc_syscall)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200304232056.h3NKu5VU060332>