linux-user patches for HEAD
cover linux-user patches for HEAD
From: Riku Voipio <[email protected]>
Again, the patches have been on the list before. I think they have had time for comments already, but I'll give another chance before sending this as a pull request to anthony.
If I have missed any patches, please resend or reply to the missed patch and CC: me.
Kirill A. Shutemov (1):
linux-user: Rewrite mmap_find_vma() to work fine on 64-bit hosts with
32-bit targets
Laurent Vivier (3):
m68k,linux-user: add setup_frame
m68k, linux-user: add setup_rt_frame
m68k, linux-user: enable sigaltstack()
Nathan Froyd (1):
linux-user: fix mq_* compilation problems
Riku Voipio (1):
linux-user: add eventfd support
Ulrich Hecht (5):
linux-user: fcntl fixes for LTP
linux-user: enable getdents for > 32-bit systems
linux-user: define a couple of syscalls for non-uid16 targets
linux-user: fadvise64 implementation
linux-user: zero fstat buffer to initialize nsec fields
configure | 18 ++ linux-user/mmap.c | 79 +++++----- linux-user/signal.c | 382 +++++++++++++++++++++++++++++++++++++++++++++ linux-user/syscall.c | 206 +++++++++++++++++++----- linux-user/syscall_defs.h | 7 + 5 files changed, 613 insertions(+), 79 deletions(-)
PATCH 1/11 linux-user: add eventfd support
From: Riku Voipio <[email protected]>
Straightforward implementation. This syscall is rare enough that we don't need to support the odder cases, just disable it if host glibc is too old.
--- configure | 18 ++++++++++++++++++ linux-user/syscall.c | 13 +++++++++++++ 2 files changed, 31 insertions(+), 0 deletions(-)
configure +18 -0
@@ -1345,6 +1345,21 @@ if compile_prog "" "" ; then splice=yes fi +# check if eventfd is supported +eventfd=no +cat > $TMPC << EOF +#include <sys/eventfd.h> + +int main(void) +{ + int efd = eventfd(0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + eventfd=yes +fi + # Check if tools are available to build documentation. if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then build_docs="no"
@@ -1684,6 +1699,9 @@ fi if test "$splice" = "yes" ; then echo "CONFIG_SPLICE=y" >> $config_host_mak fi +if test "$eventfd" = "yes" ; then + echo "CONFIG_EVENTFD=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi
linux-user/syscall.c +13 -0
@@ -6974,6 +6974,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,break ;#endif #endif /* CONFIG_SPLICE */ +#ifdef CONFIG_EVENTFD +#include <sys/eventfd.h> +#if defined(TARGET_NR_eventfd) +case TARGET_NR_eventfd: + ret =get_errno (eventfd (arg1,0 )); +break ; +#endif +#if defined(TARGET_NR_eventfd2) +case TARGET_NR_eventfd2: + ret =get_errno (eventfd (arg1, arg2)); +break ; +#endif +#endif /* CONFIG_EVENTFD */ default : unimplemented:gemu_log ("qemu: Unsupported syscall: %d\n" , num);
Signature · 1 line
1.6.2.1
Re: [Qemu-devel] [PATCH 01/11] linux-user: add eventfd support
Quoted 53 lines · On Thu, Aug 13, 2009 at 11:06 PM, <[email protected]> wrote:
From: Riku Voipio <[email protected]>
Straightforward implementation. This syscall is rare enough that we don't need to support the odder cases, just disable it if host glibc is too old.
Signed-off-by Riku Voipio <[email protected]>---
configure | 18 ++++++++++++++++++
linux-user/syscall.c | 13 +++++++++++++2 files changed, 31 insertions(+), 0 deletions(-)configure +0
-0@@ -1345,6 +1345,21 @@ if compile_prog "" "" ; thensplice=yes
ficonfigure +15
-0+# check if eventfd is supported +eventfd=no +cat > $TMPC << EOF +#include <sys/eventfd.h> + +int main(void) +{ + int efd = eventfd(0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + eventfd=yes +fi +# Check if tools are available to build documentation.
if test "$build_docs" = "yes" -a \( ! -x "which texi2html 2>/dev/null" -o ! -x "which pod2man 2>/dev/null" \) ; then build_docs="no"configure +0
-0@@ -1684,6 +1699,9 @@ fiif test "$splice" = "yes" ; then
echo "CONFIG_SPLICE=y" >> $config_host_mak
ficonfigure +3
-0+if test "$eventfd" = "yes" ; then + echo "CONFIG_EVENTFD=y" >> $config_host_mak +fiif test "$inotify" = "yes" ; then
echo "CONFIG_INOTIFY=y" >> $config_host_mak
filinux-user/syscall.c +0
-0
linux-user/syscall.c abi_long do_syscall(void *cpu_env, int num, abi_long arg1, · line 6978
Quoted 5 lines
linux-user/syscall.c +2
-0@@ -6974,6 +6974,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif #endif /* CONFIG_SPLICE */ +#ifdef CONFIG_EVENTFD +#include <sys/eventfd.h>
I don't think that #include within function is a good idea.
Quoted 20 lines
linux-user/syscall.c +11
-0+#if defined(TARGET_NR_eventfd) + case TARGET_NR_eventfd: + ret = get_errno(eventfd(arg1, 0)); + break; +#endif +#if defined(TARGET_NR_eventfd2) + case TARGET_NR_eventfd2: + ret = get_errno(eventfd(arg1, arg2)); + break; +#endif +#endif /* CONFIG_EVENTFD */ default:
unimplemented:
gemu_log("qemu: Unsupported syscall: %d\n", num); --
1.6.2.1
Re: [Qemu-devel] [PATCH 01/11] linux-user: add eventfd support
Quoted 5 lines · Kirill A. Shutemov
Review
Quoted 3 lines
#endif /*
CONFIG_SPLICE*/(quoted diff) +2
-0+#ifdef CONFIG_EVENTFD +#include <sys/eventfd.h>I don't think that #include within function is a good idea.
You are right. Corrected version attached.
Quoted 1 line
From
c2882b96545eeabf16767c6effa836e6f9991018Mon Sep 17 00:00:00 2001
Message-Id: <c2882b96545eeabf16767c6effa836e6f9991018.1251230665.git.riku.voipio@iki.fi>
In-Reply-To: <[email protected]>
References: <[email protected]>
From: Riku Voipio <[email protected]>
Date: Wed, 12 Aug 2009 15:08:24 +0300
Subject: [PATCH 01/10] linux-user: add eventfd support
Straightforward implementation. This syscall is rare enough that we don't need to support the odder cases, just disable it if host glibc is too old.
--- configure | 18 ++++++++++++++++++ linux-user/syscall.c | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 0 deletions(-)
configure +18 -0
@@ -1322,6 +1322,21 @@ if compile_prog "" "" ; then splice=yes fi +# check if eventfd is supported +eventfd=no +cat > $TMPC << EOF +#include <sys/eventfd.h> + +int main(void) +{ + int efd = eventfd(0, 0); + return 0; +} +EOF +if compile_prog "" "" ; then + eventfd=yes +fi + # Check if tools are available to build documentation. if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then build_docs="no"
@@ -1659,6 +1674,9 @@ fi if test "$splice" = "yes" ; then echo "CONFIG_SPLICE=y" >> $config_host_mak fi +if test "$eventfd" = "yes" ; then + echo "CONFIG_EVENTFD=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi
linux-user/syscall.c +15 -0
@@ -60,6 +60,9 @@#ifdef TARGET_GPROF #include <sys/gmon.h> #endif +#ifdef CONFIG_EVENTFD +#include <sys/eventfd.h> +#endif #define termios host_termios#define winsize host_winsize
@@ -6974,6 +6977,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,break ;#endif #endif /* CONFIG_SPLICE */ +#ifdef CONFIG_EVENTFD +#if defined(TARGET_NR_eventfd) +case TARGET_NR_eventfd: + ret =get_errno (eventfd (arg1,0 )); +break ; +#endif +#if defined(TARGET_NR_eventfd2) +case TARGET_NR_eventfd2: + ret =get_errno (eventfd (arg1, arg2)); +break ; +#endif +#endif /* CONFIG_EVENTFD */ default : unimplemented:gemu_log ("qemu: Unsupported syscall: %d\n" , num);
Signature · 1 line
1.6.2.1
PATCH 2/11 m68k,linux-user: add setup_frame
In reply to [email protected]From: Laurent Vivier <[email protected]>
This patch adds signals management for linux-user.
It implements setup_frame() which allows to call the user signal handler.
setup_rt_frame() is always unimplemented.
--- linux-user/signal.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 183 insertions(+), 0 deletions(-)
linux-user/signal.c +183 -0
@@ -4028,6 +4028,189 @@ sigsegv:return 0 ; } +#elif defined(TARGET_M68K ) + +struct target_sigcontext { +abi_ulong sc_mask; +abi_ulong sc_usp; +abi_ulong sc_d0; +abi_ulong sc_d1; +abi_ulong sc_a0; +abi_ulong sc_a1; +unsigned short sc_sr; +abi_ulong sc_pc; +}; + +struct target_sigframe +{ +abi_ulong pretcode; +int sig; +int code; +abi_ulong psc; +char retcode[8 ]; +abi_ulong extramask[TARGET_NSIG_WORDS -1 ]; +struct target_sigcontext sc; +}; + +static int +setup_sigcontext (struct target_sigcontext *sc,CPUState *env,abi_ulong mask) +{ +int err =0 ; + + err |=__put_user (mask, &sc->sc_mask); + err |=__put_user (env->aregs[7 ], &sc->sc_usp); + err |=__put_user (env->dregs[0 ], &sc->sc_d0); + err |=__put_user (env->dregs[1 ], &sc->sc_d1); + err |=__put_user (env->aregs[0 ], &sc->sc_a0); + err |=__put_user (env->aregs[1 ], &sc->sc_a1); + err |=__put_user (env->sr, &sc->sc_sr); + err |=__put_user (env->pc, &sc->sc_pc); + +return err; +} + +static int +restore_sigcontext (CPUState *env,struct target_sigcontext *sc,int *pd0) +{ +int err =0 ; +int temp; + + err |=__get_user (env->aregs[7 ], &sc->sc_usp); + err |=__get_user (env->dregs[1 ], &sc->sc_d1); + err |=__get_user (env->aregs[0 ], &sc->sc_a0); + err |=__get_user (env->aregs[1 ], &sc->sc_a1); + err |=__get_user (env->pc, &sc->sc_pc); + err |=__get_user (temp, &sc->sc_sr); + env->sr = (env->sr &0xff00 ) | (temp &0xff ); + + *pd0 =tswapl (sc->sc_d0); + +return err; +} + +/* +* Determine which stack to use.. +*/ +static inline abi_ulong +get_sigframe (struct target_sigaction *ka,CPUState *regs,size_t frame_size) +{ +unsigned long sp; + + sp = regs->aregs[7 ]; + +/* This is the X/Open sanctioned signal stack switching. */ +if ((ka->sa_flags &TARGET_SA_ONSTACK ) && (sas_ss_flags (sp) ==0 )) { + sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; + } + +return ((sp - frame_size) &-8UL ); +} + +static void setup_frame (int sig,struct target_sigaction *ka, +target_sigset_t *set,CPUState *env) +{ +struct target_sigframe *frame; +abi_ulong frame_addr; +abi_ulong retcode_addr; +abi_ulong sc_addr; +int err =0 ; +int i; + + frame_addr =get_sigframe (ka, env,sizeof *frame); +if (!lock_user_struct (VERIFY_WRITE , frame, frame_addr,0 )) + goto give_sigsegv; + + err |=__put_user (sig, &frame->sig); + + sc_addr = frame_addr + offsetof(struct target_sigframe , sc); + err |=__put_user (sc_addr, &frame->psc); + + err |=setup_sigcontext (&frame->sc, env, set->sig[0 ]); +if (err) + goto give_sigsegv; + +for (i =1 ; i <TARGET_NSIG_WORDS ; i++) { +if (__put_user (set->sig[i], &frame->extramask[i -1 ])) + goto give_sigsegv; + } + +/* Set up to return from userspace. */ + + retcode_addr = frame_addr + offsetof(struct target_sigframe , retcode); + err |=__put_user (retcode_addr, &frame->pretcode); + +/* moveq #,d0; trap #0 */ + + err |=__put_user (0x70004e40 + (TARGET_NR_sigreturn <<16 ), + (long *)(frame->retcode)); + +if (err) + goto give_sigsegv; + +/* Set up to return from userspace */ + + env->aregs[7 ] = frame_addr; + env->pc = ka->_sa_handler; + +unlock_user_struct (frame, frame_addr,1 ); +return ; + +give_sigsegv: +unlock_user_struct (frame, frame_addr,1 ); +force_sig (SIGSEGV ); +} + +static void setup_rt_frame (int sig,struct target_sigaction *ka, +target_siginfo_t *info, +target_sigset_t *set,CPUState *env) +{ +fprintf (stderr,"setup_rt_frame: not implemented\n" ); +} + +long do_sigreturn (CPUState *env) +{ +struct target_sigframe *frame; +abi_ulong frame_addr = env->aregs[7 ] -4 ; +target_sigset_t target_set; +sigset_t set; +int d0, i; + +if (!lock_user_struct (VERIFY_READ , frame, frame_addr,1 )) + goto badframe; + +/* set blocked signals */ + +if (__get_user (target_set.sig[0 ], &frame->sc.sc_mask)) + goto badframe; + +for (i =1 ; i <TARGET_NSIG_WORDS ; i++) { +if (__get_user (target_set.sig[i], &frame->extramask[i -1 ])) + goto badframe; + } + +target_to_host_sigset_internal (&set, &target_set); +sigprocmask (SIG_SETMASK , &set,NULL ); + +/* restore registers */ + +if (restore_sigcontext (env, &frame->sc, &d0)) + goto badframe; + +unlock_user_struct (frame, frame_addr,0 ); +return d0; + +badframe: +unlock_user_struct (frame, frame_addr,0 ); +force_sig (TARGET_SIGSEGV ); +return 0 ; +} + +long do_rt_sigreturn (CPUState *env) +{ +fprintf (stderr,"do_rt_sigreturn: not implemented\n" ); +return -TARGET_ENOSYS ; +} +#else static void setup_frame(int sig, struct target_sigaction *ka,
Signature · 1 line
1.6.2.1
PATCH 3/11 m68k, linux-user: add setup_rt_frame
In reply to [email protected]From: Laurent Vivier <[email protected]>
This patch implements setup_rt_frame().
--- linux-user/signal.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 202 insertions(+), 3 deletions(-)
linux-user/signal.c +202 -3
@@ -4051,6 +4051,43 @@ struct target_sigframeabi_ulong extramask[TARGET_NSIG_WORDS -1 ];struct target_sigcontext sc; }; + +typedef int target_greg_t ; +#define TARGET_NGREG 18 +typedef target_greg_t target_gregset_t [TARGET_NGREG ]; + +typedef struct target_fpregset { +int f_fpcntl[3 ]; +int f_fpregs[8 *3 ]; +}target_fpregset_t ; + +struct target_mcontext { +int version; +target_gregset_t gregs; +target_fpregset_t fpregs; +}; + +#define TARGET_MCONTEXT_VERSION 2 + +struct target_ucontext { +abi_ulong uc_flags; +abi_ulong uc_link; +target_stack_t uc_stack; +struct target_mcontext uc_mcontext; +abi_long uc_filler[80 ]; +target_sigset_t uc_sigmask; +}; + +struct target_rt_sigframe +{ +abi_ulong pretcode; +int sig; +abi_ulong pinfo; +abi_ulong puc; +char retcode[8 ]; +struct target_siginfo info; +struct target_ucontext uc; +};static int setup_sigcontext (struct target_sigcontext *sc,CPUState *env,abi_ulong mask)
@@ -4160,11 +4197,146 @@ give_sigsegv:force_sig (SIGSEGV ); } +static inline int target_rt_setup_ucontext (struct target_ucontext *uc, +CPUState *env) +{ +target_greg_t *gregs = uc->uc_mcontext.gregs; +int err; + + err =__put_user (TARGET_MCONTEXT_VERSION , &uc->uc_mcontext.version); + err |=__put_user (env->dregs[0 ], &gregs[0 ]); + err |=__put_user (env->dregs[1 ], &gregs[1 ]); + err |=__put_user (env->dregs[2 ], &gregs[2 ]); + err |=__put_user (env->dregs[3 ], &gregs[3 ]); + err |=__put_user (env->dregs[4 ], &gregs[4 ]); + err |=__put_user (env->dregs[5 ], &gregs[5 ]); + err |=__put_user (env->dregs[6 ], &gregs[6 ]); + err |=__put_user (env->dregs[7 ], &gregs[7 ]); + err |=__put_user (env->aregs[0 ], &gregs[8 ]); + err |=__put_user (env->aregs[1 ], &gregs[9 ]); + err |=__put_user (env->aregs[2 ], &gregs[10 ]); + err |=__put_user (env->aregs[3 ], &gregs[11 ]); + err |=__put_user (env->aregs[4 ], &gregs[12 ]); + err |=__put_user (env->aregs[5 ], &gregs[13 ]); + err |=__put_user (env->aregs[6 ], &gregs[14 ]); + err |=__put_user (env->aregs[7 ], &gregs[15 ]); + err |=__put_user (env->pc, &gregs[16 ]); + err |=__put_user (env->sr, &gregs[17 ]); + +return err; +} + +static inline int target_rt_restore_ucontext (CPUState *env, +struct target_ucontext *uc, +int *pd0) +{ +int temp; +int err; +target_greg_t *gregs = uc->uc_mcontext.gregs; + + err =__get_user (temp, &uc->uc_mcontext.version); +if (temp !=TARGET_MCONTEXT_VERSION ) + goto badframe; + +/* restore passed registers */ + err |=__get_user (env->dregs[0 ], &gregs[0 ]); + err |=__get_user (env->dregs[1 ], &gregs[1 ]); + err |=__get_user (env->dregs[2 ], &gregs[2 ]); + err |=__get_user (env->dregs[3 ], &gregs[3 ]); + err |=__get_user (env->dregs[4 ], &gregs[4 ]); + err |=__get_user (env->dregs[5 ], &gregs[5 ]); + err |=__get_user (env->dregs[6 ], &gregs[6 ]); + err |=__get_user (env->dregs[7 ], &gregs[7 ]); + err |=__get_user (env->aregs[0 ], &gregs[8 ]); + err |=__get_user (env->aregs[1 ], &gregs[9 ]); + err |=__get_user (env->aregs[2 ], &gregs[10 ]); + err |=__get_user (env->aregs[3 ], &gregs[11 ]); + err |=__get_user (env->aregs[4 ], &gregs[12 ]); + err |=__get_user (env->aregs[5 ], &gregs[13 ]); + err |=__get_user (env->aregs[6 ], &gregs[14 ]); + err |=__get_user (env->aregs[7 ], &gregs[15 ]); + err |=__get_user (env->pc, &gregs[16 ]); + err |=__get_user (temp, &gregs[17 ]); + env->sr = (env->sr &0xff00 ) | (temp &0xff ); + + *pd0 = env->dregs[0 ]; +return err; + +badframe: +return 1 ; +} +static void setup_rt_frame (int sig,struct target_sigaction *ka,target_siginfo_t *info,target_sigset_t *set,CPUState *env) { -fprintf (stderr,"setup_rt_frame: not implemented\n" ); +struct target_rt_sigframe *frame; +abi_ulong frame_addr; +abi_ulong retcode_addr; +abi_ulong info_addr; +abi_ulong uc_addr; +int err =0 ; +int i; + + frame_addr =get_sigframe (ka, env,sizeof *frame); +if (!lock_user_struct (VERIFY_WRITE , frame, frame_addr,0 )) + goto give_sigsegv; + + err |=__put_user (sig, &frame->sig); + + info_addr = frame_addr + offsetof(struct target_rt_sigframe , info); + err |=__put_user (info_addr, &frame->pinfo); + + uc_addr = frame_addr + offsetof(struct target_rt_sigframe , uc); + err |=__put_user (uc_addr, &frame->puc); + + err |=copy_siginfo_to_user (&frame->info, info); + +/* Create the ucontext */ + + err |=__put_user (0 , &frame->uc.uc_flags); + err |=__put_user (0 , &frame->uc.uc_link); + err |=__put_user (target_sigaltstack_used.ss_sp, + &frame->uc.uc_stack.ss_sp); + err |=__put_user (sas_ss_flags (env->aregs[7 ]), + &frame->uc.uc_stack.ss_flags); + err |=__put_user (target_sigaltstack_used.ss_size, + &frame->uc.uc_stack.ss_size); + err |=target_rt_setup_ucontext (&frame->uc, env); + +if (err) + goto give_sigsegv; + +for (i =0 ; i <TARGET_NSIG_WORDS ; i++) { +if (__put_user (set->sig[i], &frame->uc.uc_sigmask.sig[i])) + goto give_sigsegv; + } + +/* Set up to return from userspace. */ + + retcode_addr = frame_addr + offsetof(struct target_sigframe , retcode); + err |=__put_user (retcode_addr, &frame->pretcode); + +/* moveq #,d0; notb d0; trap #0 */ + + err |=__put_user (0x70004600 + ((TARGET_NR_rt_sigreturn ^0xff ) <<16 ), + (long *)(frame->retcode +0 )); + err |=__put_user (0x4e40 , (short *)(frame->retcode +4 )); + +if (err) + goto give_sigsegv; + +/* Set up to return from userspace */ + + env->aregs[7 ] = frame_addr; + env->pc = ka->_sa_handler; + +unlock_user_struct (frame, frame_addr,1 ); +return ; + +give_sigsegv: +unlock_user_struct (frame, frame_addr,1 ); +force_sig (SIGSEGV ); }long do_sigreturn (CPUState *env)
@@ -4207,8 +4379,35 @@ badframe:long do_rt_sigreturn (CPUState *env) { -fprintf (stderr,"do_rt_sigreturn: not implemented\n" ); -return -TARGET_ENOSYS ; +struct target_rt_sigframe *frame; +abi_ulong frame_addr = env->aregs[7 ] -4 ; +target_sigset_t target_set; +sigset_t set; +int d0; + +if (!lock_user_struct (VERIFY_READ , frame, frame_addr,1 )) + goto badframe; + +target_to_host_sigset_internal (&set, &target_set); +sigprocmask (SIG_SETMASK , &set,NULL ); + +/* restore registers */ + +if (target_rt_restore_ucontext (env, &frame->uc, &d0)) + goto badframe; + +if (do_sigaltstack (frame_addr + + offsetof(struct target_rt_sigframe, uc.uc_stack), + 0, get_sp_from_cpustate(env)) == -EFAULT) + goto badframe; + +unlock_user_struct (frame, frame_addr,0 ); +return d0; + +badframe: +unlock_user_struct (frame, frame_addr,0 ); +force_sig (TARGET_SIGSEGV ); +return 0 ; }#else
Signature · 1 line
1.6.2.1
PATCH 4/11 m68k, linux-user: enable sigaltstack()
In reply to [email protected]From: Laurent Vivier <[email protected]>
As setup_frame() and setup_rt_frame() are now implemented we can now enable sigaltstack().
--- linux-user/syscall.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
linux-user/syscall.c +2 -1
@@ -6108,7 +6108,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto unimplemented;case TARGET_NR_sigaltstack:#if defined(TARGET_I386 ) || defined(TARGET_ARM ) || defined(TARGET_MIPS ) || \ - defined(TARGET_SPARC ) || defined(TARGET_PPC ) || defined(TARGET_ALPHA ) + defined(TARGET_SPARC ) || defined(TARGET_PPC ) || defined(TARGET_ALPHA ) || \ + defined(TARGET_M68K ) ret =do_sigaltstack (arg1, arg2,get_sp_from_cpustate ((CPUState *)cpu_env));break ;#else
Signature · 1 line
1.6.2.1
PATCH 5/11 linux-user: fix mq_* compilation problems
In reply to [email protected]From: Nathan Froyd <[email protected]>
mqueue.h is only available if __NR_mq_open is defined. So don't include it unconditionally. Similarly, the mq_* family of syscalls depend on __NR_mq_open. Finally, the copy_{from,to}_user_mq_attr functions should not be defined unconditionally, but only if we're going to use the mq_* syscalls.
--- linux-user/syscall.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
linux-user/syscall.c +5 -2
@@ -28,7 +28,6 @@#include <fcntl.h> #include <time.h> #include <limits.h> -#include <mqueue.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
@@ -847,6 +846,9 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,return 0 ; } +#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) +#include <mqueue.h> +static inline abi_long copy_from_user_mq_attr (struct mq_attr *attr,abi_ulong target_mq_attr_addr) {
@@ -884,6 +886,7 @@ static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,return 0 ; } +#endif /* do_select() must return target values and target errnos. */ static abi_long do_select(int n,
@@ -6860,7 +6863,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,break ;#endif -#ifdef TARGET_NR_mq_open +#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)case TARGET_NR_mq_open: {struct mq_attr posix_mq_attr;
Signature · 1 line
1.6.2.1
PATCH 6/11 linux-user: fcntl fixes for LTP
In reply to [email protected]From: Ulrich Hecht <[email protected]>
Fixes swaps on l_pid which were pretty much of random size. Implements F_SETLEASE, F_GETLEASE. Now passes all LTP fcntl tests.
--- linux-user/syscall.c | 34 ++++++++++++++++++++++------------ linux-user/syscall_defs.h | 7 +++++++ 2 files changed, 29 insertions(+), 12 deletions(-)
linux-user/syscall.c +22 -12
@@ -3680,6 +3680,14 @@ static int target_to_host_fcntl_cmd(int cmd)case TARGET_F_SETLKW64 :return F_SETLKW64 ;#endif +case TARGET_F_SETLEASE : +return F_SETLEASE ; +case TARGET_F_GETLEASE : +return F_GETLEASE ; +case TARGET_F_DUPFD_CLOEXEC : +return F_DUPFD_CLOEXEC ; +case TARGET_F_NOTIFY : +return F_NOTIFY ;default :return -TARGET_EINVAL ; }
@@ -3706,7 +3714,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) fl.l_whence =tswap16 (target_fl->l_whence); fl.l_start =tswapl (target_fl->l_start); fl.l_len =tswapl (target_fl->l_len); - fl.l_pid =tswapl (target_fl->l_pid); + fl.l_pid =tswap32 (target_fl->l_pid);unlock_user_struct (target_fl, arg,0 ); ret =get_errno (fcntl (fd, host_cmd, &fl));if (ret ==0 ) {
@@ -3716,7 +3724,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) target_fl->l_whence =tswap16 (fl.l_whence); target_fl->l_start =tswapl (fl.l_start); target_fl->l_len =tswapl (fl.l_len); - target_fl->l_pid =tswapl (fl.l_pid); + target_fl->l_pid =tswap32 (fl.l_pid);unlock_user_struct (target_fl, arg,1 ); }break ;
@@ -3729,7 +3737,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) fl.l_whence =tswap16 (target_fl->l_whence); fl.l_start =tswapl (target_fl->l_start); fl.l_len =tswapl (target_fl->l_len); - fl.l_pid =tswapl (target_fl->l_pid); + fl.l_pid =tswap32 (target_fl->l_pid);unlock_user_struct (target_fl, arg,0 ); ret =get_errno (fcntl (fd, host_cmd, &fl));break ;
@@ -3741,7 +3749,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) fl64.l_whence =tswap16 (target_fl64->l_whence); fl64.l_start =tswapl (target_fl64->l_start); fl64.l_len =tswapl (target_fl64->l_len); - fl64.l_pid =tswap16 (target_fl64->l_pid); + fl64.l_pid =tswap32 (target_fl64->l_pid);unlock_user_struct (target_fl64, arg,0 ); ret =get_errno (fcntl (fd, host_cmd, &fl64));if (ret ==0 ) {
@@ -3751,7 +3759,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) target_fl64->l_whence =tswap16 (fl64.l_whence); target_fl64->l_start =tswapl (fl64.l_start); target_fl64->l_len =tswapl (fl64.l_len); - target_fl64->l_pid =tswapl (fl64.l_pid); + target_fl64->l_pid =tswap32 (fl64.l_pid);unlock_user_struct (target_fl64, arg,1 ); }break ;
@@ -3763,7 +3771,7 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) fl64.l_whence =tswap16 (target_fl64->l_whence); fl64.l_start =tswapl (target_fl64->l_start); fl64.l_len =tswapl (target_fl64->l_len); - fl64.l_pid =tswap16 (target_fl64->l_pid); + fl64.l_pid =tswap32 (target_fl64->l_pid);unlock_user_struct (target_fl64, arg,0 ); ret =get_errno (fcntl (fd, host_cmd, &fl64));break ;
@@ -3783,6 +3791,8 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)case TARGET_F_GETOWN :case TARGET_F_SETSIG :case TARGET_F_GETSIG : +case TARGET_F_SETLEASE : +case TARGET_F_GETLEASE : ret =get_errno (fcntl (fd, host_cmd, arg));break ;
@@ -6599,7 +6609,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, fl.l_whence =tswap16 (target_efl->l_whence); fl.l_start =tswap64 (target_efl->l_start); fl.l_len =tswap64 (target_efl->l_len); - fl.l_pid =tswapl (target_efl->l_pid); + fl.l_pid =tswap32 (target_efl->l_pid);unlock_user_struct (target_efl, arg3,0 ); } else#endif
@@ -6610,7 +6620,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, fl.l_whence =tswap16 (target_fl->l_whence); fl.l_start =tswap64 (target_fl->l_start); fl.l_len =tswap64 (target_fl->l_len); - fl.l_pid =tswapl (target_fl->l_pid); + fl.l_pid =tswap32 (target_fl->l_pid);unlock_user_struct (target_fl, arg3,0 ); } ret =get_errno (fcntl (arg1, cmd, &fl));
@@ -6623,7 +6633,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, target_efl->l_whence =tswap16 (fl.l_whence); target_efl->l_start =tswap64 (fl.l_start); target_efl->l_len =tswap64 (fl.l_len); - target_efl->l_pid =tswapl (fl.l_pid); + target_efl->l_pid =tswap32 (fl.l_pid);unlock_user_struct (target_efl, arg3,1 ); } else#endif
@@ -6634,7 +6644,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, target_fl->l_whence =tswap16 (fl.l_whence); target_fl->l_start =tswap64 (fl.l_start); target_fl->l_len =tswap64 (fl.l_len); - target_fl->l_pid =tswapl (fl.l_pid); + target_fl->l_pid =tswap32 (fl.l_pid);unlock_user_struct (target_fl, arg3,1 ); } }
@@ -6650,7 +6660,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, fl.l_whence =tswap16 (target_efl->l_whence); fl.l_start =tswap64 (target_efl->l_start); fl.l_len =tswap64 (target_efl->l_len); - fl.l_pid =tswapl (target_efl->l_pid); + fl.l_pid =tswap32 (target_efl->l_pid);unlock_user_struct (target_efl, arg3,0 ); } else#endif
@@ -6661,7 +6671,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, fl.l_whence =tswap16 (target_fl->l_whence); fl.l_start =tswap64 (target_fl->l_start); fl.l_len =tswap64 (target_fl->l_len); - fl.l_pid =tswapl (target_fl->l_pid); + fl.l_pid =tswap32 (target_fl->l_pid);unlock_user_struct (target_fl, arg3,0 ); } ret =get_errno (fcntl (arg1, cmd, &fl));
linux-user/syscall_defs.h +7 -0
@@ -1772,6 +1772,13 @@ struct target_statfs64 {#define TARGET_F_SETLK64 13#define TARGET_F_SETLKW64 14#endif + +#define TARGET_F_LINUX_SPECIFIC_BASE 1024 +#define TARGET_F_SETLEASE (TARGET_F_LINUX_SPECIFIC_BASE + 0) +#define TARGET_F_GETLEASE (TARGET_F_LINUX_SPECIFIC_BASE + 1) +#define TARGET_F_DUPFD_CLOEXEC (TARGET_F_LINUX_SPECIFIC_BASE + 6) +#define TARGET_F_NOTIFY (TARGET_F_LINUX_SPECIFIC_BASE+2) +#if defined (TARGET_ARM )#define TARGET_O_ACCMODE 0003#define TARGET_O_RDONLY 00
Signature · 1 line
1.6.2.1
PATCH 7/11 linux-user: enable getdents for > 32-bit systems
In reply to [email protected]From: Ulrich Hecht <[email protected]>
works perfectly fine with the example from getdents(2) and passes the LTP tests (tested with s390x on x86_64 emulation)
--- linux-user/syscall.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-)
linux-user/syscall.c +1 -5
@@ -193,9 +193,7 @@ static int gettid(void) {return -ENOSYS ; }#endif -#if TARGET_ABI_BITS ==32 _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); -#endif #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);#endif
@@ -5792,9 +5790,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,break ;#endif case TARGET_NR_getdents: -#if TARGET_ABI_BITS !=32 - goto unimplemented; -#elif TARGET_ABI_BITS ==32 &&HOST_LONG_BITS ==64 +#if TARGET_ABI_BITS ==32 &&HOST_LONG_BITS ==64 {struct target_dirent *target_dirp;struct linux_dirent *dirp;
Signature · 1 line
1.6.2.1
PATCH 8/11 linux-user: define a couple of syscalls for non-uid16 targets
In reply to [email protected]From: Ulrich Hecht <[email protected]>
Quite a number of syscalls are only defined on systems with USE_UID16 defined; this patch defines them on other systems as well.
Fixes a large number of uid/gid-related testcases on the s390x target (and most likely on other targets as well)
--- linux-user/syscall.c | 125 ++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 105 insertions(+), 20 deletions(-)
linux-user/syscall.c +105 -20
@@ -304,7 +304,7 @@ static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)return (fchmodat (dirfd, pathname, mode,0 )); }#endif -#if defined(TARGET_NR_fchownat) && defined(USE_UID16 ) +#if defined(TARGET_NR_fchownat)static int sys_fchownat (int dirfd,const char *pathname,uid_t owner,gid_t group,int flags) {
@@ -413,7 +413,7 @@ _syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat) _syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)#endif -#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16 ) +#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, uid_t,owner,gid_t,group,int,flags)#endif
@@ -6351,18 +6351,35 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,case TARGET_NR_setfsgid: ret =get_errno (setfsgid (arg1));break ; +#else /* USE_UID16 */ +#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) +case TARGET_NR_fchownat: +if (!(p =lock_user_string (arg2))) + goto efault; + ret =get_errno (sys_fchownat (arg1, p, arg3, arg4, arg5)); +unlock_user (p, arg2,0 ); +break ; +#endif #endif /* USE_UID16 */ -#ifdef TARGET_NR_lchown32 +#if defined(TARGET_NR_lchown32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_lchown32)case TARGET_NR_lchown32: +#else +case TARGET_NR_lchown: +#endif if (!(p =lock_user_string (arg1))) goto efault; ret =get_errno (lchown (p, arg2, arg3));unlock_user (p, arg1,0 );break ;#endif -#ifdef TARGET_NR_getuid32 +#if defined(TARGET_NR_getuid32) || (defined(TARGET_NR_getuid) && !defined(USE_UID16 )) +#if defined(TARGET_NR_getuid32)case TARGET_NR_getuid32: +#else +case TARGET_NR_getuid: +#endif ret =get_errno (getuid ());break ;#endif
@@ -6390,33 +6407,57 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,break ;#endif -#ifdef TARGET_NR_getgid32 +#if defined(TARGET_NR_getgid32) || (defined(TARGET_NR_getgid) && !defined(USE_UID16 )) +#if defined(TARGET_NR_getgid32)case TARGET_NR_getgid32: +#else +case TARGET_NR_getgid: +#endif ret =get_errno (getgid ());break ;#endif -#ifdef TARGET_NR_geteuid32 +#if defined(TARGET_NR_geteuid32) || (defined(TARGET_NR_geteuid) && !defined(USE_UID16 )) +#if defined(TARGET_NR_geteuid32)case TARGET_NR_geteuid32: +#else +case TARGET_NR_geteuid: +#endif ret =get_errno (geteuid ());break ;#endif -#ifdef TARGET_NR_getegid32 +#if defined(TARGET_NR_getegid32) || (defined(TARGET_NR_getegid) && !defined(USE_UID16 )) +#if defined(TARGET_NR_getegid32)case TARGET_NR_getegid32: +#else +case TARGET_NR_getegid: +#endif ret =get_errno (getegid ());break ;#endif -#ifdef TARGET_NR_setreuid32 +#if defined(TARGET_NR_setreuid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setreuid32)case TARGET_NR_setreuid32: +#else +case TARGET_NR_setreuid: +#endif ret =get_errno (setreuid (arg1, arg2));break ;#endif -#ifdef TARGET_NR_setregid32 +#if defined(TARGET_NR_setregid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setregid32)case TARGET_NR_setregid32: +#else +case TARGET_NR_setregid: +#endif ret =get_errno (setregid (arg1, arg2));break ;#endif -#ifdef TARGET_NR_getgroups32 +#if defined(TARGET_NR_getgroups32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_getgroups32)case TARGET_NR_getgroups32: +#else +case TARGET_NR_getgroups: +#endif {int gidsetsize = arg1;uint32_t *target_grouplist;
@@ -6440,8 +6481,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, }break ;#endif -#ifdef TARGET_NR_setgroups32 +#if defined(TARGET_NR_setgroups32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setgroups32)case TARGET_NR_setgroups32: +#else +case TARGET_NR_setgroups: +#endif {int gidsetsize = arg1;uint32_t *target_grouplist;
@@ -6461,18 +6506,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, }break ;#endif -#ifdef TARGET_NR_fchown32 +#if defined(TARGET_NR_fchown32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_fchown32)case TARGET_NR_fchown32: +#else +case TARGET_NR_fchown: +#endif ret =get_errno (fchown (arg1, arg2, arg3));break ;#endif -#ifdef TARGET_NR_setresuid32 +#if defined(TARGET_NR_setresuid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setresuid32)case TARGET_NR_setresuid32: +#else +case TARGET_NR_setresuid: +#endif ret =get_errno (setresuid (arg1, arg2, arg3));break ;#endif -#ifdef TARGET_NR_getresuid32 +#if defined(TARGET_NR_getresuid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_getresuid32)case TARGET_NR_getresuid32: +#else +case TARGET_NR_getresuid: +#endif {uid_t ruid, euid, suid; ret =get_errno (getresuid (&ruid, &euid, &suid));
@@ -6485,13 +6542,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, }break ;#endif -#ifdef TARGET_NR_setresgid32 +#if defined(TARGET_NR_setresgid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setresgid32)case TARGET_NR_setresgid32: +#else +case TARGET_NR_setresgid: +#endif ret =get_errno (setresgid (arg1, arg2, arg3));break ;#endif +#if defined(TARGET_NR_getresgid32) || !defined(USE_UID16 )#ifdef TARGET_NR_getresgid32case TARGET_NR_getresgid32: +#else +case TARGET_NR_getresgid: +#endif {gid_t rgid, egid, sgid; ret =get_errno (getresgid (&rgid, &egid, &sgid));
@@ -6504,31 +6569,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, }break ;#endif -#ifdef TARGET_NR_chown32 +#if defined(TARGET_NR_chown32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_chown32)case TARGET_NR_chown32: +#else +case TARGET_NR_chown: +#endif if (!(p =lock_user_string (arg1))) goto efault; ret =get_errno (chown (p, arg2, arg3));unlock_user (p, arg1,0 );break ;#endif -#ifdef TARGET_NR_setuid32 +#if defined(TARGET_NR_setuid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setuid32)case TARGET_NR_setuid32: +#else +case TARGET_NR_setuid: +#endif ret =get_errno (setuid (arg1));break ;#endif -#ifdef TARGET_NR_setgid32 +#if defined(TARGET_NR_setgid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setgid32)case TARGET_NR_setgid32: +#else +case TARGET_NR_setgid: +#endif ret =get_errno (setgid (arg1));break ;#endif -#ifdef TARGET_NR_setfsuid32 +#if defined(TARGET_NR_setfsuid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setfsuid32)case TARGET_NR_setfsuid32: +#else +case TARGET_NR_setfsuid: +#endif ret =get_errno (setfsuid (arg1));break ;#endif -#ifdef TARGET_NR_setfsgid32 +#if defined(TARGET_NR_setfsgid32) || !defined(USE_UID16 ) +#if defined(TARGET_NR_setfsgid32)case TARGET_NR_setfsgid32: +#else +case TARGET_NR_setfsgid: +#endif ret =get_errno (setfsgid (arg1));break ;#endif
Signature · 1 line
1.6.2.1
PATCH 9/11 linux-user: fadvise64 implementation
In reply to [email protected]From: Ulrich Hecht <[email protected]>
good enough to pass all LTP fadvise64 tests
--- linux-user/syscall.c | 17 ++++++++++++++--- 1 files changed, 14 insertions(+), 3 deletions(-)
linux-user/syscall.c +14 -3
@@ -6649,12 +6649,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, arg4 = temp; }#endif -#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) +#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64)#ifdef TARGET_NR_fadvise64_64case TARGET_NR_fadvise64_64:#endif -/* This is a hint, so ignoring and returning success is ok. */ - ret =get_errno (0 ); +#ifdef TARGET_NR_fadvise64 +case TARGET_NR_fadvise64: +#endif +#ifdef TARGET_S390X +switch (arg4) { +case 4 : arg4 =POSIX_FADV_NOREUSE +1 ;break ;/* make sure it's an invalid value */ +case 5 : arg4 =POSIX_FADV_NOREUSE +2 ;break ;/* ditto */ +case 6 : arg4 =POSIX_FADV_DONTNEED ;break ; +case 7 : arg4 =POSIX_FADV_NOREUSE ;break ; +default :break ; + } +#endif + ret = -posix_fadvise (arg1, arg2, arg3, arg4);break ;#endif #ifdef TARGET_NR_madvise
Signature · 1 line
1.6.2.1
PATCH 10/11 linux-user: zero fstat buffer to initialize nsec fields
In reply to [email protected]From: Ulrich Hecht <[email protected]>
The fstat implementation does not initialize the nanosecond fields in the stat buffer; this caused funny values to turn up there, preventing, for instance, cp -p from preserving timestamps because utimensat rejected the out-of-bounds nanosecond values. Resetting the entire structure to zero fixes that.
--- linux-user/syscall.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
linux-user/syscall.c +1 -0
@@ -5526,6 +5526,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,if (!lock_user_struct (VERIFY_WRITE , target_st, arg2,0 )) goto efault; +memset (target_st,0 ,sizeof (*target_st));__put_user (st.st_dev, &target_st->st_dev);__put_user (st.st_ino, &target_st->st_ino);__put_user (st.st_mode, &target_st->st_mode);
Signature · 1 line
1.6.2.1
PATCH 11/11 linux-user: Rewrite mmap_find_vma() to work fine on 64-bit hosts with 32-bit targets
In reply to [email protected]From: Kirill A. Shutemov <[email protected]>
qemu's page table can be incomple if /proc/self/maps is unavailable or host allocating a memory with mmap(), so we can't use it to find free memory area.
New version mmap_find_vma() uses mmap() without MAP_FIXED to find free memory.
quite some time ago this patch had been sent by Kirill to the QEMU ml. At that time, the patch was rejected. Now we found out why the current user mode memory allocator sometimes fails:
- Kernel Bug linux/fs/proc/task_mmu.c (fixed after 2.6.27)
http://bugzilla.kernel.org/attachment.cgi?id=17219
- use of proc file system to find memory mappings => bad idea
So I please apply the attached patch from Kirill to qemu to fix this longstanding bug, because it causes all older linux distros (using kernel 2.6.26 or older) to fail the QEMU memory allocator in user mode.
--- linux-user/mmap.c | 79 +++++++++++++++++++++++++++++------------------------ 1 files changed, 43 insertions(+), 36 deletions(-)
linux-user/mmap.c +43 -36
@@ -273,52 +273,59 @@ static abi_ulong mmap_next_start = 0x40000000;unsigned long last_brk; -/* find a free memory area of size 'size'. The search starts at -'start'. If 'start' == 0, then a default start address is used. -Return -1 if error. -*/ -/* page_init() marks pages used by the host as reserved to be sure not -to use them. */ +/* +* Find and reserve a free memory area of size 'size'. The search +* starts at 'start'. +* It must be called with mmap_lock() held. +* Return -1 if error. +*/ abi_ulong mmap_find_vma (abi_ulong start,abi_ulong size) { -abi_ulong addr, addr1, addr_start; -int prot; -unsigned long new_brk; - - new_brk = (unsigned long )sbrk (0 ); -if (last_brk && last_brk < new_brk && last_brk == (target_ulong )last_brk) { -/* This is a hack to catch the host allocating memory with brk(). -If it uses mmap then we loose. -FIXME: We really want to avoid the host allocating memory in -the first place, and maybe leave some slack to avoid switching -to mmap. */ -page_set_flags (last_brk &TARGET_PAGE_MASK , -TARGET_PAGE_ALIGN (new_brk), -PAGE_RESERVED ); - } - last_brk = new_brk; +void *ptr; +abi_ulong addr; size =HOST_PAGE_ALIGN (size); - start = start & qemu_host_page_mask; + start &= qemu_host_page_mask; + +/* If 'start' == 0, then a default start address is used. */ +if (start ==0 ) + start = mmap_next_start; + addr = start; -if (addr ==0 ) - addr = mmap_next_start; - addr_start = addr; +for (;;) { - prot =0 ; -for (addr1 = addr; addr1 < (addr + size); addr1 +=TARGET_PAGE_SIZE ) { - prot |=page_get_flags (addr1); - } -if (prot ==0 ) +/* +* Reserve needed memory area to avoid a race. +* It should be discarded using: +* - mmap() with MAP_FIXED flag +* - mremap() with MREMAP_FIXED flag +* - shmat() with SHM_REMAP flag +*/ + ptr =mmap ((void *)(unsigned long )addr, size,PROT_NONE , +MAP_ANONYMOUS |MAP_PRIVATE |MAP_NORESERVE ,-1 ,0 ); + +/* ENOMEM, if host address space has no memory */ +if (ptr ==MAP_FAILED ) +return (abi_ulong)-1 ; + +/* If address fits target address space we've found what we need */ +if ((unsigned long )ptr + size -1 <= (abi_ulong)-1 )break ; + +/* Unmap and try again with new page */ +munmap (ptr, size); addr += qemu_host_page_size; -/* we found nothing */ -if (addr == addr_start) + +/* ENOMEM if we check whole of target address space */ +if (addr == start)return (abi_ulong)-1 ; } -if (start ==0 ) - mmap_next_start = addr + size; -return addr; + +/* Update default start address */ +if (start == mmap_next_start) + mmap_next_start = (unsigned long )ptr + size; + +return h2g (ptr); }/* NOTE: all the constants are the HOST ones */
Signature · 1 line
1.6.2.1