mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-28 21:03:54 -06:00
bsd-user: FreeBSD update
basic FreeBSD sysarch(2) handling fixed syscall errno return Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
976b2037e5
commit
78cfb07fe0
9 changed files with 462 additions and 31 deletions
116
bsd-user/main.c
116
bsd-user/main.c
|
@ -46,6 +46,7 @@ int have_guest_base;
|
|||
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
|
||||
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
|
||||
extern char **environ;
|
||||
enum BSDType bsd_type;
|
||||
|
||||
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
|
||||
we allocate a bigger stack. Need a better solution, for example
|
||||
|
@ -168,7 +169,7 @@ static void set_idt(int n, unsigned int dpl)
|
|||
}
|
||||
#endif
|
||||
|
||||
void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
|
||||
void cpu_loop(CPUX86State *env)
|
||||
{
|
||||
int trapnr;
|
||||
abi_ulong pc;
|
||||
|
@ -179,27 +180,90 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
|
|||
switch(trapnr) {
|
||||
case 0x80:
|
||||
/* syscall from int $0x80 */
|
||||
env->regs[R_EAX] = do_openbsd_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EBX],
|
||||
env->regs[R_ECX],
|
||||
env->regs[R_EDX],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_EBP]);
|
||||
if (bsd_type == target_freebsd) {
|
||||
abi_ulong params = (abi_ulong) env->regs[R_ESP] +
|
||||
sizeof(int32_t);
|
||||
int32_t syscall_nr = env->regs[R_EAX];
|
||||
int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
|
||||
|
||||
if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
|
||||
get_user_s32(syscall_nr, params);
|
||||
params += sizeof(int32_t);
|
||||
} else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
|
||||
get_user_s32(syscall_nr, params);
|
||||
params += sizeof(int64_t);
|
||||
}
|
||||
get_user_s32(arg1, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg2, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg3, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg4, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg5, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg6, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg7, params);
|
||||
params += sizeof(int32_t);
|
||||
get_user_s32(arg8, params);
|
||||
env->regs[R_EAX] = do_freebsd_syscall(env,
|
||||
syscall_nr,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4,
|
||||
arg5,
|
||||
arg6,
|
||||
arg7,
|
||||
arg8);
|
||||
} else { //if (bsd_type == target_openbsd)
|
||||
env->regs[R_EAX] = do_openbsd_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EBX],
|
||||
env->regs[R_ECX],
|
||||
env->regs[R_EDX],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_EBP]);
|
||||
}
|
||||
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
|
||||
env->regs[R_EAX] = -env->regs[R_EAX];
|
||||
env->eflags |= CC_C;
|
||||
} else {
|
||||
env->eflags &= ~CC_C;
|
||||
}
|
||||
break;
|
||||
#ifndef TARGET_ABI32
|
||||
case EXCP_SYSCALL:
|
||||
/* linux syscall from syscall intruction */
|
||||
env->regs[R_EAX] = do_openbsd_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDX],
|
||||
env->regs[10],
|
||||
env->regs[8],
|
||||
env->regs[9]);
|
||||
/* syscall from syscall intruction */
|
||||
if (bsd_type == target_freebsd)
|
||||
env->regs[R_EAX] = do_freebsd_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDX],
|
||||
env->regs[R_ECX],
|
||||
env->regs[8],
|
||||
env->regs[9], 0, 0);
|
||||
else { //if (bsd_type == target_openbsd)
|
||||
env->regs[R_EAX] = do_openbsd_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDX],
|
||||
env->regs[10],
|
||||
env->regs[8],
|
||||
env->regs[9]);
|
||||
}
|
||||
env->eip = env->exception_next_eip;
|
||||
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
|
||||
env->regs[R_EAX] = -env->regs[R_EAX];
|
||||
env->eflags |= CC_C;
|
||||
} else {
|
||||
env->eflags &= ~CC_C;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if 0
|
||||
|
@ -446,7 +510,7 @@ static void flush_windows(CPUSPARCState *env)
|
|||
#endif
|
||||
}
|
||||
|
||||
void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
|
||||
void cpu_loop(CPUSPARCState *env)
|
||||
{
|
||||
int trapnr, ret, syscall_nr;
|
||||
//target_siginfo_t info;
|
||||
|
@ -458,6 +522,10 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
|
|||
#ifndef TARGET_SPARC64
|
||||
case 0x80:
|
||||
#else
|
||||
/* FreeBSD uses 0x141 for syscalls too */
|
||||
case 0x141:
|
||||
if (bsd_type != target_freebsd)
|
||||
goto badtrap;
|
||||
case 0x100:
|
||||
#endif
|
||||
syscall_nr = env->gregs[1];
|
||||
|
@ -465,7 +533,7 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
|
|||
ret = do_freebsd_syscall(env, syscall_nr,
|
||||
env->regwptr[0], env->regwptr[1],
|
||||
env->regwptr[2], env->regwptr[3],
|
||||
env->regwptr[4], env->regwptr[5]);
|
||||
env->regwptr[4], env->regwptr[5], 0, 0);
|
||||
else if (bsd_type == target_netbsd)
|
||||
ret = do_netbsd_syscall(env, syscall_nr,
|
||||
env->regwptr[0], env->regwptr[1],
|
||||
|
@ -482,6 +550,7 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
|
|||
env->regwptr[4], env->regwptr[5]);
|
||||
}
|
||||
if ((unsigned int)ret >= (unsigned int)(-515)) {
|
||||
ret = -ret;
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
env->xcc |= PSR_CARRY;
|
||||
#else
|
||||
|
@ -587,6 +656,9 @@ void cpu_loop(CPUSPARCState *env, enum BSDType bsd_type)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef TARGET_SPARC64
|
||||
badtrap:
|
||||
#endif
|
||||
printf ("Unhandled trap: 0x%x\n", trapnr);
|
||||
cpu_dump_state(env, stderr, fprintf, 0);
|
||||
exit (1);
|
||||
|
@ -668,7 +740,7 @@ int main(int argc, char **argv)
|
|||
int gdbstub_port = 0;
|
||||
char **target_environ, **wrk;
|
||||
envlist_t *envlist = NULL;
|
||||
enum BSDType bsd_type = target_openbsd;
|
||||
bsd_type = target_openbsd;
|
||||
|
||||
if (argc <= 1)
|
||||
usage();
|
||||
|
@ -1033,7 +1105,7 @@ int main(int argc, char **argv)
|
|||
gdbserver_start (gdbstub_port);
|
||||
gdb_handlesig(env, 0);
|
||||
}
|
||||
cpu_loop(env, bsd_type);
|
||||
cpu_loop(env);
|
||||
/* never exits */
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue