diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h index 0427244..24dca00 100644 --- a/bsd-user/arm/target_vmparam.h +++ b/bsd-user/arm/target_vmparam.h @@ -20,6 +20,10 @@ 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/elfload.c b/bsd-user/elfload.c index 0c48f5a..f5f652f 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -715,9 +715,13 @@ 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 #ifdef TARGET_USRSTACK stack_base = TARGET_USRSTACK - size; @@ -738,7 +742,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm, #if defined(__FreeBSD__) /* - * The inital FreeBSD stack looks like follows: + * The inital FreeBSD stack is as follows: * (see kern/kern_exec.c exec_copyout_strings() ) * * Hi Address -> char **ps_argvstr (struct ps_strings for ps, w, etc.) diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list index bcdd931..c66dcfa 100644 --- a/bsd-user/freebsd/strace.list +++ b/bsd-user/freebsd/strace.list @@ -118,6 +118,7 @@ { TARGET_FREEBSD_NR_revoke, "revoke", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_rfork, "rfork", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_rmdir, "rmdir", NULL, NULL, NULL }, +{ TARGET_FREEBSD_NR_rtprio_thread, "rtprio_thread", "%s(%d, %d, %p)", NULL, NULL }, { TARGET_FREEBSD_NR_sbrk, "sbrk", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_sched_yield, "sched_yield", NULL, NULL, NULL }, { TARGET_FREEBSD_NR_select, "select", NULL, NULL, NULL }, diff --git a/bsd-user/i386/target_vmparam.h b/bsd-user/i386/target_vmparam.h index 8fc98d5..ea7546c 100644 --- a/bsd-user/i386/target_vmparam.h +++ b/bsd-user/i386/target_vmparam.h @@ -19,6 +19,10 @@ 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 7cc77aa..32bd3e5 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -855,7 +855,9 @@ void cpu_loop(CPUARMState *env) goto do_segv; } break; +#if 0 error: +#endif default: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h index 9fca7f3..8abc26c 100644 --- a/bsd-user/mips/target_vmparam.h +++ b/bsd-user/mips/target_vmparam.h @@ -21,6 +21,10 @@ 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_vmparam.h b/bsd-user/mips64/target_vmparam.h index 47c2267..55ed254 100644 --- a/bsd-user/mips64/target_vmparam.h +++ b/bsd-user/mips64/target_vmparam.h @@ -20,6 +20,10 @@ 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/sparc/target_vmparam.h b/bsd-user/sparc/target_vmparam.h index 9494c46..82c29ed 100644 --- a/bsd-user/sparc/target_vmparam.h +++ b/bsd-user/sparc/target_vmparam.h @@ -1,8 +1,6 @@ #ifndef _TARGET_VMPARAM_H_ #define _TARGET_VMPARAM_H_ -#define TARGET_USRSTACK 0 - #ifdef __FreeBSD__ struct target_ps_strings { abi_ulong ps_argvstr; @@ -14,9 +12,22 @@ struct target_ps_strings { #define TARGET_SPACE_USRSPACE 4096 #define TARGET_ARG_MAX 262144 +/* XXX */ +#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024)) +#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS + #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(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 + #endif /* __FreeBSD__ */ #endif /* _TARGET_VMPARAM_H_ */ diff --git a/bsd-user/sparc64/target_vmparam.h b/bsd-user/sparc64/target_vmparam.h index 12af063..7f2b464 100644 --- a/bsd-user/sparc64/target_vmparam.h +++ b/bsd-user/sparc64/target_vmparam.h @@ -21,6 +21,10 @@ 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 a40d7ce..8565ae8 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -409,19 +409,44 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) *q++ = tswap32(*p); oidfmt(snamep, namelen, NULL, &kind); - /* XXX swap hnewp */ -#if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 - /* XXX there may be more sysctls that differ */ - if (namelen == 2 && - snamep[0] == CTL_KERN && snamep[1] == KERN_USRSTACK && - holdlen && holdlen == 4 && hnewp == NULL) { - (*(uint32_t *)holdp) = 0xfffff000U; - ret = 0; - } else + + /* Handle some arch/emulator dependent sysctl()'s here. */ + if (CTL_KERN == snamep[0]) { + 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 + (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK); + holdlen = sizeof(abi_ulong); + ret = 0; +#else + ret = -TARGET_ENOENT; +#endif + goto out; + + case KERN_PS_STRINGS: +#if defined(TARGET_PS_STRINGS) + (*(abi_ulong *)holdp) = tswapal(TARGET_PS_STRINGS); + holdlen = sizeof(abi_ulong); + ret = 0; +#else + ret = -TARGET_ENOENT; #endif + goto out; + + default: + break; + } + } + ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen)); if (!ret) sysctl_oldcvt(holdp, holdlen, kind); + +out: put_user_ual(holdlen, oldlenp); unlock_user(hnamep, namep, 0); unlock_user(holdp, oldp, holdlen); @@ -3293,6 +3318,47 @@ host_to_target_fhandle(abi_ulong target_addr, fhandle_t *host_fh) } static inline abi_long +target_to_host_rtprio(struct rtprio *host_rtp, abi_ulong target_addr) +{ + struct target_rtprio *target_rtp; + + if (!lock_user_struct(VERIFY_READ, target_rtp, target_addr, 1)) + return (-TARGET_EFAULT); + __get_user(host_rtp->type, &target_rtp->type); + __get_user(host_rtp->prio, &target_rtp->prio); + unlock_user_struct(target_rtp, target_addr, 0); + return (0); +} + +static inline abi_long +host_to_target_rtprio(abi_ulong target_addr, struct rtprio *host_rtp) +{ + struct target_rtprio *target_rtp; + + if (!lock_user_struct(VERIFY_WRITE, target_rtp, target_addr, 0)) + return (-TARGET_EFAULT); + __put_user(host_rtp->type, &target_rtp->type); + __put_user(host_rtp->prio, &target_rtp->prio); + unlock_user_struct(target_rtp, target_addr, 1); + return (0); +} + +static inline abi_long +do_rtprio_thread(int function, lwpid_t lwpid, abi_ulong target_addr) +{ + int ret; + struct rtprio rtp; + + ret = target_to_host_rtprio(&rtp, target_addr); + if (0 == ret) + ret = get_errno(rtprio_thread(function, lwpid, &rtp)); + if (0 == ret) + ret = host_to_target_rtprio(target_addr, &rtp); + + return (ret); +} + +static inline abi_long target_to_host_sched_param(struct sched_param *host_sp, abi_ulong target_addr) { struct target_sched_param *target_sp; @@ -4617,12 +4683,17 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, struct target_rlimit *target_rlim; struct rlimit rlim; - if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) - goto efault; - rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); - rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); - unlock_user_struct(target_rlim, arg2, 0); - ret = get_errno(setrlimit(resource, &rlim)); + if (RLIMIT_STACK == resource) { + /* XXX We should, maybe, allow the stack size to shrink */ + ret = -TARGET_EPERM; + } else { + if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) + goto efault; + rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); + rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); + unlock_user_struct(target_rlim, arg2, 0); + ret = get_errno(setrlimit(resource, &rlim)); + } } break; @@ -4633,7 +4704,12 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, struct target_rlimit *target_rlim; struct rlimit rlim; - ret = get_errno(getrlimit(resource, &rlim)); + /* Return the target stack size */ + if (RLIMIT_STACK == resource) { + rlim.rlim_cur = rlim.rlim_max = TARGET_STACK_SIZE; + ret = 0; + } else + ret = get_errno(getrlimit(resource, &rlim)); if (!is_error(ret)) { if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) @@ -6148,7 +6224,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, break; case TARGET_FREEBSD_NR_rtprio_thread: - ret = 0; + ret = do_rtprio_thread(arg1, arg2, arg3); break; case TARGET_FREEBSD_NR_getcontext: diff --git a/bsd-user/x86_64/target_vmparam.h b/bsd-user/x86_64/target_vmparam.h index aa5e0e0..ff9f534 100644 --- a/bsd-user/x86_64/target_vmparam.h +++ b/bsd-user/x86_64/target_vmparam.h @@ -20,6 +20,10 @@ 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