Date: Sun, 4 May 2003 21:57:10 -0700 (PDT) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 30572 for review Message-ID: <200305050457.h454vAHe027383@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=30572 Change 30572 by marcel@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, ¶ms); */ + /* (*p->p_sysent->sv_prepsyscall)(tf, args, &code, ¶ms); */ 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305050457.h454vAHe027383>