PERFORCE change 30572 for review

Marcel Moolenaar marcel at FreeBSD.org
Sun May 4 21:57:12 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=30572

Change 30572 by marcel at marcel_nfs on 2003/05/04 21:56:31

	Implement syscall restarts for EPC syscalls. This almost
	fell through the cracks. Since we store both the syscall
	number and syscall arguments in the trapframe for both
	the EPC sycalls and the break syscalls, we don't have to
	pass these seperately. This means that we don't have to
	save anything special for syscall restarts. We only need
	the frame pointer.
	We use the "raw" error code to determine if we need to
	restart. The raw error code is the register that signals
	to userland if the syscall resulted in an error and used
	to be 0 (=no error) or 1 (error in retval[0]). This has
	been replaced by the untranslated error code. The raw
	error code is returned by both syscall() and do_ast() as
	a favor to callers.
	Interrupted syscalls will never have ERESTART returned
	by do_ast() for two reasons: 1) we initialize the raw
	error code with EJUSTRETURN prior to executing the syscall,
	and 2) when delivering a signal, the raw error code is
	used to pass the signal handler address to the trampoline
	code. This can never cause false positives because the
	address is at least 8 byte aligned (it's the function
	descriptor, not the actual code address).
	
	While here, rename syscall_return with epc_syscall_return
	for clarity and consistency.

Affected files ...

.. //depot/projects/ia64_epc/sys/ia64/ia64/locore.s#17 edit
.. //depot/projects/ia64_epc/sys/ia64/ia64/syscall.s#16 edit
.. //depot/projects/ia64_epc/sys/ia64/ia64/trap.c#19 edit
.. //depot/projects/ia64_epc/sys/ia64/include/cpu.h#8 edit

Differences ...

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

@@ -174,7 +174,7 @@
 {	.mbb
 	cmp.eq		p6,p7=r0,r14
 (p6)	br.sptk		exception_restore
-(p7)	br.sptk		syscall_return
+(p7)	br.sptk		epc_syscall_return
 	;;
 }
 END(fork_trampoline)

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

@@ -323,40 +323,40 @@
 	;;
 }
 {	.mmi
-	alloc		r14=ar.pfs,8,0,3,0
+	alloc		r14=ar.pfs,0,0,8,0
 	st8		[r30]=r8,16		// syscall number (=r15)
 	nop		0
 	;;
 }
 {	.mmi
 	.mem.offset	0,0
-	st8.spill	[r31]=in0,16		// arg0 (=r16)
+	st8.spill	[r31]=r32,16		// arg0 (=r16)
 	.mem.offset	8,0
-	st8.spill	[r30]=in1,16		// arg1 (=r17)
+	st8.spill	[r30]=r33,16		// arg1 (=r17)
 	nop		0
 	;;
 }
 {	.mmi
 	.mem.offset	16,0
-	st8.spill	[r31]=in2,16		// arg2 (=r18)
+	st8.spill	[r31]=r34,16		// arg2 (=r18)
 	.mem.offset	24,0
-	st8.spill	[r30]=in3,16		// arg3 (=r19)
+	st8.spill	[r30]=r35,16		// arg3 (=r19)
 	nop		0
 	;;
 }
 {	.mmi
 	.mem.offset	32,0
-	st8.spill	[r31]=in4,16		// arg4 (=r20)
+	st8.spill	[r31]=r36,16		// arg4 (=r20)
 	.mem.offset	40,0
-	st8.spill	[r30]=in5,16		// arg5 (=r21)
+	st8.spill	[r30]=r37,16		// arg5 (=r21)
 	nop		0
 	;;
 }
 {	.mmi
 	.mem.offset	48,0
-	st8.spill	[r31]=in6,16		// arg6 (=r22)
+	st8.spill	[r31]=r38		// arg6 (=r22)
 	.mem.offset	56,0
-	st8.spill	[r30]=in7,8		// arg7 (=r23)
+	st8.spill	[r30]=r39		// arg7 (=r23)
 	nop		0
 	;;
 }
@@ -365,28 +365,27 @@
 	movl		gp=__gp
 	;;
 }
-{	.mii
-	mov		out0=r8
-	add		out1=-(8*8),r31
-	add		out2=16,sp
+epc_syscall_restart:
+{	.mib
+	srlz.d
+	add		out0=16,sp
+	br.call.sptk	rp=syscall
 	;;
 }
 {	.mfb
-	srlz.d
+	add		out0=16,sp
 	nop		0
-	br.call.sptk	rp=syscall
+	br.call.sptk	rp=do_ast
 	;;
 }
 {	.mfb
-	add		out0=16,sp
+	cmp4.eq		p15,p0=ERESTART,r8
 	nop		0
-	br.call.sptk	rp=do_ast
+(p15)	br.spnt		epc_syscall_restart
 	;;
 }
-
-	.global		syscall_return
-	.type		syscall_return, @function
-syscall_return:
+	.global		epc_syscall_return
+epc_syscall_return:
 {	.mmi
 	alloc		r31=ar.pfs,0,0,0,0
 	add		r14=32,sp

==== //depot/projects/ia64_epc/sys/ia64/ia64/trap.c#19 (text+ko) ====

@@ -312,7 +312,7 @@
 /*
  *
  */
-void
+int
 do_ast(struct trapframe *tf)
 {
 
@@ -322,7 +322,12 @@
 		ast(tf);
 		disable_intr();
 	}
-	/* Keep interrupts disabled. */
+	/*
+	 * Keep interrupts disabled. We return r10 as a favor to the EPC
+	 * syscall code so that it can quicky determine if the syscall
+	 * needs to be restarted or not.
+	 */
+	return (tf->tf_scratch.gr10);
 }
 
 /*
@@ -886,7 +891,7 @@
 		if (((uintptr_t)bsp & 0x1ff) == 0x1f8)
 			bsp++;
 	}
-	error = syscall(tf->tf_scratch.gr15, &tf->tf_scratch.gr16, tf);
+	error = syscall(tf);
 	if (error == ERESTART) {
 		tf->tf_special.iip = iip;
 		tf->tf_special.psr = psr;
@@ -903,20 +908,24 @@
  * the hairy details.
  */
 int
-syscall(int code, u_int64_t *args, struct trapframe *framep)
+syscall(struct trapframe *tf)
 {
 	struct sysent *callp;
 	struct proc *p;
 	struct thread *td;
-	int error;
+	u_int64_t *args;
+	int code, error;
 	u_int sticks;
 
+	code = tf->tf_scratch.gr15;
+	args = &tf->tf_scratch.gr16;
+
 	atomic_add_int(&cnt.v_syscall, 1);
 
 	td = curthread;
 	p = td->td_proc;
 
-	td->td_frame = framep;
+	td->td_frame = tf;
 	sticks = td->td_sticks;
 	if (td->td_ucred != p->p_ucred)
 		cred_update_thread(td);
@@ -924,7 +933,7 @@
 		thread_user_enter(p, td);
 
 	if (p->p_sysent->sv_prepsyscall) {
-		/* (*p->p_sysent->sv_prepsyscall)(framep, args, &code, &params); */
+		/* (*p->p_sysent->sv_prepsyscall)(tf, args, &code, &params); */
 		panic("prepsyscall");
 	} else {
 		/*
@@ -960,31 +969,30 @@
 
 	td->td_retval[0] = 0;
 	td->td_retval[1] = 0;
+	tf->tf_scratch.gr10 = EJUSTRETURN;
 
 	STOPEVENT(p, S_SCE, (callp->sy_narg & SYF_ARGMASK));
 
 	error = (*callp->sy_call)(td, args);
 
-	switch (error) {
-	case 0:
-		framep->tf_scratch.gr8 = td->td_retval[0];
-		framep->tf_scratch.gr9 = td->td_retval[1];
-		framep->tf_scratch.gr10 = 0;
-		break;
-	case ERESTART:
-		break;
-	case EJUSTRETURN:
-		break;
-	default:
-		if (p->p_sysent->sv_errsize) {
-			if (error >= p->p_sysent->sv_errsize)
-				error = -1;	/* XXX */
-			else
+	if (error != EJUSTRETURN) {
+		/*
+		 * Save the "raw" error code in r10. We use this to handle
+		 * syscall restarts (see do_ast()).
+		 */
+		tf->tf_scratch.gr10 = error;
+		if (error == 0) {
+			tf->tf_scratch.gr8 = td->td_retval[0];
+			tf->tf_scratch.gr9 = td->td_retval[1];
+		} else if (error != ERESTART) {
+			if (error < p->p_sysent->sv_errsize)
 				error = p->p_sysent->sv_errtbl[error];
+			/*
+			 * Translated error codes are returned in r8. User
+			 * processes use the translated error code.
+			 */
+			tf->tf_scratch.gr8 = error;
 		}
-		framep->tf_scratch.gr8 = error;
-		framep->tf_scratch.gr10 = 1;
-		break;
 	}
 
 	/*
@@ -993,7 +1001,7 @@
 	if ((callp->sy_narg & SYF_MPSAFE) == 0)
 		mtx_unlock(&Giant);
 
-	userret(td, framep, sticks);
+	userret(td, tf, sticks);
 
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSRET))

==== //depot/projects/ia64_epc/sys/ia64/include/cpu.h#8 (text+ko) ====

@@ -107,7 +107,7 @@
 int	badaddr(void *, size_t);
 int	badaddr_read(void *, size_t, void *);
 u_int64_t console_restart(u_int64_t, u_int64_t, u_int64_t);
-void	do_ast(struct trapframe *);
+int	do_ast(struct trapframe *);
 void	dumpconf(void);
 void	frametoreg(struct trapframe *, struct reg *);
 long	fswintrberr(void);				/* MAGIC */
@@ -126,7 +126,7 @@
 void	regtoframe(struct reg *, struct trapframe *);
 void	set_iointr(void (*)(void *, unsigned long));
 void	fork_trampoline(void);				/* MAGIC */
-int	syscall(int, u_int64_t *, struct trapframe *);
+int	syscall(struct trapframe *);
 void	trap(int vector, struct trapframe *framep);
 void	ia64_probe_sapics(void);
 int	ia64_count_cpus(void);


More information about the p4-projects mailing list