diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h index 05c9d1c..214d691 100644 --- a/bsd-user/arm/target_signal.h +++ b/bsd-user/arm/target_signal.h @@ -67,6 +67,29 @@ struct target_sigframe { target_ucontext_t sf_uc; /* saved ucontext */ }; +/* compare to sys/arm/include/frame.h */ +typedef struct target_trapframe { + abi_ulong tf_spsr; /* Zero on arm26 */ + abi_ulong tf_r0; + abi_ulong tf_r1; + abi_ulong tf_r2; + abi_ulong tf_r3; + abi_ulong tf_r4; + abi_ulong tf_r5; + abi_ulong tf_r6; + abi_ulong tf_r7; + abi_ulong tf_r8; + abi_ulong tf_r9; + abi_ulong tf_r10; + abi_ulong tf_r11; + abi_ulong tf_r12; + abi_ulong tf_usr_sp; + abi_ulong tf_usr_lr; + abi_ulong tf_svc_sp; /* Not used on arm26 */ + abi_ulong tf_svc_lr; /* Not used on arm26 */ + abi_ulong tf_pc; +} target_trapframe_t; + #define TARGET_SZSIGCODE (8 * 4) /* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */ @@ -224,4 +247,22 @@ get_ucontext_sigreturn(CPUARMState *regs, abi_ulong sf_addr, return (0); } +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +/* XXX crashes on first shared lib call */ +static inline void +thread_set_upcall(CPUARMState *regs, abi_ulong entry, abi_ulong arg, + abi_ulong stack_base, abi_ulong stack_size) +{ + abi_ulong sp; + + sp = ((stack_base + stack_size) & (8 - 1)) - sizeof(struct target_trapframe); + + /* fp = sp = stack base */ + regs->regs[11] = regs->regs[13] = sp; + /* pc = start function entry */ + regs->regs[15] = regs->regs[14] = entry & 0xfffffffe; + /* r0 = arg */ + regs->regs[0] = arg; +} + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h index bc50fbb..2186c68 100644 --- a/bsd-user/arm/target_vmparam.h +++ b/bsd-user/arm/target_vmparam.h @@ -1,7 +1,19 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "arm" +#define TARGET_HW_MACHINE_ARCH "armv6" + #if defined(__FreeBSD__) + +/* compare to arm/include/vmparam.h */ +#define TARGET_MAXTSIZ (64UL*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (512UL*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (2UL*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (8UL*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */ + /* KERNBASE - 512 MB */ #define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024)) #define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS @@ -18,10 +30,6 @@ struct target_ps_strings { #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings)) -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 7a7c3eb..da9ad73 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -701,13 +701,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm, /* Create enough stack to hold everything. If we don't use * it for args, we'll use it for something else... */ -#ifdef TARGET_STACK_SIZE - size = TARGET_STACK_SIZE; -#else - size = x86_stack_size; - if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) - size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; -#endif + size = target_dflssiz; #ifdef TARGET_USRSTACK stack_base = TARGET_USRSTACK - size; diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h index 51a2a7b..034b455 100644 --- a/bsd-user/i386/target_signal.h +++ b/bsd-user/i386/target_signal.h @@ -45,4 +45,12 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr, return (-TARGET_ENOSYS); } +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +static inline void +thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg, + abi_ulong stack_base, abi_ulong stack_size) +{ + fprintf(stderr, "i386 doesn't have support for thread_set_upcall()\n"); +} + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/i386/target_vmparam.h b/bsd-user/i386/target_vmparam.h index ea7546c..fb8493f 100644 --- a/bsd-user/i386/target_vmparam.h +++ b/bsd-user/i386/target_vmparam.h @@ -1,8 +1,19 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "i386" +#define TARGET_HW_MACHINE_ARCH "i386" + #if defined(__FreeBSD__) +/* compare to i386/include/vmparam.h */ +#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (512UL*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */ + #define TARGET_USRSTACK (0xbfc00000) struct target_ps_strings { @@ -19,10 +30,6 @@ struct target_ps_strings { #define TARGET_SZSIGCODE 0 -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/main.c b/bsd-user/main.c index b248a91..99b94c1 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -56,10 +56,15 @@ const char *qemu_uname_release = CONFIG_UNAME_RELEASE; extern char **environ; enum BSDType bsd_type; +unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */ +unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */ +unsigned long target_maxdsiz = TARGET_MAXDSIZ; /* max data size */ /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so we allocate a bigger stack. Need a better solution, for example by remapping the process stack directly at the right place */ -unsigned long x86_stack_size = 512 * 1024; +unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */ +unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */ +unsigned long target_sgrowsiz = TARGET_SGROWSIZ;/* amount to grow stack */ static void save_proc_pathname(void); char qemu_proc_pathname[PATH_MAX]; @@ -126,7 +131,7 @@ static int pending_cpus; /* Make sure everything is in a consistent state for calling fork(). */ void fork_start(void) { - pthread_mutex_lock(&tb_lock); + spin_lock(&tb_lock); pthread_mutex_lock(&exclusive_lock); mmap_fork_start(); } @@ -146,11 +151,11 @@ void fork_end(int child) pthread_mutex_init(&cpu_list_mutex, NULL); pthread_cond_init(&exclusive_cond, NULL); pthread_cond_init(&exclusive_resume, NULL); - pthread_mutex_init(&tb_lock, NULL); + spin_lock_init(&tb_lock); gdbserver_fork(thread_env); } else { pthread_mutex_unlock(&exclusive_lock); - pthread_mutex_unlock(&tb_lock); + spin_unlock(&tb_lock); } } @@ -1012,10 +1017,7 @@ void cpu_loop(CPUMIPSState *env) for(;;) { cpu_exec_start(env); - /* XXX there is a concurrency problem - giant lock for now */ - pthread_mutex_lock(&exclusive_lock); /* XXX */ trapnr = cpu_mips_exec(env); - pthread_mutex_unlock(&exclusive_lock); /* XXX */ cpu_exec_end(env); switch(trapnr) { case EXCP_SYSCALL: /* syscall exception */ @@ -1481,7 +1483,7 @@ static void usage(void) , TARGET_ARCH, interp_prefix, - x86_stack_size, + target_dflssiz, DEBUG_LOGFILE); exit(1); } @@ -1603,13 +1605,15 @@ int main(int argc, char **argv) usage(); } else if (!strcmp(r, "s")) { r = argv[optind++]; - x86_stack_size = strtol(r, (char **)&r, 0); - if (x86_stack_size <= 0) + target_dflssiz = strtol(r, (char **)&r, 0); + if (target_dflssiz <= 0) usage(); if (*r == 'M') - x86_stack_size *= 1024 * 1024; + target_dflssiz *= 1024 * 1024; else if (*r == 'k' || *r == 'K') - x86_stack_size *= 1024; + target_dflssiz *= 1024; + if (target_dflssiz > target_maxssiz) + usage(); } else if (!strcmp(r, "L")) { interp_prefix = argv[optind++]; } else if (!strcmp(r, "p")) { @@ -1797,7 +1801,7 @@ int main(int argc, char **argv) qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); } - target_set_brk(info->brk); + target_set_brk(info->start_data, info->brk, info->end_data); syscall_init(); signal_init(); diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h index 0f57f0f..abe4587 100644 --- a/bsd-user/mips/target_signal.h +++ b/bsd-user/mips/target_signal.h @@ -6,6 +6,10 @@ #define TARGET_MINSIGSTKSZ (512 * 4) #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) +/* compare to sys/mips/include/asm.h */ +#define TARGET_SZREG 4 +#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4) + struct target_sigcontext { target_sigset_t sc_mask; /* signal mask to retstore */ int32_t sc_onstack; /* sigstack state to restore */ @@ -207,4 +211,27 @@ get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr, return (0); } +/* Compare to mips/mips/vm_machdep.c cpu_set_upcall_kse() */ +static inline void +thread_set_upcall(CPUMIPSState *regs, abi_ulong entry, + abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size) +{ + abi_ulong sp; + + /* + * At the point where a function is called, sp must be 8 + * byte aligned[for compatibility with 64-bit CPUs] + * in ``See MIPS Run'' by D. Sweetman, p. 269 + * align stack + */ + sp = ((stack_base + stack_size) & ~0x7) - TARGET_CALLFRAME_SIZ; + + /* t9 = pc = start function entry */ + regs->active_tc.gpr[25] = regs->active_tc.PC = entry; + /* a0 = arg */ + regs->active_tc.gpr[ 4] = arg; + /* sp = top of the stack */ + regs->active_tc.gpr[29] = sp; +} + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h index 8abc26c..6eca54f 100644 --- a/bsd-user/mips/target_vmparam.h +++ b/bsd-user/mips/target_vmparam.h @@ -1,7 +1,19 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "mips" +#define TARGET_HW_MACHINE_ARCH "mips" + #if defined(__FreeBSD__) + +/* compare to sys/mips/include/vmparam.h */ +#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (1*1024UL*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */ + #define TARGET_VM_MINUSER_ADDRESS (0x00000000) #define TARGET_VM_MAXUSER_ADDRESS (0x80000000) @@ -21,10 +33,6 @@ struct target_ps_strings { #define TARGET_SZSIGCODE 0 -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h index 3fee772..60105ec 100644 --- a/bsd-user/mips64/target_signal.h +++ b/bsd-user/mips64/target_signal.h @@ -6,6 +6,10 @@ #define TARGET_MINSIGSTKSZ (512 * 4) #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) +/* compare to sys/mips/include/asm.h */ +#define TARGET_SZREG 8 +#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4) + struct target_sigcontext { target_sigset_t sc_mask; /* signal mask to retstore */ int32_t sc_onstack; /* sigstack state to restore */ @@ -226,5 +230,28 @@ get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr, return (0); } +/* Compare to mips/mips/vm_machdep.c cpu_set_upcall_kse() */ +static inline void +thread_set_upcall(CPUMIPSState *regs, abi_ulong entry, + abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size) +{ + abi_ulong sp; + + /* + * At the point where a function is called, sp must be 8 + * byte aligned[for compatibility with 64-bit CPUs] + * in ``See MIPS Run'' by D. Sweetman, p. 269 + * align stack + */ + sp = ((stack_base + stack_size) & ~0x7) - TARGET_CALLFRAME_SIZ; + + /* t9 = pc = start function entry */ + regs->active_tc.gpr[25] = regs->active_tc.PC = entry; + /* a0 = arg */ + regs->active_tc.gpr[ 4] = arg; + /* sp = top of the stack */ + regs->active_tc.gpr[29] = sp; +} + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/mips64/target_vmparam.h b/bsd-user/mips64/target_vmparam.h index 55ed254..3fe93fb 100644 --- a/bsd-user/mips64/target_vmparam.h +++ b/bsd-user/mips64/target_vmparam.h @@ -1,8 +1,19 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "mips" +#define TARGET_HW_MACHINE_ARCH "mips64" + #if defined(__FreeBSD__) +/* compare to sys/mips/include/vmparam.h */ +#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (1*1024UL*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */ + #define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL) #define TARGET_VM_MAXUSER_ADDRESS (0x0000008000000000UL) @@ -20,10 +31,6 @@ struct target_ps_strings { #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings)) -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c index 495f0ec..1ed597a 100644 --- a/bsd-user/mmap.c +++ b/bsd-user/mmap.c @@ -31,8 +31,8 @@ //#define DEBUG_MMAP #if defined(CONFIG_USE_NPTL) -pthread_mutex_t mmap_mutex; -static int __thread mmap_lock_count; +pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; +static __thread int mmap_lock_count; void mmap_lock(void) { @@ -348,6 +348,9 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, case MAP_SHARED: printf("MAP_SHARED "); break; + case MAP_STACK: + printf("MAP_STACK "); + break; default: printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK); break; @@ -356,6 +359,14 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, } #endif + if (flags & MAP_STACK) { + if ((fd != -1) || + ((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE))) { + errno = EINVAL; + goto fail; + } + } + if (offset & ~TARGET_PAGE_MASK) { errno = EINVAL; goto fail; diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index fbcdd6c..4c20e48 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -147,7 +147,7 @@ int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs, struct image_info * info); int is_target_elf_binary(int fd); -void target_set_brk(abi_ulong new_brk); +void target_set_brk(abi_ulong start_brk, abi_ulong cur_brk, abi_ulong end_brk); 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, @@ -221,7 +221,12 @@ void mmap_fork_end(int child); #endif /* main.c */ -extern unsigned long x86_stack_size; +extern unsigned long target_maxtsiz; +extern unsigned long target_dfldsiz; +extern unsigned long target_maxdsiz; +extern unsigned long target_dflssiz; +extern unsigned long target_maxssiz; +extern unsigned long target_sgrowsiz; extern char qemu_proc_pathname[]; extern char target_proc_pathname[]; diff --git a/bsd-user/signal.c b/bsd-user/signal.c index e7e9e41..c4e8440 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -631,7 +631,7 @@ get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size) target_sigaltstack_used.ss_size; } -#if defined(TARGET_MIPS) +#if defined(TARGET_MIPS) || defined(TARGET_ARM) return ((sp - frame_size) & ~7); #else return (sp - frame_size); diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h index 65d315a..20630d7 100644 --- a/bsd-user/sparc/target_signal.h +++ b/bsd-user/sparc/target_signal.h @@ -51,4 +51,12 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr, return (-TARGET_ENOSYS); } +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +static inline void +thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg, + abi_ulong stack_base, abi_ulong stack_size) +{ + fprintf(stderr, "SPARC doesn't have support for thread_set_upcall()\n"); +} + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/sparc/target_vmparam.h b/bsd-user/sparc/target_vmparam.h index 82c29ed..b8dcd0d 100644 --- a/bsd-user/sparc/target_vmparam.h +++ b/bsd-user/sparc/target_vmparam.h @@ -1,7 +1,18 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "sparc" +#define TARGET_HW_MACHINE_ARCH "sparc" + #ifdef __FreeBSD__ + +#define TARGET_MAXTSIZ (1*1024*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (128*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (1*1024*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (128*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (1*1024*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128*1024) /* amount to grow stack */ + struct target_ps_strings { abi_ulong ps_argvstr; uint32_t ps_nargvstr; @@ -20,10 +31,6 @@ struct target_ps_strings { #define TARGET_SZSIGCODE 0 -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h index fa8edb8..67378a5 100644 --- a/bsd-user/sparc64/target_signal.h +++ b/bsd-user/sparc64/target_signal.h @@ -253,4 +253,12 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr, return (-TARGET_ENOSYS); } +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +static inline void +thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg, + abi_ulong stack_base, abi_ulong stack_size) +{ + fprintf(stderr, "SPARC64 doesn't have support for thread_set_upcall()\n"); +} + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/sparc64/target_vmparam.h b/bsd-user/sparc64/target_vmparam.h index 7f2b464..b8dbf2c 100644 --- a/bsd-user/sparc64/target_vmparam.h +++ b/bsd-user/sparc64/target_vmparam.h @@ -1,7 +1,19 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "sparc" +#define TARGET_HW_MACHINE_ARCH "sparc64" + #if defined(__FreeBSD__) + +/* compare to amd64/include/vmparam.h */ +#define TARGET_MAXTSIZ (1*1024*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (128*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (1*1024*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (128*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (1*1024*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128*1024) /* amount to grow stack */ + #define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL) #define TARGET_VM_MAXUSER_ADDRESS (0x000007fe00000000UL) @@ -21,10 +33,6 @@ struct target_ps_strings { #define TARGET_SZSIGCODE 0 -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index 2d97a23..0f337e2 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -98,8 +98,7 @@ //#define DEBUG -static abi_ulong target_brk; -static abi_ulong target_original_brk; +static abi_ulong target_brk_start, target_brk_cur, target_brk_end; static char *get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len); @@ -123,6 +122,7 @@ get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len) struct filestat *fst; char *ret = NULL; +#if defined(__FreeBSD_version) && __FreeBSD_version > 900000 procstat = procstat_open_sysctl(); if (NULL == procstat) goto out; @@ -152,6 +152,7 @@ out: procstat_freeprocs(procstat, kipp); if (procstat != NULL) procstat_close(procstat); +#endif return (ret); } @@ -188,41 +189,45 @@ static inline int is_error(abi_long ret) return (abi_ulong)ret >= (abi_ulong)(-4096); } -void target_set_brk(abi_ulong new_brk) +void target_set_brk(abi_ulong start_brk, abi_ulong cur_brk, abi_ulong end_brk) { - target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); + target_brk_start = HOST_PAGE_ALIGN(start_brk); + target_brk_cur = cur_brk; + target_brk_end = HOST_PAGE_ALIGN(end_brk); } /* do_obreak() must return target errnos. */ static abi_long do_obreak(abi_ulong new_brk) { - abi_ulong brk_page; abi_long mapped_addr; - int new_alloc_size; + abi_ulong new_alloc_size; + + return -TARGET_EINVAL; // XXX Temporary disable obreak() until it can be properly fixed if (!new_brk) return 0; - if (new_brk < target_original_brk) + if (new_brk < target_brk_cur) { return -TARGET_EINVAL; - - brk_page = HOST_PAGE_ALIGN(target_brk); + } /* If the new brk is less than this, set it and we're done... */ - if (new_brk < brk_page) { - target_brk = new_brk; + if (new_brk < target_brk_end) { + target_brk_cur = new_brk; return 0; } /* We need to allocate more memory after the brk... */ - new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); - mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, + new_alloc_size = HOST_PAGE_ALIGN(new_brk - target_brk_end + 1); + mapped_addr = get_errno(target_mmap(target_brk_end, new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0)); - if (!is_error(mapped_addr)) - target_brk = new_brk; - else + if (!is_error(mapped_addr)) { + target_brk_cur = new_brk; + target_brk_end += new_alloc_size; + } else { return mapped_addr; + } return 0; } @@ -520,11 +525,7 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol case CTL_KERN: switch(snamep[1]) { case KERN_USRSTACK: -#if defined(TARGET_ARM) && HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 - (*(uint32_t *)holdp) = 0xfffff000U; - holdlen = sizeof(uint32_t); - ret = 0; -#elif TARGET_USRSTACK != 0 +#if TARGET_USRSTACK != 0 (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK); holdlen = sizeof(abi_ulong); ret = 0; @@ -568,6 +569,22 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol } break; + case CTL_HW: + switch(snamep[1]) { + case HW_MACHINE: + strlcpy(holdp, TARGET_HW_MACHINE, oldlen); + ret = 0; + goto out; + + case HW_MACHINE_ARCH: + strlcpy(holdp, TARGET_HW_MACHINE_ARCH, oldlen); + ret = 0; + goto out; + + default: + break; + } + default: break; } @@ -1736,7 +1753,9 @@ int_case: case IP_RECVDSTADDR: case IP_RETOPTS: +#if defined(__FreeBSD_version) && __FreeBSD_version > 900000 case IP_RECVTOS: +#endif case IP_MULTICAST_TTL: case IP_MULTICAST_LOOP: case IP_PORTRANGE: @@ -2553,7 +2572,7 @@ do_fork(CPUArchState *env, int num, int flags, int *fdp) static pthread_mutex_t new_thread_lock = PTHREAD_MUTEX_INITIALIZER; typedef struct { CPUArchState *env; - long tid; + long parent_tid; pthread_mutex_t mutex; pthread_cond_t cond; pthread_t thread; @@ -2571,24 +2590,23 @@ new_thread_start(void *arg) env = info->env; thread_env = env; + fork_end(1); + ts = (TaskState *)thread_env->opaque; (void)thr_self(&tid); - info->tid = tid; task_settid(ts); /* copy out the TID info */ if (info->param.child_tid) put_user(tid, info->param.child_tid, abi_long); if (info->param.parent_tid) - put_user(tid, info->param.parent_tid, abi_long); + put_user(info->parent_tid, info->param.parent_tid, abi_long); -#ifdef TARGET_MIPS64 - CPUMIPSState *regs = env; - regs->active_tc.gpr[25] = regs->active_tc.PC = info->param.start_func; - regs->active_tc.gpr[ 4] = info->param.arg; - regs->active_tc.gpr[29] = info->param.stack_base; -#endif - /* Eenable signals */ + /* Set arch dependent registers to start thread. */ + thread_set_upcall(env, info->param.start_func, info->param.arg, + info->param.stack_base, info->param.stack_size); + + /* Enable signals */ sigprocmask(SIG_SETMASK, &info->sigmask, NULL); /* Signal to the parent that we're ready. */ pthread_mutex_lock(&info->mutex); @@ -2662,9 +2680,12 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size) info.param.tls_size = tswapal(target_param->tls_size); info.param.child_tid = tswapal(target_param->child_tid); info.param.parent_tid = tswapal(target_param->parent_tid); + info.param.flags = tswap32(target_param->flags); target_rtp_addr = info.param.rtp = tswapal(target_param->rtp); unlock_user(target_param, target_param_addr, 0); + thr_self(&info.parent_tid); + if (target_rtp_addr) { if (!lock_user_struct(VERIFY_READ, target_rtp, target_rtp_addr, 1)) @@ -2678,6 +2699,7 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size) } /* Create a new CPU instance. */ + fork_start(); ts = g_malloc0(sizeof(TaskState)); init_task_state(ts); new_env = cpu_copy(env); @@ -2691,9 +2713,8 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size) ts->bprm = parent_ts->bprm; ts->info = parent_ts->info; -#if defined(TARGET_MIPS) - env->tls_value = info.param.tls_base; - /* cpu_set_tls(new_env, info.param.tls_base); */ +#if defined(TARGET_MIPS) || defined(TARGET_ARM) + cpu_set_tls(env, info.param.tls_base); #endif /* Grab a mutex so that thread setup appears atomic. */ @@ -2725,6 +2746,8 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size) ret = pthread_create(&info.thread, &attr, new_thread_start, &info); /* XXX Free new CPU state if thread creation fails. */ + fork_end(0); + sigprocmask(SIG_SETMASK, &info.sigmask, NULL); pthread_attr_destroy(&attr); if (0 == ret) { @@ -2791,6 +2814,9 @@ do_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr) g_free(ts); pthread_exit(NULL); } + + gdb_exit(cpu_env, 0); /* XXX need to put in the correct exit status here? */ + _exit(0); } static int @@ -3010,7 +3036,7 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts, int mode) { uint32_t owner, flags; - int ret; + int ret = 0; for (;;) { struct target_umutex *target_umutex; @@ -3058,7 +3084,6 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts, } __get_user(flags, &target_umutex->m_flags); - flags = tswap32(flags); if ((flags & TARGET_UMUTEX_ERROR_CHECK) != 0 && (owner & ~TARGET_UMUTEX_CONTESTED) == id) { unlock_user_struct(target_umutex, target_addr, 1); @@ -3070,6 +3095,15 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts, return (-TARGET_EBUSY); } + /* + * If we caught a signal, we have retried and now + * exit immediately. + */ + if (ret) { + unlock_user_struct(target_umutex, target_addr, 1); + return (ret); + } + /* Set the contested bit and sleep. */ if (!tcmpset_32(&target_umutex->m_owner, owner, owner | TARGET_UMUTEX_CONTESTED)) { @@ -3084,8 +3118,6 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts, owner = tswap32(owner); ret = get_errno(_umtx_op(target_umutex, UMTX_OP_WAIT_UINT, owner, 0, ts)); - if (ret) - return (ret); } return (0); @@ -4841,8 +4873,9 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_FREEBSD_NR_fstat: { struct stat st; + ret = get_errno(fstat(arg1, &st)); - if (! ret) + if (!is_error(ret)) ret = host_to_target_stat(arg2, &st); } break; @@ -4851,10 +4884,12 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, { struct timespec req, rem; - target_to_host_timespec(&req, arg1); - ret = get_errno(nanosleep(&req, &rem)); - if (is_error(ret) && arg2) - host_to_target_timespec(arg2, &rem); + ret = target_to_host_timespec(&req, arg1); + if (!is_error(ret)) { + ret = get_errno(nanosleep(&req, &rem)); + if (!is_error(ret) && arg2) + host_to_target_timespec(arg2, &rem); + } } break; @@ -5119,12 +5154,23 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, struct target_rlimit *target_rlim; struct rlimit rlim; - /* Return the target stack size */ - if (RLIMIT_STACK == resource) { - rlim.rlim_cur = rlim.rlim_max = TARGET_STACK_SIZE; + switch (resource) { + case RLIMIT_STACK: + rlim.rlim_cur = target_dflssiz; + rlim.rlim_max = target_maxssiz; ret = 0; - } else + break; + + case RLIMIT_DATA: + rlim.rlim_cur = target_dfldsiz; + rlim.rlim_max = target_maxdsiz; + ret = 0; + break; + + default: ret = get_errno(getrlimit(resource, &rlim)); + break; + } if (!is_error(ret)) { if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) @@ -7260,11 +7306,28 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, #if defined(__FreeBSD_version) && __FreeBSD_version > 900000 case TARGET_UMTX_OP_NWAKE_PRIVATE: - if (! access_ok(VERIFY_READ, obj, - val * sizeof(uint32_t))) - goto efault; - ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE, - val, NULL, NULL)); + { + int i; + abi_ulong *uaddr; + + if (! access_ok(VERIFY_READ, obj, + val * sizeof(uint32_t))) + goto efault; + + ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE, + val, NULL, NULL)); + + uaddr = (abi_ulong *)g2h(obj); + ret = 0; + for(i = 0; i < (int32_t)val; i++) { + ret = get_errno(_umtx_op(g2h(tswapal(uaddr[i])), + UMTX_OP_WAKE_PRIVATE, tswap32(INT_MAX), + NULL, NULL)); + if (ret) + break; + } + + } break; #endif diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index eb804b3..c2e78bd 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -544,6 +544,7 @@ struct target_thr_param { abi_ulong tls_size; /* tls size. */ abi_ulong child_tid; /* address to store new TID. */ abi_ulong parent_tid; /* parent access the new TID here. */ + int32_t flags; /* thread flags. */ abi_ulong rtp; /* Real-time scheduling priority. */ abi_ulong spare[3]; /* spares. */ }; diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h index 72df2f0..51e32bf 100644 --- a/bsd-user/x86_64/target_signal.h +++ b/bsd-user/x86_64/target_signal.h @@ -49,4 +49,13 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr, return (-TARGET_ENOSYS); } +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +static inline void +thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg, + abi_ulong stack_base, abi_ulong stack_size) +{ + fprintf(stderr, "x86_64 doesn't have support for thread_set_upcall()\n"); +} + + #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/x86_64/target_vmparam.h b/bsd-user/x86_64/target_vmparam.h index ff9f534..70891a1 100644 --- a/bsd-user/x86_64/target_vmparam.h +++ b/bsd-user/x86_64/target_vmparam.h @@ -1,7 +1,19 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ +#define TARGET_HW_MACHINE "amd64" +#define TARGET_HW_MACHINE_ARCH "amd64" + #if defined(__FreeBSD__) + +/* compare to amd64/include/vmparam.h */ +#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */ +#define TARGET_DFLDSIZ (32768UL*1024*1024) /* initial data size limit */ +#define TARGET_MAXDSIZ (32768UL*1024*1024) /* max data size */ +#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */ +#define TARGET_MAXSSIZ (512UL*1024*1024) /* max stack size */ +#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */ + #define TARGET_VM_MAXUSER_ADDRESS (0x0000800000000000UL) #define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE) @@ -20,10 +32,6 @@ struct target_ps_strings { #define TARGET_SZSIGCODE 0 -/* Make stack size large enough to hold everything. */ -#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ - MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) - #else #define TARGET_USRSTACK 0 diff --git a/include/exec/spinlock.h b/include/exec/spinlock.h index a72edda..fc1f808 100644 --- a/include/exec/spinlock.h +++ b/include/exec/spinlock.h @@ -24,6 +24,7 @@ #include #define spin_lock pthread_mutex_lock #define spin_unlock pthread_mutex_unlock +#define spin_lock_init(mtx) pthread_mutex_init(mtx, NULL) #define spinlock_t pthread_mutex_t #define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER diff --git a/include/qemu/tls.h b/include/qemu/tls.h index b92ea9d..ae7d79d 100644 --- a/include/qemu/tls.h +++ b/include/qemu/tls.h @@ -38,7 +38,7 @@ * TODO: proper implementations via Win32 .tls sections and * POSIX pthread_getspecific. */ -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) #define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x) #define DEFINE_TLS(type, x) __thread __typeof__(type) tls__##x #define tls_var(x) tls__##x