PR/6356: Hubert Feyer: Linux emulation has problem w/ pipes

On linux we don't have syscalls that use retval[1] (edx). So don't
corrupt edx, because the compiler assumes that it has the same
value as before the syscall. Also, compute if we are running under
linux emulation in one place.  XXX: Someday we should have a syscall
function per emulation and avoid the mess.
This commit is contained in:
christos 1998-10-27 18:04:27 +00:00
parent 6463d10c79
commit 12fd61ebc9
1 changed files with 34 additions and 35 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.124 1998/10/01 15:53:33 erh Exp $ */
/* $NetBSD: trap.c,v 1.125 1998/10/27 18:04:27 christos Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -657,12 +657,15 @@ syscall(frame)
size_t argsize;
register_t code, args[8], rval[2];
u_quad_t sticks;
#ifdef COMPAT_LINUX
int linux;
#endif /* COMPAT_LINUX */
#if defined(UVM)
uvmexp.syscalls++;
#else
cnt.v_syscall++;
#endif
#endif /* UVM */
if (!USERMODE(frame.tf_cs, frame.tf_eflags))
panic("syscall");
p = curproc;
@ -674,12 +677,25 @@ syscall(frame)
nsys = p->p_emul->e_nsysent;
callp = p->p_emul->e_sysent;
#ifdef COMPAT_LINUX
linux = 0
# ifdef EXEC_AOUT
|| (p->p_emul == &emul_linux_aout)
# endif /* EXEC_AOUT */
# ifdef EXEC_ELF32
|| (p->p_emul == &emul_linux_elf32)
# endif /* EXEC_ELF32 */
# ifdef EXEC_ELF64
|| (p->p_emul == &emul_linux_elf64)
# endif /* EXEC_ELF64 */
;
#endif /* COMPAT_LINUX */
#ifdef COMPAT_IBCS2
if (p->p_emul == &emul_ibcs2_coff || p->p_emul == &emul_ibcs2_elf ||
p->p_emul == &emul_ibcs2_xout)
if (IBCS2_HIGH_SYSCALL(code))
code = IBCS2_CVT_HIGH_SYSCALL(code);
#endif
#endif /* COMPAT_IBCS2 */
params = (caddr_t)frame.tf_esp + sizeof(int);
#ifdef VM86
@ -691,25 +707,15 @@ syscall(frame)
if (frame.tf_eflags & PSL_VM)
code = -1;
else
#endif
#endif /* VM86 */
switch (code) {
case SYS_syscall:
#ifdef COMPAT_LINUX
/* Linux has a special system setup call as number 0 */
if (0
#ifdef EXEC_AOUT
|| (p->p_emul == &emul_linux_aout)
#endif
#ifdef EXEC_ELF32
|| (p->p_emul == &emul_linux_elf32)
#endif
#ifdef EXEC_ELF64
|| (p->p_emul == &emul_linux_elf64)
#endif
)
if (linux)
break;
#endif
#endif /* COMPAT_LINUX */
/*
* Code is first argument, followed by actual args.
*/
@ -724,10 +730,11 @@ syscall(frame)
#ifdef COMPAT_FREEBSD
/* FreeBSD has a same function in SYS___syscall */
if (callp != sysent && p->p_emul != &emul_freebsd)
break;
#else
if (callp != sysent)
#endif
break;
#endif /* COMPAT_FREEBSD */
code = fuword(params + _QUAD_LOWWORD * sizeof(int));
params += sizeof(quad_t);
break;
@ -741,18 +748,7 @@ syscall(frame)
argsize = callp->sy_argsize;
if (argsize) {
#ifdef COMPAT_LINUX
/* XXX extra if() for every emul type.. */
if (0
#ifdef EXEC_AOUT
|| (p->p_emul == &emul_linux_aout)
#endif
#ifdef EXEC_ELF32
|| (p->p_emul == &emul_linux_elf32)
#endif
#ifdef EXEC_ELF64
|| (p->p_emul == &emul_linux_elf64)
#endif
) {
if (linux) {
/*
* Linux passes the args in ebx, ecx, edx, esi, edi, in
* increasing order.
@ -776,7 +772,7 @@ syscall(frame)
}
}
else
#endif /* !COMPAT_LINUX */
#endif /* COMPAT_LINUX */
{
error = copyin(params, (caddr_t)args, argsize);
if (error)
@ -785,11 +781,11 @@ syscall(frame)
}
#ifdef SYSCALL_DEBUG
scdebug_call(p, code, args);
#endif
#endif /* SYSCALL_DEBUG */
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code, argsize, args);
#endif
#endif /* KTRACE */
rval[0] = 0;
rval[1] = frame.tf_edx;
error = (*callp->sy_call)(p, args, rval);
@ -801,7 +797,10 @@ syscall(frame)
*/
p = curproc;
frame.tf_eax = rval[0];
frame.tf_edx = rval[1];
#ifdef COMPAT_LINUX
if (!linux)
#endif /* COMPAT_LINUX */
frame.tf_edx = rval[1];
frame.tf_eflags &= ~PSL_C; /* carry bit */
break;
case ERESTART:
@ -826,12 +825,12 @@ syscall(frame)
#ifdef SYSCALL_DEBUG
scdebug_ret(p, code, error, rval);
#endif
#endif /* SYSCALL_DEBUG */
userret(p, frame.tf_eip, sticks);
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET))
ktrsysret(p->p_tracep, code, error, rval[0]);
#endif
#endif /* KTRACE */
}
void