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, ¶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);
More information about the p4-projects
mailing list