Commit 78cfb07f authored by Juergen Lock's avatar Juergen Lock Committed by Blue Swirl
Browse files

bsd-user: FreeBSD update



basic FreeBSD sysarch(2) handling
fixed syscall errno return

Signed-off-by: default avatarJuergen Lock <nox@jelal.kn-bremen.de>
Signed-off-by: default avatarBlue Swirl <blauwirbel@gmail.com>
parent 976b2037
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -126,6 +126,9 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
    regs->rax = 0;
    regs->rsp = infop->start_stack;
    regs->rip = infop->entry;
    if (bsd_type == target_freebsd) {
        regs->rdi = infop->start_stack;
    }
}

#else
@@ -249,8 +252,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#else
    if (personality(infop->personality) == PER_LINUX32)
        regs->u_regs[14] = infop->start_stack - 16 * 4;
    else
    else {
        regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
        if (bsd_type == target_freebsd) {
            regs->u_regs[8] = infop->start_stack;
            regs->u_regs[11] = infop->start_stack;
        }
    }
#endif
}

+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
{ TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_geteuid, "geteuid", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_getfh, "getfh", NULL, NULL, NULL },
+14 −0
Original line number Diff line number Diff line
@@ -143,5 +143,19 @@ struct target_vm86plus_struct {
	struct target_vm86plus_info_struct vm86plus;
};

/* FreeBSD sysarch(2) */
#define TARGET_FREEBSD_I386_GET_LDT	0
#define TARGET_FREEBSD_I386_SET_LDT	1
				/* I386_IOPL */
#define TARGET_FREEBSD_I386_GET_IOPERM	3
#define TARGET_FREEBSD_I386_SET_IOPERM	4
				/* xxxxx */
#define TARGET_FREEBSD_I386_VM86	6
#define TARGET_FREEBSD_I386_GET_FSBASE	7
#define TARGET_FREEBSD_I386_SET_FSBASE	8
#define TARGET_FREEBSD_I386_GET_GSBASE	9
#define TARGET_FREEBSD_I386_SET_GSBASE	10


#define UNAME_MACHINE "i386"
+94 −22
Original line number Diff line number Diff line
@@ -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,6 +180,45 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
        switch(trapnr) {
        case 0x80:
            /* syscall from int $0x80 */
            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],
@@ -187,10 +227,27 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
                                                      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 */
            /* 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],
@@ -199,7 +256,14 @@ void cpu_loop(CPUX86State *env, enum BSDType bsd_type)
                                                      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;
}
+4 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ enum BSDType {
    target_netbsd,
    target_openbsd,
};
extern enum BSDType bsd_type;

#include "syscall_defs.h"
#include "syscall.h"
@@ -130,7 +131,8 @@ abi_long do_brk(abi_ulong new_brk);
void syscall_init(void);
abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
                            abi_long arg2, abi_long arg3, abi_long arg4,
                            abi_long arg5, abi_long arg6);
                            abi_long arg5, abi_long arg6, abi_long arg7,
                            abi_long arg8);
abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
                           abi_long arg2, abi_long arg3, abi_long arg4,
                           abi_long arg5, abi_long arg6);
@@ -139,7 +141,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
                            abi_long arg5, abi_long arg6);
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
extern THREAD CPUState *thread_env;
void cpu_loop(CPUState *env, enum BSDType bsd_type);
void cpu_loop(CPUState *env);
char *target_strerror(int err);
int get_osversion(void);
void fork_start(void);
Loading