diff options
author | sos <sos@FreeBSD.org> | 1995-02-14 19:23:22 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 1995-02-14 19:23:22 +0000 |
commit | 6deee3a45e9abcbe47f1e19b76c976658e2c5f26 (patch) | |
tree | 14e904cc9fa37485b1036478f5d4998f31c42a71 /sys | |
parent | 7402b2152526539603dab9e8f1b64f404e3905e1 (diff) | |
download | FreeBSD-src-6deee3a45e9abcbe47f1e19b76c976658e2c5f26.zip FreeBSD-src-6deee3a45e9abcbe47f1e19b76c976658e2c5f26.tar.gz |
First attempt to run linux binaries. This is only the changes needed to
the generic kernel. The actual emulator is a separate LKM. (not finished
yet, sorry).
Submitted by: sos@freebsd.org & sef@kithrup.com
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/exception.S | 40 | ||||
-rw-r--r-- | sys/amd64/amd64/exception.s | 40 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 12 | ||||
-rw-r--r-- | sys/amd64/amd64/trap.c | 117 | ||||
-rw-r--r-- | sys/amd64/include/segments.h | 4 | ||||
-rw-r--r-- | sys/i386/i386/exception.s | 40 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 12 | ||||
-rw-r--r-- | sys/i386/i386/trap.c | 117 | ||||
-rw-r--r-- | sys/i386/include/segments.h | 4 | ||||
-rw-r--r-- | sys/kern/imgact_aout.c | 12 | ||||
-rw-r--r-- | sys/kern/init_sysent.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 12 | ||||
-rw-r--r-- | sys/kern/makesyscalls.sh | 4 | ||||
-rw-r--r-- | sys/kern/subr_trap.c | 117 | ||||
-rw-r--r-- | sys/kern/syscalls.c | 2 | ||||
-rw-r--r-- | sys/sys/syscall-hide.h | 2 | ||||
-rw-r--r-- | sys/sys/syscall.h | 2 | ||||
-rw-r--r-- | sys/sys/sysent.h | 3 |
18 files changed, 518 insertions, 25 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index f6d6115..5d4f469 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: exception.s,v 1.6 1994/12/03 10:02:19 bde Exp $ + * $Id: exception.s,v 1.7 1995/01/14 13:20:05 bde Exp $ */ #include "npx.h" /* NNPX */ @@ -245,6 +245,44 @@ IDTVEC(syscall) MEXITCOUNT jmp _doreti +#ifdef COMPAT_LINUX +/* + * Call gate entry for Linux syscall (int 0x80) + */ + SUPERALIGN_TEXT +IDTVEC(linux_syscall) + pushl $0 + pushl $0 + pushal + pushl %ds + pushl %es + movl $KDSEL,%eax + movl %ax,%ds + movl %ax,%es + FAKE_MCOUNT(12*4(%esp)) + incl _cnt+V_SYSCALL + orl $SWI_AST_MASK,_cpl + call _linux_syscall + /* + * There was no place to save the cpl so we have to recover it + * indirectly. For traps from user mode it was 0, and for traps + * from kernel mode Oring SWI_AST_MASK into it didn't change it. + */ + subl %eax,%eax + testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) + jne 1f + movl _cpl,%eax +1: + /* + * Return via _doreti to handle ASTs. Have to change trap frame + * to interrupt frame. + */ + pushl %eax + subl $4,%esp + MEXITCOUNT + jmp _doreti +#endif /* COMPAT_LINUX */ + /* * Include what was once config+isa-dependent code. * XXX it should be in a stand-alone file. It's still icu-dependent and diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s index f6d6115..5d4f469 100644 --- a/sys/amd64/amd64/exception.s +++ b/sys/amd64/amd64/exception.s @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: exception.s,v 1.6 1994/12/03 10:02:19 bde Exp $ + * $Id: exception.s,v 1.7 1995/01/14 13:20:05 bde Exp $ */ #include "npx.h" /* NNPX */ @@ -245,6 +245,44 @@ IDTVEC(syscall) MEXITCOUNT jmp _doreti +#ifdef COMPAT_LINUX +/* + * Call gate entry for Linux syscall (int 0x80) + */ + SUPERALIGN_TEXT +IDTVEC(linux_syscall) + pushl $0 + pushl $0 + pushal + pushl %ds + pushl %es + movl $KDSEL,%eax + movl %ax,%ds + movl %ax,%es + FAKE_MCOUNT(12*4(%esp)) + incl _cnt+V_SYSCALL + orl $SWI_AST_MASK,_cpl + call _linux_syscall + /* + * There was no place to save the cpl so we have to recover it + * indirectly. For traps from user mode it was 0, and for traps + * from kernel mode Oring SWI_AST_MASK into it didn't change it. + */ + subl %eax,%eax + testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) + jne 1f + movl _cpl,%eax +1: + /* + * Return via _doreti to handle ASTs. Have to change trap frame + * to interrupt frame. + */ + pushl %eax + subl $4,%esp + MEXITCOUNT + jmp _doreti +#endif /* COMPAT_LINUX */ + /* * Include what was once config+isa-dependent code. * XXX it should be in a stand-alone file. It's still icu-dependent and diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index b82ecc0..3e07341 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.108 1995/02/11 04:21:24 phk Exp $ + * $Id: machdep.c,v 1.109 1995/02/12 09:21:04 davidg Exp $ */ #include "npx.h" @@ -1125,6 +1125,11 @@ extern inthand_t IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), IDTVEC(syscall); +#ifdef COMPAT_LINUX +extern inthand_t + IDTVEC(linux_syscall); +#endif + void sdtossd(sd, ssd) struct segment_descriptor *sd; @@ -1224,7 +1229,10 @@ init386(first) setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL); - +#ifdef COMPAT_LINUX + setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL); +#endif + #include "isa.h" #if NISA >0 isa_defaultirq(); diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 5adff94..f98022b 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.46 1995/02/10 06:25:14 davidg Exp $ + * $Id: trap.c,v 1.47 1995/02/10 06:43:47 davidg Exp $ */ /* @@ -747,3 +747,118 @@ syscall(frame) ktrsysret(p->p_tracep, code, error, rval[0]); #endif } + +#ifdef COMPAT_LINUX +/* + * linux_syscall(frame): + */ +/*ARGSUSED*/ +void +linux_syscall(frame) + struct trapframe frame; +{ + caddr_t params; + int i; + struct proc *p = curproc; + struct sysent *callp; + u_quad_t sticks; + int error, opc; + int rval[2]; + int code; + struct linux_syscall_args { + int ebx; + int ecx; + int edx; + int esi; + int edi; + int ebp; + int eax; + } args; + + args.ebx = frame.tf_ebx; + args.ecx = frame.tf_ecx; + args.edx = frame.tf_edx; + args.esi = frame.tf_esi; + args.edi = frame.tf_edi; + args.ebp = frame.tf_ebp; + args.eax = frame.tf_eax; + + sticks = p->p_sticks; + if (ISPL(frame.tf_cs) != SEL_UPL) + panic("linux syscall"); + + code = frame.tf_eax; + p->p_md.md_regs = (int *)&frame; + params = (caddr_t)frame.tf_esp + sizeof (int) ; + + /* + * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. + * THIS IS WRONG FOR LINUX XXX SOS + * SIZE OF INT 0x80 (2??) NEEDED HERE !!! + */ + opc = frame.tf_eip - 2; /* was 7 */ + if (code == 0) { + code = fuword(params); + params += sizeof (int); + } + if (p->p_sysent->sv_mask) + code = code & p->p_sysent->sv_mask; + + if (code < 0 || code >= p->p_sysent->sv_size) + callp = &p->p_sysent->sv_table[0]; + else + callp = &p->p_sysent->sv_table[code]; + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); +#endif + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); +#endif + rval[0] = 0; + rval[1] = frame.tf_edx; + + error = (*callp->sy_call)(p, &args, rval); + + switch (error) { + + case 0: + /* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + frame.tf_eax = rval[0]; + frame.tf_eflags &= ~PSL_C; /* carry bit */ + break; + + case ERESTART: + frame.tf_eip = opc; + break; + + case EJUSTRETURN: + break; + + default: + bad: + if (p->p_sysent->sv_errsize) + if (error >= p->p_sysent->sv_errsize) + error = -1; /* XXX */ + else + error = p->p_sysent->sv_errtbl[error]; + frame.tf_eax = -error; + frame.tf_eflags |= PSL_C; /* carry bit */ + break; + } + + userret(p, &frame, sticks); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif +} +#endif /* COMPAT_LINUX */ diff --git a/sys/amd64/include/segments.h b/sys/amd64/include/segments.h index 6302599..0c236f5 100644 --- a/sys/amd64/include/segments.h +++ b/sys/amd64/include/segments.h @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 - * $Id: segments.h,v 1.6 1994/11/14 14:18:15 bde Exp $ + * $Id: segments.h,v 1.7 1994/11/15 14:12:40 bde Exp $ */ #ifndef _MACHINE_SEGMENTS_H_ @@ -194,7 +194,7 @@ struct region_descriptor { * Size of IDT table */ -#define NIDT 48 /* 32 reserved, 16 h/w, 0 s/w */ +#define NIDT 129 /* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */ #define NRSVIDT 32 /* reserved entries for cpu exceptions */ /* diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index f6d6115..5d4f469 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: exception.s,v 1.6 1994/12/03 10:02:19 bde Exp $ + * $Id: exception.s,v 1.7 1995/01/14 13:20:05 bde Exp $ */ #include "npx.h" /* NNPX */ @@ -245,6 +245,44 @@ IDTVEC(syscall) MEXITCOUNT jmp _doreti +#ifdef COMPAT_LINUX +/* + * Call gate entry for Linux syscall (int 0x80) + */ + SUPERALIGN_TEXT +IDTVEC(linux_syscall) + pushl $0 + pushl $0 + pushal + pushl %ds + pushl %es + movl $KDSEL,%eax + movl %ax,%ds + movl %ax,%es + FAKE_MCOUNT(12*4(%esp)) + incl _cnt+V_SYSCALL + orl $SWI_AST_MASK,_cpl + call _linux_syscall + /* + * There was no place to save the cpl so we have to recover it + * indirectly. For traps from user mode it was 0, and for traps + * from kernel mode Oring SWI_AST_MASK into it didn't change it. + */ + subl %eax,%eax + testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) + jne 1f + movl _cpl,%eax +1: + /* + * Return via _doreti to handle ASTs. Have to change trap frame + * to interrupt frame. + */ + pushl %eax + subl $4,%esp + MEXITCOUNT + jmp _doreti +#endif /* COMPAT_LINUX */ + /* * Include what was once config+isa-dependent code. * XXX it should be in a stand-alone file. It's still icu-dependent and diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index b82ecc0..3e07341 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.108 1995/02/11 04:21:24 phk Exp $ + * $Id: machdep.c,v 1.109 1995/02/12 09:21:04 davidg Exp $ */ #include "npx.h" @@ -1125,6 +1125,11 @@ extern inthand_t IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), IDTVEC(syscall); +#ifdef COMPAT_LINUX +extern inthand_t + IDTVEC(linux_syscall); +#endif + void sdtossd(sd, ssd) struct segment_descriptor *sd; @@ -1224,7 +1229,10 @@ init386(first) setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL); - +#ifdef COMPAT_LINUX + setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL); +#endif + #include "isa.h" #if NISA >0 isa_defaultirq(); diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 5adff94..f98022b 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.46 1995/02/10 06:25:14 davidg Exp $ + * $Id: trap.c,v 1.47 1995/02/10 06:43:47 davidg Exp $ */ /* @@ -747,3 +747,118 @@ syscall(frame) ktrsysret(p->p_tracep, code, error, rval[0]); #endif } + +#ifdef COMPAT_LINUX +/* + * linux_syscall(frame): + */ +/*ARGSUSED*/ +void +linux_syscall(frame) + struct trapframe frame; +{ + caddr_t params; + int i; + struct proc *p = curproc; + struct sysent *callp; + u_quad_t sticks; + int error, opc; + int rval[2]; + int code; + struct linux_syscall_args { + int ebx; + int ecx; + int edx; + int esi; + int edi; + int ebp; + int eax; + } args; + + args.ebx = frame.tf_ebx; + args.ecx = frame.tf_ecx; + args.edx = frame.tf_edx; + args.esi = frame.tf_esi; + args.edi = frame.tf_edi; + args.ebp = frame.tf_ebp; + args.eax = frame.tf_eax; + + sticks = p->p_sticks; + if (ISPL(frame.tf_cs) != SEL_UPL) + panic("linux syscall"); + + code = frame.tf_eax; + p->p_md.md_regs = (int *)&frame; + params = (caddr_t)frame.tf_esp + sizeof (int) ; + + /* + * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. + * THIS IS WRONG FOR LINUX XXX SOS + * SIZE OF INT 0x80 (2??) NEEDED HERE !!! + */ + opc = frame.tf_eip - 2; /* was 7 */ + if (code == 0) { + code = fuword(params); + params += sizeof (int); + } + if (p->p_sysent->sv_mask) + code = code & p->p_sysent->sv_mask; + + if (code < 0 || code >= p->p_sysent->sv_size) + callp = &p->p_sysent->sv_table[0]; + else + callp = &p->p_sysent->sv_table[code]; + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); +#endif + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); +#endif + rval[0] = 0; + rval[1] = frame.tf_edx; + + error = (*callp->sy_call)(p, &args, rval); + + switch (error) { + + case 0: + /* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + frame.tf_eax = rval[0]; + frame.tf_eflags &= ~PSL_C; /* carry bit */ + break; + + case ERESTART: + frame.tf_eip = opc; + break; + + case EJUSTRETURN: + break; + + default: + bad: + if (p->p_sysent->sv_errsize) + if (error >= p->p_sysent->sv_errsize) + error = -1; /* XXX */ + else + error = p->p_sysent->sv_errtbl[error]; + frame.tf_eax = -error; + frame.tf_eflags |= PSL_C; /* carry bit */ + break; + } + + userret(p, &frame, sticks); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif +} +#endif /* COMPAT_LINUX */ diff --git a/sys/i386/include/segments.h b/sys/i386/include/segments.h index 6302599..0c236f5 100644 --- a/sys/i386/include/segments.h +++ b/sys/i386/include/segments.h @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)segments.h 7.1 (Berkeley) 5/9/91 - * $Id: segments.h,v 1.6 1994/11/14 14:18:15 bde Exp $ + * $Id: segments.h,v 1.7 1994/11/15 14:12:40 bde Exp $ */ #ifndef _MACHINE_SEGMENTS_H_ @@ -194,7 +194,7 @@ struct region_descriptor { * Size of IDT table */ -#define NIDT 48 /* 32 reserved, 16 h/w, 0 s/w */ +#define NIDT 129 /* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */ #define NRSVIDT 32 /* reserved entries for cpu exceptions */ /* diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index c700c26..5d6454c 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: imgact_aout.c,v 1.8 1994/09/24 21:36:50 davidg Exp $ + * $Id: imgact_aout.c,v 1.9 1994/09/25 19:33:31 phk Exp $ */ #include <sys/param.h> @@ -54,6 +54,16 @@ exec_aout_imgact(iparams) int error; extern struct sysentvec aout_sysvec; +#ifdef COMPAT_LINUX + /* + * Linux and *BSD binaries look very much alike, + * only the machine id is different: + * 0x64 for Linux, 0x86 for *BSD. + */ + if (((a_out->a_magic >> 16) & 0xff) != 0x86) + return -1; +#endif /* COMPAT_LINUX */ + /* * Set file/virtual offset based on a.out variant. * We do two cases: host byte order and network byte order diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 8c68240..bd77750 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from $Id: syscalls.master,v 1.11 1994/10/02 04:45:52 davidg Exp $ + * created from $Id: syscalls.master,v 1.12 1994/12/14 17:57:23 wollman Exp $ */ #include <sys/param.h> @@ -520,5 +520,6 @@ struct sysentvec aout_sysvec = { 0, 0, 0, + 0, 0 }; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index b35343b..94b5dc2 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_exec.c,v 1.10 1994/10/02 17:35:13 phk Exp $ + * $Id: kern_exec.c,v 1.11 1995/01/09 16:04:49 davidg Exp $ */ #include <sys/param.h> @@ -46,6 +46,7 @@ #include <sys/wait.h> #include <sys/mman.h> #include <sys/malloc.h> +#include <sys/sysent.h> #include <sys/syslog.h> #include <sys/shm.h> @@ -214,9 +215,14 @@ interpret: p->p_vmspace->vm_minsaddr = (char *)stack_base; /* - * Stuff argument count as first item on stack + * If custom stack fixup routine present for this process + * let it do the stack setup. + * Else stuff argument count as first item on stack */ - *(--stack_base) = iparams->argc; + if (p->p_sysent->sv_fixup) + (*p->p_sysent->sv_fixup)(&stack_base, iparams); + else + *(--stack_base) = iparams->argc; /* close files on exec */ fdcloseexec(p); diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 50de7d2..a4875fb 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -1,6 +1,6 @@ #! /bin/sh - # @(#)makesyscalls.sh 8.1 (Berkeley) 6/10/93 -# $Id: makesyscalls.sh,v 1.9 1994/10/09 22:07:37 sos Exp $ +# $Id: makesyscalls.sh,v 1.10 1994/11/06 21:57:16 ats Exp $ set -e @@ -183,7 +183,7 @@ awk < $1 " printf ("struct sysentvec aout_sysvec = {\n") > sysent printf ("\tsizeof (sysent) / sizeof (sysent[0]),\n") > sysent printf ("\tsysent,\n") > sysent - printf ("\t0,\n\t0,\n\t0,\n\t0,\n\t0\n};\n") > sysent + printf ("\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0\n};\n") > sysent printf("};\n") > sysnames } ' diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 5adff94..f98022b 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.46 1995/02/10 06:25:14 davidg Exp $ + * $Id: trap.c,v 1.47 1995/02/10 06:43:47 davidg Exp $ */ /* @@ -747,3 +747,118 @@ syscall(frame) ktrsysret(p->p_tracep, code, error, rval[0]); #endif } + +#ifdef COMPAT_LINUX +/* + * linux_syscall(frame): + */ +/*ARGSUSED*/ +void +linux_syscall(frame) + struct trapframe frame; +{ + caddr_t params; + int i; + struct proc *p = curproc; + struct sysent *callp; + u_quad_t sticks; + int error, opc; + int rval[2]; + int code; + struct linux_syscall_args { + int ebx; + int ecx; + int edx; + int esi; + int edi; + int ebp; + int eax; + } args; + + args.ebx = frame.tf_ebx; + args.ecx = frame.tf_ecx; + args.edx = frame.tf_edx; + args.esi = frame.tf_esi; + args.edi = frame.tf_edi; + args.ebp = frame.tf_ebp; + args.eax = frame.tf_eax; + + sticks = p->p_sticks; + if (ISPL(frame.tf_cs) != SEL_UPL) + panic("linux syscall"); + + code = frame.tf_eax; + p->p_md.md_regs = (int *)&frame; + params = (caddr_t)frame.tf_esp + sizeof (int) ; + + /* + * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. + * THIS IS WRONG FOR LINUX XXX SOS + * SIZE OF INT 0x80 (2??) NEEDED HERE !!! + */ + opc = frame.tf_eip - 2; /* was 7 */ + if (code == 0) { + code = fuword(params); + params += sizeof (int); + } + if (p->p_sysent->sv_mask) + code = code & p->p_sysent->sv_mask; + + if (code < 0 || code >= p->p_sysent->sv_size) + callp = &p->p_sysent->sv_table[0]; + else + callp = &p->p_sysent->sv_table[code]; + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); +#endif + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, callp->sy_narg, &args); +#endif + rval[0] = 0; + rval[1] = frame.tf_edx; + + error = (*callp->sy_call)(p, &args, rval); + + switch (error) { + + case 0: + /* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + frame.tf_eax = rval[0]; + frame.tf_eflags &= ~PSL_C; /* carry bit */ + break; + + case ERESTART: + frame.tf_eip = opc; + break; + + case EJUSTRETURN: + break; + + default: + bad: + if (p->p_sysent->sv_errsize) + if (error >= p->p_sysent->sv_errsize) + error = -1; /* XXX */ + else + error = p->p_sysent->sv_errtbl[error]; + frame.tf_eax = -error; + frame.tf_eflags |= PSL_C; /* carry bit */ + break; + } + + userret(p, &frame, sticks); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif +} +#endif /* COMPAT_LINUX */ diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 247b928..d880f18 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * created from $Id: syscalls.master,v 1.11 1994/10/02 04:45:52 davidg Exp $ + * created from $Id: syscalls.master,v 1.12 1994/12/14 17:57:23 wollman Exp $ */ char *syscallnames[] = { diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index b40f3d9..3447f9c 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -2,7 +2,7 @@ * System call hiders. * * DO NOT EDIT-- this file is automatically generated. - * created from $Id: syscalls.master,v 1.11 1994/10/02 04:45:52 davidg Exp $ + * created from $Id: syscalls.master,v 1.12 1994/12/14 17:57:23 wollman Exp $ */ HIDE_POSIX(fork) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index ab6178c..8ebc58f 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * created from $Id: syscalls.master,v 1.11 1994/10/02 04:45:52 davidg Exp $ + * created from $Id: syscalls.master,v 1.12 1994/12/14 17:57:23 wollman Exp $ */ #define SYS_syscall 0 diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index 8a0d939..64ac5bb 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: sysent.h,v 1.1 1994/08/24 11:47:23 sos Exp $ + * $Id: sysent.h,v 1.2 1994/10/09 21:53:05 sos Exp $ */ #ifndef _SYS_SYSENT_H_ @@ -49,6 +49,7 @@ struct sysentvec { int *sv_sigtbl; /* signal translation table */ int sv_errsize; /* size of signal translation table */ int *sv_errtbl; /* errno translation table */ + int (*sv_fixup)(); /* stack fixup function */ }; #ifdef KERNEL |