Re: [Qemu-devel] re: Nothing happens

2005-06-16 Thread Thayne Harbaugh
On Thu, 2005-06-16 at 17:36 +0100, Paul Brook wrote:
  I first just tried without the SDL-devel libs, but that was the same,
  and the above mentioned thread suggested that SDL may be a cause
  (although I suspect we may be talking of different problems).
 
 Did you actually do a clean build after installing sdl-devel? You need to 
 either delete your build directory or do make clean before rebuilding. 
 Otherwise qemu will reuse the old (output disabled) object files.

Don't forget that configure needs to be re-run so that SDL can be
re-detected.




___
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel


[Qemu-devel] arm-linux-user infinite SIGSEGV looping

2007-08-24 Thread Thayne Harbaugh
I've encountered what appears to be a race condition in arm-linux-user:
sometimes the program qemu is running will hang forever and sometimes it
will complete.  After digging about there appears to be at least two
problems:

1) An initial cause of a SIGSEGV

2) The incorrect handling of the SIGSEGV

When #2 happens the symptom is an infinite loop in handling the SIGSEGV.
Using GDB I've stepped through the signal handling and have cause to
question a section of code that I would appreciate comments on.  The
target-specific cpu-exec.c:handle_cpu_signal() appears to have a
different logical flow for arm than all other architectures and I wonder
if it is incorrectly implemented.

All architecture versions of handle_cpu_signal() will do one of four
things:

1) return 0 or 1 at the start for certain conditions

2) not return by calling (do_)raise_exception_err() which eventually
calls cpu_loop_exit()

3) not return by calling cpu_resume_from_signal() which eventually calls
longjmp()

4) call cpu_loop_exit() directly (which eventually calls longjmp())

After these various code paths there's usually a comment that says
never comes here.

The arm target is an exception to the above outline.
raise_exception_err() has been comment disabled and the cpu_loop_exit()
is incorrectly indented giving a false impression that it will always be
called at the end of the function.  I'm hypothesizing that for arm
handle_cpu_signal() incorrectly returns and doesn't break an infinite
loop.

Please comment!

Below is the questionable handle_cpu_signal():

static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
TranslationBlock *tb;
int ret;

if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
printf(qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n, 
   pc, address, is_write, *(unsigned long *)old_set);
#endif
/* XXX: locking issue */
if (is_write  page_unprotect(h2g(address), pc, puc)) {
return 1;
}
/* see if it is an MMU fault */
ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
if (ret  0)
return 0; /* not an MMU fault */
if (ret == 0)
return 1; /* the MMU fault was handled without causing real CPU fault */
/* now we have a real cpu fault */
tb = tb_find_pc(pc);
if (tb) {
/* the PC is inside the translated code. It means that we have
   a virtual CPU fault */
cpu_restore_state(tb, env, pc, puc);
}
if( ret == 1 ) {
sigprocmask(SIG_SETMASK, old_set, NULL);
//raise_exception_err(env-exception_index, env-error_code);
} else {
/* we restore the process signal mask as the sigreturn should
   do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
cpu_loop_exit();
}
}






Re: [Qemu-devel] arm-linux-user infinite SIGSEGV looping

2007-08-25 Thread Thayne Harbaugh
On Fri, 2007-08-24 at 15:16 -0600, Thayne Harbaugh wrote:
 I've encountered what appears to be a race condition in arm-linux-user:
 sometimes the program qemu is running will hang forever and sometimes it
 will complete.  After digging about there appears to be at least two
 problems:

After digging about I have discovered that there truly is a bug in
cpu-exec.c:handle_cpu_exception() - unfortunately it's one that was
introduced by one of our patches.

My apologies for disturbing the list.

Thanks.






[Qemu-devel] Insta-segfault! i386-linux-user

2007-09-18 Thread Thayne Harbaugh
Has anyone seen an insta-segfault with i386-linux-user qemu?  I've
compiled qemu-0.9.0 as well as qemu-cvs (2007-09-18) with gcc-3.4 and
-fno-strict-aliasing on an amd64 and I get this:

./i386-linux-user/qemu-i386 --help
Segmentation fault

From GDB:

Program received signal SIGSEGV, Segmentation fault.
0x in ?? ()
(gdb) bt
#0  0x in ?? ()
#1  0x600575ed in __libc_csu_init ()
#2  0x2b826c660ade in __libc_start_main () from /lib/libc.so.6
#3  0x600050e9 in _start ()

Nice NULL frame there - and it's before main() is reached.

Install prefix/usr
BIOS directory/usr/share/qemu
binary directory  /usr/bin
Manual directory  /usr/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path   /home/thayne/dev/c2/qemu-0.9.0
C compilergcc-3.4
Host C compiler   gcc (also tried with gcc-3.4)
make  make
install   install
host CPU  x86_64
host big endian   no
target list   i386-linux-user arm-linux-user
gprof enabled no
profiler  no
static build  no
SDL support   yes
SDL static link   yes
mingw32 support   no
Adlib support yes
CoreAudio support no
ALSA support  yes
DSound supportno
FMOD support  no
kqemu support yes
Documentation yes

CFLAGS-Wall -fno-strict-aliasing -Wall -ggdb -fno-strict-aliasing
libc  2.6.1-1 (debian lenny)






Re: [Qemu-devel] Insta-segfault! i386-linux-user

2007-09-18 Thread Thayne Harbaugh
On Tue, 2007-09-18 at 15:53 +0200, Ronald wrote:
 Thayne Harbaugh schreef:
  Has anyone seen an insta-segfault with i386-linux-user qemu?  I've
  compiled qemu-0.9.0 as well as qemu-cvs (2007-09-18) with gcc-3.4 and
  -fno-strict-aliasing on an amd64 and I get this:
 
  ./i386-linux-user/qemu-i386 --help
  Segmentation fault
 
  From GDB:
 
  Program received signal SIGSEGV, Segmentation fault.
  0x in ?? ()
  (gdb) bt
  #0  0x in ?? ()
  #1  0x600575ed in __libc_csu_init ()
  #2  0x2b826c660ade in __libc_start_main () from /lib/libc.so.6
  #3  0x600050e9 in _start ()

SNIP


 Yes, I had this problem too. U only compiled the program using the 
 'user' parameters.

I only compiled the 'user' portion because that's all I want.

  But to get the virtualisation going, you need to 
 compile at least one 'softmmu' (whatever that is). Doing that will 
 create the executable: qemu(this is the executable you want :)   )

Err, no.  I don't want full virtualization.

 So I run Linux and I compile it with (and I really need it):
 
 i386-linux-user AND i386-softmmu (i386 can be replaced with your 
 arch such as: ppc, sparc, x86_64, mips, mipsel and arm)
 
 That should create an executable called qemu (as stated before) which 
 should not segfault immediatly lol :)

Thank you for your comments.  User virtualization doesn't require
softmmu.  User virtualization translates the ops in the user space
program and then jumps into the real kernel of the host operating system
when a syscall is made - it therefore doesn't need to virtualize all of
the hardware for I/O and the like.  Obviously this only works for
running linux executables of one architecture on linux of possibly
another architecture.

I might mention that none of the other user-space architectures segfault
- just i386 - e.g. arm-linux-user/qemu-arm works just fine.






Re: [Qemu-devel] Insta-segfault! i386-linux-user

2007-09-18 Thread Thayne Harbaugh
On Tue, 2007-09-18 at 21:11 +0200, Alexander Graf wrote:
 On Sep 18, 2007, at 8:25 PM, Thayne Harbaugh wrote:
 
  On Tue, 2007-09-18 at 15:53 +0200, Ronald wrote:
  Thayne Harbaugh schreef:

SNIP

  ./i386-linux-user/qemu-i386 --help
  Segmentation fault
 
  From GDB:
 
  Program received signal SIGSEGV, Segmentation fault.
  0x in ?? ()
  (gdb) bt
  #0  0x in ?? ()
  #1  0x600575ed in __libc_csu_init ()
  #2  0x2b826c660ade in __libc_start_main () from /lib/libc.so.6
  #3  0x600050e9 in _start ()

SNIP

 
 We had this on the list some months ago.

I'll dig for that.

 As far as I recall this  
 correctly the problem is the linker script. Just take a look at the  
 suse source rpm where we replace that one, so it works with x86_64.

Thanks for the guidance.

 Be prepared for breakage though, as linux-user on 64-Bit hosts does  
 not work properly.

What about it doesn't work properly?  Do you have some links for the
list archives?

Thank you.





[Qemu-devel] [PATCH] linux-user *at() syscalls

2007-09-19 Thread Thayne Harbaugh
I have a series of patches to add *at() syscalls to linux-user.  The
patches have minor inter-dependencies due to adjacent modifications in
some files.





[Qemu-devel] Re: [PATCH] linux-user utimensat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the utimensat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:16:40.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:17:45.0 -0600
@@ -158,6 +158,7 @@
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
+#define __NR_sys_utimensat __NR_utimensat
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
 #define __NR__llseek __NR_lseek
@@ -192,6 +193,10 @@
 #if defined(TARGET_NR_set_tid_address)  defined(__NR_set_tid_address)
 _syscall1(int,set_tid_address,int *,tidptr)
 #endif
+#if defined(TARGET_NR_utimensat)  defined(__NR_utimensat)
+_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
+  const struct timespec *,tsp,int,flags)
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -4873,6 +4878,30 @@
 	goto unimplemented_nowarn;
 #endif
 
+#if defined(TARGET_NR_utimensat)  defined(__NR_utimensat)
+case TARGET_NR_utimensat:
+{
+struct timespec ts[2];
+if (copy_from_user_timespec(ts, (struct target_timespec *)arg3)
+|| copy_from_user_timespec(ts+1, (struct target_timespec *)arg3+1)) {
+ret = -EFAULT;
+	goto fail;
+}
+if (!arg2)
+ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
+else {
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
+if (p)
+unlock_user(p, arg2, 0);
+}
+}
+	break;
+#endif
+
 default:
 unimplemented:
 gemu_log(qemu: Unsupported syscall: %d\n, num);
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-18 23:36:22.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:17:18.0 -0600
@@ -325,3 +325,4 @@
 #define TARGET_NR_mbind			319
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
+#define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user openat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the openat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:18:58.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:19:38.0 -0600
@@ -155,6 +155,7 @@
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_openat __NR_openat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
@@ -184,6 +185,9 @@
 #endif
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
   loff_t *, res, uint, wh);
+#if defined(TARGET_NR_openat)  defined(__NR_openat)
+_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
+#endif
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #if defined(TARGET_NR_tgkill)  defined(__NR_tgkill)
@@ -2685,6 +2689,24 @@
  arg3));
 unlock_user(p, arg1, 0);
 break;
+#if defined(TARGET_NR_openat)  defined(__NR_openat)
+case TARGET_NR_openat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_openat(arg1,
+   path(p),
+   target_to_host_bitmask(arg3, fcntl_flags_tbl),
+   arg4));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 case TARGET_NR_close:
 ret = get_errno(close(arg1));
 break;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:18:22.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:19:07.0 -0600
@@ -325,5 +325,6 @@
 #define TARGET_NR_mbind			319
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
+#define TARGET_NR_openat			322
 #define TARGET_NR_futimesat			326
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user mkdirat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the mkdirat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:19:38.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:20:59.0 -0600
@@ -155,6 +155,7 @@
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_mkdirat __NR_mkdirat
 #define __NR_sys_openat __NR_openat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
 #define __NR_sys_syslog __NR_syslog
@@ -185,6 +186,9 @@
 #endif
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
   loff_t *, res, uint, wh);
+#if defined(TARGET_NR_mkdirat)  defined(__NR_mkdirat)
+_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
+#endif
 #if defined(TARGET_NR_openat)  defined(__NR_openat)
 _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
 #endif
@@ -2973,6 +2977,21 @@
 ret = get_errno(mkdir(p, arg2));
 unlock_user(p, arg1, 0);
 break;
+#if defined(TARGET_NR_mkdirat)  defined(__NR_mkdirat)
+case TARGET_NR_mkdirat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_mkdirat(arg1, p, arg3));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 case TARGET_NR_rmdir:
 p = lock_user_string(arg1);
 ret = get_errno(rmdir(p));
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:19:07.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:20:24.0 -0600
@@ -326,5 +326,6 @@
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
 #define TARGET_NR_openat			322
+#define TARGET_NR_mkdirat			323
 #define TARGET_NR_futimesat			326
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user mknodat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the mknodat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:20:59.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:21:49.0 -0600
@@ -156,6 +156,7 @@
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
 #define __NR_sys_mkdirat __NR_mkdirat
+#define __NR_sys_mknodat __NR_mknodat
 #define __NR_sys_openat __NR_openat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
 #define __NR_sys_syslog __NR_syslog
@@ -189,6 +190,10 @@
 #if defined(TARGET_NR_mkdirat)  defined(__NR_mkdirat)
 _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
 #endif
+#if defined(TARGET_NR_mknodat)  defined(__NR_mknodat)
+_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
+  mode_t,mode,dev_t,dev)
+#endif
 #if defined(TARGET_NR_openat)  defined(__NR_openat)
 _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
 #endif
@@ -2828,6 +2833,21 @@
 ret = get_errno(mknod(p, arg2, arg3));
 unlock_user(p, arg1, 0);
 break;
+#if defined(TARGET_NR_mknodat)  defined(__NR_mknodat)
+case TARGET_NR_mknodat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 case TARGET_NR_chmod:
 p = lock_user_string(arg1);
 ret = get_errno(chmod(p, arg2));
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:20:24.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:21:07.0 -0600
@@ -327,5 +327,6 @@
 #define TARGET_NR_set_mempolicy		321
 #define TARGET_NR_openat			322
 #define TARGET_NR_mkdirat			323
+#define TARGET_NR_mknodat			324
 #define TARGET_NR_futimesat			326
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user fchownat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the fchownat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:21:49.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:22:58.0 -0600
@@ -151,6 +151,7 @@
 
 
 #define __NR_sys_uname __NR_uname
+#define __NR_sys_fchownat __NR_fchownat
 #define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
@@ -176,6 +177,10 @@
 }
 #endif
 _syscall1(int,sys_uname,struct new_utsname *,buf)
+#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
 #if defined(TARGET_NR_futimesat)  defined(__NR_futimesat)
 _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
   const struct timeval *,times)
@@ -4518,6 +4523,21 @@
 case TARGET_NR_fchown:
 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
 break;
+#if defined(TARGET_NR_fchownat)  defined(__NR_fchownat)
+case TARGET_NR_fchownat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+	else
+ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 #ifdef TARGET_NR_setresuid
 case TARGET_NR_setresuid:
 ret = get_errno(setresuid(low2highuid(arg1),
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:21:07.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:22:15.0 -0600
@@ -328,5 +328,6 @@
 #define TARGET_NR_openat			322
 #define TARGET_NR_mkdirat			323
 #define TARGET_NR_mknodat			324
+#define TARGET_NR_fchownat			325
 #define TARGET_NR_futimesat			326
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user unlinkat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the unlinkat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:22:58.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:23:52.0 -0600
@@ -163,6 +163,7 @@
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
+#define __NR_sys_unlinkat __NR_unlinkat
 #define __NR_sys_utimensat __NR_utimensat
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
@@ -216,6 +217,9 @@
 #if defined(TARGET_NR_set_tid_address)  defined(__NR_set_tid_address)
 _syscall1(int,set_tid_address,int *,tidptr)
 #endif
+#if defined(TARGET_NR_unlinkat)  defined(__NR_unlinkat)
+_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
+#endif
 #if defined(TARGET_NR_utimensat)  defined(__NR_utimensat)
 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
   const struct timespec *,tsp,int,flags)
@@ -2762,6 +2766,21 @@
 ret = get_errno(unlink(p));
 unlock_user(p, arg1, 0);
 break;
+#if defined(TARGET_NR_unlinkat)  defined(__NR_unlinkat)
+case TARGET_NR_unlinkat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_unlinkat(arg1, p, arg3));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 case TARGET_NR_execve:
 {
 char **argp, **envp;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:22:15.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:23:07.0 -0600
@@ -330,4 +330,5 @@
 #define TARGET_NR_mknodat			324
 #define TARGET_NR_fchownat			325
 #define TARGET_NR_futimesat			326
+#define TARGET_NR_unlinkat			328
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user renameat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the renameat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:23:52.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:24:47.0 -0600
@@ -159,6 +159,7 @@
 #define __NR_sys_mkdirat __NR_mkdirat
 #define __NR_sys_mknodat __NR_mknodat
 #define __NR_sys_openat __NR_openat
+#define __NR_sys_renameat __NR_renameat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
@@ -203,6 +204,10 @@
 #if defined(TARGET_NR_openat)  defined(__NR_openat)
 _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
 #endif
+#if defined(TARGET_NR_renameat)  defined(__NR_renameat)
+_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
+  int,newdirfd,const char *,newpath)
+#endif
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #if defined(TARGET_NR_tgkill)  defined(__NR_tgkill)
@@ -3016,6 +3021,28 @@
 unlock_user(p, arg1, 0);
 }
 break;
+#if defined(TARGET_NR_renameat)  defined(__NR_renameat)
+case TARGET_NR_renameat:
+if (!arg2 || !arg4) {
+ret = -EFAULT;
+	goto fail;
+}
+{
+void *p2 = NULL;
+p  = lock_user_string(arg2);
+p2 = lock_user_string(arg4);
+if (!access_ok(VERIFY_READ, p, 1)
+|| !access_ok(VERIFY_READ, p2, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_renameat(arg1, p, arg3, p2));
+if (p2)
+unlock_user(p2, arg4, 0);
+if (p)
+unlock_user(p, arg2, 0);
+}
+break;
+#endif
 case TARGET_NR_mkdir:
 p = lock_user_string(arg1);
 ret = get_errno(mkdir(p, arg2));
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:23:07.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:24:10.0 -0600
@@ -331,4 +331,5 @@
 #define TARGET_NR_fchownat			325
 #define TARGET_NR_futimesat			326
 #define TARGET_NR_unlinkat			328
+#define TARGET_NR_renameat			329
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user linkat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the linkat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:24:47.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:25:51.0 -0600
@@ -156,6 +156,7 @@
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_linkat __NR_linkat
 #define __NR_sys_mkdirat __NR_mkdirat
 #define __NR_sys_mknodat __NR_mknodat
 #define __NR_sys_openat __NR_openat
@@ -194,6 +195,10 @@
 #endif
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
   loff_t *, res, uint, wh);
+#if defined(TARGET_NR_linkat)  defined(__NR_linkat)
+_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
+	  int,newdirfd,const char *,newpath,int,flags)
+#endif
 #if defined(TARGET_NR_mkdirat)  defined(__NR_mkdirat)
 _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
 #endif
@@ -2766,6 +2771,28 @@
 unlock_user(p, arg1, 0);
 }
 break;
+#if defined(TARGET_NR_linkat)  defined(__NR_linkat)
+case TARGET_NR_linkat:
+if (!arg2 || !arg4) {
+ret = -EFAULT;
+goto fail;
+	}
+{
+void * p2 = NULL;
+p  = lock_user_string(arg2);
+p2 = lock_user_string(arg4);
+if (!access_ok(VERIFY_READ, p, 1)
+|| !access_ok(VERIFY_READ, p2, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
+if (p2)
+unlock_user(p, arg2, 0);
+if (p)
+unlock_user(p2, arg4, 0);
+}
+break;
+#endif
 case TARGET_NR_unlink:
 p = lock_user_string(arg1);
 ret = get_errno(unlink(p));
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:24:10.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:25:08.0 -0600
@@ -332,4 +332,5 @@
 #define TARGET_NR_futimesat			326
 #define TARGET_NR_unlinkat			328
 #define TARGET_NR_renameat			329
+#define TARGET_NR_linkat			330
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user symlinkat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the symlinkat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:25:51.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:26:51.0 -0600
@@ -162,6 +162,7 @@
 #define __NR_sys_openat __NR_openat
 #define __NR_sys_renameat __NR_renameat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
+#define __NR_sys_symlinkat __NR_symlinkat
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
@@ -214,6 +215,10 @@
   int,newdirfd,const char *,newpath)
 #endif
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
+#ifdef TARGET_NR_symlinkat
+_syscall3(int,sys_symlinkat,const char *,oldpath,
+  int,newdirfd,const char *,newpath)
+#endif
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #if defined(TARGET_NR_tgkill)  defined(__NR_tgkill)
 _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
@@ -3543,6 +3548,28 @@
 unlock_user(p, arg1, 0);
 }
 break;
+#if defined(TARGET_NR_symlinkat)  defined(__NR_symlinkat)
+case TARGET_NR_symlinkat:
+if (!arg1 || !arg3) {
+ret = -EFAULT;
+	goto fail;
+	}
+{
+void *p2 = NULL;
+p  = lock_user_string(arg1);
+p2 = lock_user_string(arg3);
+if (!access_ok(VERIFY_READ, p, 1)
+|| !access_ok(VERIFY_READ, p2, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_symlinkat(p, arg2, p2));
+if (p2)
+unlock_user(p2, arg3, 0);
+if (p)
+unlock_user(p, arg1, 0);
+}
+break;
+#endif
 #ifdef TARGET_NR_oldlstat
 case TARGET_NR_oldlstat:
 goto unimplemented;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:25:08.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:26:21.0 -0600
@@ -333,4 +333,5 @@
 #define TARGET_NR_unlinkat			328
 #define TARGET_NR_renameat			329
 #define TARGET_NR_linkat			330
+#define TARGET_NR_symlinkat			331
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user readlinkat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the readlinkat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:26:51.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:27:29.0 -0600
@@ -160,6 +160,7 @@
 #define __NR_sys_mkdirat __NR_mkdirat
 #define __NR_sys_mknodat __NR_mknodat
 #define __NR_sys_openat __NR_openat
+#define __NR_sys_readlinkat __NR_readlinkat
 #define __NR_sys_renameat __NR_renameat
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
 #define __NR_sys_symlinkat __NR_symlinkat
@@ -210,6 +211,10 @@
 #if defined(TARGET_NR_openat)  defined(__NR_openat)
 _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
 #endif
+#if defined(TARGET_NR_readlinkat)  defined(__NR_readlinkat)
+_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
+  char *,buf,size_t,bufsize)
+#endif
 #if defined(TARGET_NR_renameat)  defined(__NR_renameat)
 _syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
   int,newdirfd,const char *,newpath)
@@ -3584,6 +3589,28 @@
 unlock_user(p, arg1, 0);
 }
 break;
+#if defined(TARGET_NR_readlinkat)  defined(__NR_readlinkat)
+case TARGET_NR_readlinkat:
+if (!arg2 || !arg3) {
+ret = -EFAULT;
+goto fail;
+	}
+{
+void *p2 = NULL;
+p  = lock_user_string(arg2);
+p2 = lock_user(arg3, arg4, 0);
+if (!access_ok(VERIFY_READ, p, 1)
+|| !access_ok(VERIFY_READ, p2, 1))
+	ret = -EFAULT;
+else
+ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
+if (p2)
+unlock_user(p2, arg3, ret);
+if (p)
+unlock_user(p, arg2, 0);
+}
+break;
+#endif
 #ifdef TARGET_NR_uselib
 case TARGET_NR_uselib:
 goto unimplemented;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:26:21.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:26:57.0 -0600
@@ -334,4 +334,5 @@
 #define TARGET_NR_renameat			329
 #define TARGET_NR_linkat			330
 #define TARGET_NR_symlinkat			331
+#define TARGET_NR_readlinkat			332
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user fchmodat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the fchmodat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:27:29.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:28:02.0 -0600
@@ -151,6 +151,7 @@
 
 
 #define __NR_sys_uname __NR_uname
+#define __NR_sys_fchmodat __NR_fchmodat
 #define __NR_sys_fchownat __NR_fchownat
 #define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
@@ -182,6 +183,10 @@
 }
 #endif
 _syscall1(int,sys_uname,struct new_utsname *,buf)
+#if defined(TARGET_NR_fchmodat)  defined(__NR_fchmodat)
+_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
+  mode_t,mode,int,flags)
+#endif
 #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)
@@ -3715,6 +3720,21 @@
 case TARGET_NR_fchmod:
 ret = get_errno(fchmod(arg1, arg2));
 break;
+#if defined(TARGET_NR_fchmodat)  defined(__NR_fchmodat)
+case TARGET_NR_fchmodat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 case TARGET_NR_getpriority:
 ret = get_errno(getpriority(arg1, arg2));
 break;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:26:57.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:27:37.0 -0600
@@ -335,4 +335,5 @@
 #define TARGET_NR_linkat			330
 #define TARGET_NR_symlinkat			331
 #define TARGET_NR_readlinkat			332
+#define TARGET_NR_fchmodat			333
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user faccessat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the faccessat syscall to linux-user.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:28:02.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:28:30.0 -0600
@@ -151,6 +151,7 @@
 
 
 #define __NR_sys_uname __NR_uname
+#define __NR_sys_faccessat __NR_faccessat
 #define __NR_sys_fchmodat __NR_fchmodat
 #define __NR_sys_fchownat __NR_fchownat
 #define __NR_sys_futimesat __NR_futimesat
@@ -183,6 +184,9 @@
 }
 #endif
 _syscall1(int,sys_uname,struct new_utsname *,buf)
+#if defined(TARGET_NR_faccessat)  defined(__NR_faccessat)
+_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
+#endif
 #if defined(TARGET_NR_fchmodat)  defined(__NR_fchmodat)
 _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
   mode_t,mode,int,flags)
@@ -3037,6 +3041,21 @@
 ret = get_errno(access(p, arg2));
 unlock_user(p, arg1, 0);
 break;
+#if defined(TARGET_NR_faccessat)  defined(__NR_faccessat)
+case TARGET_NR_faccessat:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+	ret = -EFAULT;
+else
+ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
+if (p)
+unlock_user(p, arg2, 0);
+break;
+#endif
 #ifdef TARGET_NR_nice /* not on alpha */
 case TARGET_NR_nice:
 ret = get_errno(nice(arg1));
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:27:37.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:28:08.0 -0600
@@ -336,4 +336,5 @@
 #define TARGET_NR_symlinkat			331
 #define TARGET_NR_readlinkat			332
 #define TARGET_NR_fchmodat			333
+#define TARGET_NR_faccessat			334
 #define TARGET_NR_utimensat			348


[Qemu-devel] Re: [PATCH] linux-user stat64_put_user function

2007-09-19 Thread Thayne Harbaugh
This patch puts stat64 functionality into a function rather than using
gotos for all the locations that copy stat64 buffers to user space.
This patch is necessary for following fstatat64 syscall patch.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:28:30.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:28:34.0 -0600
@@ -526,6 +526,77 @@
 return 0;
 }
 
+#ifdef TARGET_ARM
+#define copy_to_user_statbuf64_wrapper(tsb,hsb)		\
+	CPUARMState *)cpu_env)-eabi)		\
+	 ? copy_to_user_statbuf64_eabi((tsb),(hsb))	\
+	 : copy_to_user_statbuf64((tsb),(hsb)))
+#else
+#define copy_to_user_statbuf64_wrapper(tsb,hsb)		\
+	copy_to_user_eabi_statbuf64((tsb),(hsb))
+#endif
+
+#ifdef TARGET_ARM
+static inline long copy_to_user_statbuf64_eabi(void *gen_target_stbuf,
+	   const struct stat *host_stbuf)
+{
+struct target_eabi_stat64 *target_stbuf = (struct target_eabi_stat64 *)gen_target_stbuf;
+int i;
+
+if( !access_ok(VERIFY_WRITE,target_stbuf,sizeof(struct target_eabi_stat64)) ) return -EFAULT;
+memset(target_stbuf, 0, sizeof(struct target_eabi_stat64));
+/* use __put_user() since we just checked that the buffer is valid  */
+__put_user(host_stbuf-st_dev, target_stbuf-st_dev);
+__put_user(host_stbuf-st_ino, target_stbuf-st_ino);
+#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
+__put_user(host_stbuf-st_ino, target_stbuf-__st_ino);
+#endif
+__put_user(host_stbuf-st_mode, target_stbuf-st_mode);
+__put_user(host_stbuf-st_nlink, target_stbuf-st_nlink);
+__put_user(host_stbuf-st_uid, target_stbuf-st_uid);
+__put_user(host_stbuf-st_gid, target_stbuf-st_gid);
+__put_user(host_stbuf-st_rdev, target_stbuf-st_rdev);
+/* XXX: better use of kernel struct */
+__put_user(host_stbuf-st_size, target_stbuf-st_size);
+__put_user(host_stbuf-st_blksize, target_stbuf-st_blksize);
+__put_user(host_stbuf-st_blocks, target_stbuf-st_blocks);
+__put_user(host_stbuf-st_atime, target_stbuf-target_st_atime);
+__put_user(host_stbuf-st_mtime, target_stbuf-target_st_mtime);
+__put_user(host_stbuf-st_ctime, target_stbuf-target_st_ctime);
+
+return 0;
+}
+#endif
+
+static inline long copy_to_user_statbuf64(void *gen_target_stbuf,
+	  const struct stat *host_stbuf)
+{
+struct target_stat64 *target_stbuf = (struct target_stat64 *)gen_target_stbuf;
+gemu_log(%s()\n, __func__);
+if( !access_ok(VERIFY_WRITE,target_stbuf,sizeof(struct target_stat64)) ) return -EFAULT;
+memset(target_stbuf, 0, sizeof(struct target_stat64));
+/* use __put_user() since we just checked that the buffer is valid  */
+__put_user(host_stbuf-st_dev, target_stbuf-st_dev);
+__put_user(host_stbuf-st_ino, target_stbuf-st_ino);
+#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
+__put_user(host_stbuf-st_ino, target_stbuf-__st_ino);
+#endif
+__put_user(host_stbuf-st_mode, target_stbuf-st_mode);
+__put_user(host_stbuf-st_nlink, target_stbuf-st_nlink);
+__put_user(host_stbuf-st_uid, target_stbuf-st_uid);
+__put_user(host_stbuf-st_gid, target_stbuf-st_gid);
+__put_user(host_stbuf-st_rdev, target_stbuf-st_rdev);
+/* XXX: better use of kernel struct */
+__put_user(host_stbuf-st_size, target_stbuf-st_size);
+__put_user(host_stbuf-st_blksize, target_stbuf-st_blksize);
+__put_user(host_stbuf-st_blocks, target_stbuf-st_blocks);
+__put_user(host_stbuf-st_atime, target_stbuf-target_st_atime);
+__put_user(host_stbuf-st_mtime, target_stbuf-target_st_mtime);
+__put_user(host_stbuf-st_ctime, target_stbuf-target_st_ctime);
+return 0;
+}
+
+
 static inline long copy_from_user_timeval(struct timeval *tv,
   struct target_timeval *target_tv)
 {
@@ -4562,7 +4633,10 @@
 if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT;
 ret = get_errno(stat(path(p), st));
 unlock_user(p, arg1, 0);
-goto do_stat64;
+if (!is_error(ret)
+ copy_to_user_statbuf64_wrapper(arg2,st))
+return -EFAULT;
+	break;
 #endif
 #ifdef TARGET_NR_lstat64
 case TARGET_NR_lstat64:
@@ -4570,65 +4644,18 @@
 if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT;
 ret = get_errno(lstat(path(p), st));
 unlock_user(p, arg1, 0);
-goto do_stat64;
+if (!is_error(ret)
+ copy_to_user_statbuf64_wrapper(arg2,st))
+return -EFAULT;
+	break;
 #endif
 #ifdef TARGET_NR_fstat64
 case TARGET_NR_fstat64:
-{
-ret = get_errno(fstat(arg1, st));
-do_stat64:
-if (!is_error(ret)) {
-#ifdef TARGET_ARM
-if (((CPUARMState *)cpu_env)-eabi) {
-struct target_eabi_stat64 *target_st = (struct target_eabi_stat64 *)arg2;
-		if( !access_ok(VERIFY_WRITE,target_st,sizeof(struct target_eabi_stat64)) ) return -EFAULT;
-memset(target_st, 0, 

[Qemu-devel] Re: [PATCH] linux-user fstatat syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the fstatat syscall to linux-user.  To depends on the
previous stat64_put_user patch.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:28:34.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:31:35.0 -0600
@@ -149,11 +149,26 @@
 	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6);	\
 }
 
+#if defined(__NR_fstatat64)
+#define HOST_NR_FSTATAT __NR_fstatat64
+typedef struct stat64 host_statbuf_t;
+#elif defined(__NR_newfstatat)
+#define HOST_NR_FSTATAT __NR_newfstatat
+typedef struct stat host_statbuf_t;
+#endif
+#if defined(TARGET_NR_fstatat64)
+#define TARGET_NR_FSTATAT (TARGET_NR_fstatat64)
+typedef struct target_stat64 target_statbuf_t;
+#elif defined(TARGET_NR_newfstatat)
+#define TARGET_NR_FSTATAT (TARGET_NR_newfstatat)
+typedef struct target_stat target_statbuf_t;
+#endif
 
 #define __NR_sys_uname __NR_uname
 #define __NR_sys_faccessat __NR_faccessat
 #define __NR_sys_fchmodat __NR_fchmodat
 #define __NR_sys_fchownat __NR_fchownat
+#define __NR_sys_fstatat HOST_NR_FSTATAT
 #define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
@@ -170,6 +185,9 @@
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
 #define __NR_sys_unlinkat __NR_unlinkat
+#if !defined(__NR_utimensat)  defined(__x86_64__)
+#define __NR_utimensat		280
+#endif
 #define __NR_sys_utimensat __NR_utimensat
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
@@ -199,6 +217,10 @@
 _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
   const struct timeval *,times)
 #endif
+#if defined(TARGET_NR_FSTATAT)  (HOST_NR_FSTATAT)
+_syscall4(int,sys_fstatat,int,dirfd,const char *,pathname,
+  host_statbuf_t *,buf,int,flags)
+#endif
 _syscall2(int,sys_getcwd1,char *,buf,size_t,size)
 _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
 #if defined(TARGET_NR_getdents64)  defined(__NR_getdents64)
@@ -533,7 +555,7 @@
 	 : copy_to_user_statbuf64((tsb),(hsb)))
 #else
 #define copy_to_user_statbuf64_wrapper(tsb,hsb)		\
-	copy_to_user_eabi_statbuf64((tsb),(hsb))
+	copy_to_user_statbuf64((tsb),(hsb))
 #endif
 
 #ifdef TARGET_ARM
@@ -4731,6 +4753,28 @@
 unlock_user(p, arg2, 0);
 break;
 #endif
+#if defined(TARGET_NR_FSTATAT)  defined(HOST_NR_FSTATAT)
+case TARGET_NR_FSTATAT:
+if (!arg2) {
+ret = -EFAULT;
+goto fail;
+}
+{
+host_statbuf_t statbuf;
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else {
+ret = get_errno(sys_fstatat(arg1, path(p), statbuf, arg4));
+if (!is_error(ret)
+ copy_to_user_statbuf64_wrapper((struct target_stat64 *)arg3, statbuf))
+ret = -EFAULT;
+}
+if (p)
+unlock_user(p, arg2, 0);
+}
+break;
+#endif
 #ifdef TARGET_NR_setresuid
 case TARGET_NR_setresuid:
 ret = get_errno(setresuid(low2highuid(arg1),
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:28:08.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:29:54.0 -0600
@@ -330,6 +330,7 @@
 #define TARGET_NR_mknodat			324
 #define TARGET_NR_fchownat			325
 #define TARGET_NR_futimesat			326
+#define TARGET_NR_fstatat64			327
 #define TARGET_NR_unlinkat			328
 #define TARGET_NR_renameat			329
 #define TARGET_NR_linkat			330


Re: [Qemu-devel] Re: [PATCH] linux-user utimensat() syscall

2007-09-24 Thread Thayne Harbaugh
On Mon, 2007-09-24 at 13:45 -0600, Thayne Harbaugh wrote:
 On Sun, 2007-09-23 at 12:58 -0400, Stuart Anderson wrote:
  On Sun, 23 Sep 2007, Thiemo Seufer wrote:
  
   Thayne Harbaugh wrote:
   This patch adds the utimensat syscall to linux-user
 
 Oops!
 
   Doesn't build:
  
   gcc-3.4 -g  -Wl,-T,/home/ths/qemu/qemu-work/ppc.ld   -o qemu-arm main.o 
   syscall.o mmap.o signal.o path.o osdep.o thunk.o elfload.o linuxload.o 
   flatload.o nwfpe/fpa11.o nwfpe/fpa11_cpdo.o nwfpe/fpa11_cpdt.o 
   nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o 
   nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o libqemu.a gdbstub.o  
-lm -lrt
   syscall.o: In function `do_syscall':
   /home/ths/qemu/qemu-work/linux-user/syscall.c:4665: undefined reference 
   to `copy_from_user_timespec'
   /home/ths/qemu/qemu-work/linux-user/syscall.c:4665: undefined reference 
   to `copy_from_user_timespec'
  
  It's looking for something that is in the EFAULT patch.
 
 Yeah, I guess I had the EFAULT patch applied.  I'll work up a patch for
 utimensat() without the EFAULT patch.

Try this patch for utimensat() that doesn't depend on the EFAULT patch.
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-24 15:22:35.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-24 15:22:58.0 -0600
@@ -325,3 +325,4 @@
 #define TARGET_NR_mbind			319
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
+#define TARGET_NR_utimensat			348
Index: qemu/linux-user/i386/syscall_nr.h
===
--- qemu.orig/linux-user/i386/syscall_nr.h	2007-09-24 15:22:42.0 -0600
+++ qemu/linux-user/i386/syscall_nr.h	2007-09-24 15:22:58.0 -0600
@@ -275,3 +275,5 @@
 #define TARGET_NR_utimes		271
 
 #define TARGET_NR_set_robust_list	311
+
+#define TARGET_NR_utimensat		320
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-24 15:22:50.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-24 15:41:51.0 -0600
@@ -146,6 +146,7 @@
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_tgkill __NR_tgkill
 #define __NR_sys_tkill __NR_tkill
+#define __NR_sys_utimensat __NR_utimensat
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
 #define __NR__llseek __NR_lseek
@@ -180,6 +181,10 @@
 #if defined(TARGET_NR_set_tid_address)  defined(__NR_set_tid_address)
 _syscall1(int,set_tid_address,int *,tidptr)
 #endif
+#if defined(TARGET_NR_utimensat)  defined(__NR_utimensat)
+_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
+  const struct timespec *,tsp,int,flags)
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -4653,6 +4658,27 @@
 	goto unimplemented_nowarn;
 #endif
 
+#if defined(TARGET_NR_utimensat)  defined(__NR_utimensat)
+case TARGET_NR_utimensat:
+{
+struct timespec ts[2];
+target_to_host_timespec(ts, arg3);
+target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
+if (!arg2)
+ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
+else {
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret = -EFAULT;
+else
+ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
+if (p)
+unlock_user(p, arg2, 0);
+}
+}
+	break;
+#endif
+
 default:
 unimplemented:
 gemu_log(qemu: Unsupported syscall: %d\n, num);


Re: [Qemu-devel] Updated RFC: linux user problems]]

2007-09-24 Thread Thayne Harbaugh
I've often wondered why there isn't a tswap_target_ulong().  Seems like
using tswap32() is asking for trouble.





[Qemu-devel] [PATCH] linux-user sigaltstack() syscall

2007-09-24 Thread Thayne Harbaugh
This patch adds the sigaltstack() syscall for linux-user.
Index: qemu/linux-user/signal.c
===
--- qemu.orig/linux-user/signal.c	2007-09-24 22:45:48.0 -0600
+++ qemu/linux-user/signal.c	2007-09-24 22:56:18.0 -0600
@@ -26,6 +26,7 @@
 #include errno.h
 #include sys/ucontext.h
 
+#include target_signal.h
 #include qemu.h
 
 /*
@@ -51,6 +52,12 @@
  first signal, we put it here */
 };
 
+struct target_sigaltstack target_sigaltstack_used = {
+.ss_sp = 0,
+.ss_size = 0,
+.ss_flags = TARGET_SS_DISABLE,
+};
+
 static struct emulated_sigaction sigact_table[TARGET_NSIG];
 static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
 static struct sigqueue *first_free; /* first free siginfo queue entry */
@@ -98,6 +105,18 @@
 };
 static uint8_t target_to_host_signal_table[65];
 
+static inline int on_sig_stack(unsigned long sp)
+{
+return (sp - target_sigaltstack_used.ss_sp
+ target_sigaltstack_used.ss_size);
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
+: on_sig_stack(sp) ? SS_ONSTACK : 0);
+}
+
 static inline int host_to_target_signal(int sig)
 {
 return host_to_target_signal_table[sig];
@@ -420,6 +439,66 @@
 }
 }
 
+int do_sigaltstack(const struct target_sigaltstack *uss,
+   struct target_sigaltstack *uoss,
+   target_ulong sp)
+{
+int ret;
+struct target_sigaltstack oss;
+
+/* XXX: test errors */
+if(uoss)
+{
+oss.ss_sp = tswap32(target_sigaltstack_used.ss_sp);
+oss.ss_size = tswap32(target_sigaltstack_used.ss_size);
+oss.ss_flags = tswap32(sas_ss_flags(sp));
+}
+
+if(uss)
+{
+	struct target_sigaltstack ss;
+
+	ret = -EFAULT;
+	if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
+	|| __get_user(ss.ss_sp, uss-ss_sp)
+	|| __get_user(ss.ss_size, uss-ss_size)
+	|| __get_user(ss.ss_flags, uss-ss_flags))
+goto out;
+
+	ret = -EPERM;
+	if (on_sig_stack(sp))
+goto out;
+
+	ret = -EINVAL;
+	if (ss.ss_flags != TARGET_SS_DISABLE
+ ss.ss_flags != TARGET_SS_ONSTACK
+ ss.ss_flags != 0)
+goto out;
+
+	if (ss.ss_flags == TARGET_SS_DISABLE) {
+ss.ss_size = 0;
+ss.ss_sp = 0;
+	} else {
+ret = -ENOMEM;
+if (ss.ss_size  MINSIGSTKSZ)
+goto out;
+	}
+
+target_sigaltstack_used.ss_sp = ss.ss_sp;
+target_sigaltstack_used.ss_size = ss.ss_size;
+}
+
+if (uoss) {
+ret = -EFAULT;
+if (copy_to_user(uoss, oss, sizeof(oss)))
+goto out;
+}
+
+ret = 0;
+out:
+return ret;
+}
+
 int do_sigaction(int sig, const struct target_sigaction *act,
  struct target_sigaction *oact)
 {
@@ -550,12 +629,6 @@
 	target_ulong cr2;
 };
 
-typedef struct target_sigaltstack {
-	target_ulong ss_sp;
-	int ss_flags;
-	target_ulong ss_size;
-} target_stack_t;
-
 struct target_ucontext {
 target_ulong	  tuc_flags;
 	target_ulong  tuc_link;
@@ -639,16 +712,14 @@
 
 	/* Default to using normal stack */
 	esp = env-regs[R_ESP];
-#if 0
 	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka-sa.sa_flags  SA_ONSTACK) {
-		if (sas_ss_flags(esp) == 0)
-			esp = current-sas_ss_sp + current-sas_ss_size;
-	}
+if (ka-sa.sa_flags  TARGET_SA_ONSTACK) {
+if (sas_ss_flags(esp) == 0)
+esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+}
 
 	/* This is the legacy signal stack switching. */
 	else
-#endif
 if ((env-segs[R_SS].selector  0x) != __USER_DS 
 !(ka-sa.sa_flags  TARGET_SA_RESTORER) 
 ka-sa.sa_restorer) {
@@ -749,11 +820,11 @@
 	/* Create the ucontext.  */
 	err |= __put_user(0, frame-uc.tuc_flags);
 	err |= __put_user(0, frame-uc.tuc_link);
-	err |= __put_user(/*current-sas_ss_sp*/ 0,
+	err |= __put_user(target_sigaltstack_used.ss_sp,
 			  frame-uc.tuc_stack.ss_sp);
-	err |= __put_user(/* sas_ss_flags(regs-esp) */ 0,
+	err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
 			  frame-uc.tuc_stack.ss_flags);
-	err |= __put_user(/* current-sas_ss_size */ 0,
+	err |= __put_user(target_sigaltstack_used.ss_size,
 			  frame-uc.tuc_stack.ss_size);
 	err |= setup_sigcontext(frame-uc.tuc_mcontext, frame-fpstate,
 			env, set-sig[0]);
@@ -877,7 +948,6 @@
 {
 	struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env-regs[R_ESP] - 4);
 sigset_t set;
-//	stack_t st;
 	int eax;
 
 #if 0
@@ -890,13 +960,9 @@
 	if (restore_sigcontext(env, frame-uc.tuc_mcontext, eax))
 		goto badframe;
 
-#if 0
-	if (__copy_from_user(st, frame-uc.tuc_stack, sizeof(st)))
+	if (do_sigaltstack(frame-uc.tuc_stack, NULL, get_sp_from_cpustate(env)) == -EFAULT)
 		goto badframe;
-	/* It is more difficult to avoid calling this 

Re: [Qemu-devel] [PATCH] linux-user sigaltstack() syscall

2007-09-25 Thread Thayne Harbaugh
On Mon, 2007-09-24 at 23:04 -0600, Thayne Harbaugh wrote:
 This patch adds the sigaltstack() syscall for linux-user.

The previous patch relied on the EFAULT patch, this newer version does
not.  It also fixes a few places that used tswap32() that should use
__put_user().
Index: qemu/linux-user/signal.c
===
--- qemu.orig/linux-user/signal.c	2007-09-25 05:46:34.0 -0600
+++ qemu/linux-user/signal.c	2007-09-25 06:35:23.0 -0600
@@ -26,6 +26,7 @@
 #include errno.h
 #include sys/ucontext.h
 
+#include target_signal.h
 #include qemu.h
 
 //#define DEBUG_SIGNAL
@@ -45,6 +46,12 @@
  first signal, we put it here */
 };
 
+struct target_sigaltstack target_sigaltstack_used = {
+.ss_sp = 0,
+.ss_size = 0,
+.ss_flags = TARGET_SS_DISABLE,
+};
+
 static struct emulated_sigaction sigact_table[TARGET_NSIG];
 static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
 static struct sigqueue *first_free; /* first free siginfo queue entry */
@@ -92,6 +99,18 @@
 };
 static uint8_t target_to_host_signal_table[65];
 
+static inline int on_sig_stack(unsigned long sp)
+{
+return (sp - target_sigaltstack_used.ss_sp
+ target_sigaltstack_used.ss_size);
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE
+: on_sig_stack(sp) ? SS_ONSTACK : 0);
+}
+
 static inline int host_to_target_signal(int sig)
 {
 return host_to_target_signal_table[sig];
@@ -419,6 +438,67 @@
 }
 }
 
+int do_sigaltstack(const struct target_sigaltstack *uss,
+   struct target_sigaltstack *uoss,
+   target_ulong sp)
+{
+int ret;
+struct target_sigaltstack oss;
+
+/* XXX: test errors */
+if(uoss)
+{
+__put_user(target_sigaltstack_used.ss_sp, oss.ss_sp);
+__put_user(target_sigaltstack_used.ss_size, oss.ss_size);
+__put_user(sas_ss_flags(sp), oss.ss_flags);
+}
+
+if(uss)
+{
+	struct target_sigaltstack ss;
+
+	ret = -EFAULT;
+	if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
+	|| __get_user(ss.ss_sp, uss-ss_sp)
+	|| __get_user(ss.ss_size, uss-ss_size)
+	|| __get_user(ss.ss_flags, uss-ss_flags))
+goto out;
+
+	ret = -EPERM;
+	if (on_sig_stack(sp))
+goto out;
+
+	ret = -EINVAL;
+	if (ss.ss_flags != TARGET_SS_DISABLE
+ ss.ss_flags != TARGET_SS_ONSTACK
+ ss.ss_flags != 0)
+goto out;
+
+	if (ss.ss_flags == TARGET_SS_DISABLE) {
+ss.ss_size = 0;
+ss.ss_sp = 0;
+	} else {
+ret = -ENOMEM;
+if (ss.ss_size  MINSIGSTKSZ)
+goto out;
+	}
+
+target_sigaltstack_used.ss_sp = ss.ss_sp;
+target_sigaltstack_used.ss_size = ss.ss_size;
+}
+
+if (uoss) {
+ret = -EFAULT;
+if (!access_ok(VERIFY_WRITE, uoss, sizeof(oss)))
+goto out;
+memcpy(uoss, oss, sizeof(oss));
+}
+
+ret = 0;
+out:
+return ret;
+}
+
 int do_sigaction(int sig, const struct target_sigaction *act,
  struct target_sigaction *oact)
 {
@@ -551,12 +631,6 @@
 	target_ulong cr2;
 };
 
-typedef struct target_sigaltstack {
-	target_ulong ss_sp;
-	int ss_flags;
-	target_ulong ss_size;
-} target_stack_t;
-
 struct target_ucontext {
 target_ulong	  tuc_flags;
 	target_ulong  tuc_link;
@@ -640,16 +714,14 @@
 
 	/* Default to using normal stack */
 	esp = env-regs[R_ESP];
-#if 0
 	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka-sa.sa_flags  SA_ONSTACK) {
-		if (sas_ss_flags(esp) == 0)
-			esp = current-sas_ss_sp + current-sas_ss_size;
-	}
+if (ka-sa.sa_flags  TARGET_SA_ONSTACK) {
+if (sas_ss_flags(esp) == 0)
+esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+}
 
 	/* This is the legacy signal stack switching. */
 	else
-#endif
 if ((env-segs[R_SS].selector  0x) != __USER_DS 
 !(ka-sa.sa_flags  TARGET_SA_RESTORER) 
 ka-sa.sa_restorer) {
@@ -750,11 +822,11 @@
 	/* Create the ucontext.  */
 	err |= __put_user(0, frame-uc.tuc_flags);
 	err |= __put_user(0, frame-uc.tuc_link);
-	err |= __put_user(/*current-sas_ss_sp*/ 0,
+	err |= __put_user(target_sigaltstack_used.ss_sp,
 			  frame-uc.tuc_stack.ss_sp);
-	err |= __put_user(/* sas_ss_flags(regs-esp) */ 0,
+	err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
 			  frame-uc.tuc_stack.ss_flags);
-	err |= __put_user(/* current-sas_ss_size */ 0,
+	err |= __put_user(target_sigaltstack_used.ss_size,
 			  frame-uc.tuc_stack.ss_size);
 	err |= setup_sigcontext(frame-uc.tuc_mcontext, frame-fpstate,
 			env, set-sig[0]);
@@ -880,7 +952,6 @@
 {
 	struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env-regs[R_ESP] - 4);
 sigset_t set;
-//	stack_t st;
 	int eax;
 
 #if 0
@@ -893,13 +964,9

[Qemu-devel] [PATCH] getpriority() shouldn't use libc wrapper

2007-09-26 Thread Thayne Harbaugh
The linux-user getpriority() syscall goes through the libc wrapper.
This causes a problem because the libc wrapper remaps the return value
from the kernel.  This patch calls the kernel getpriority syscall
directly.

Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-26 13:13:40.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-26 14:10:29.0 -0600
@@ -174,6 +174,7 @@
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
+#define __NR_sys_getpriority __NR_getpriority
 #define __NR_sys_linkat __NR_linkat
 #define __NR_sys_mkdirat __NR_mkdirat
 #define __NR_sys_mknodat __NR_mknodat
@@ -229,6 +230,7 @@
 #if defined(TARGET_NR_getdents64)  defined(__NR_getdents64)
 _syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
 #endif
+_syscall2(int, sys_getpriority, int, which, int, who);
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
   loff_t *, res, uint, wh);
 #if defined(TARGET_NR_linkat)  defined(__NR_linkat)
@@ -4010,7 +4012,10 @@
 break;
 #endif
 case TARGET_NR_getpriority:
-ret = get_errno(getpriority(arg1, arg2));
+/* libc does special remapping of the return value of
+ * sys_getpriority() so it's just easiest to call
+ * sys_getpriority() directly rather than through libc. */
+ret = sys_getpriority(arg1, arg2);
 break;
 case TARGET_NR_setpriority:
 ret = get_errno(setpriority(arg1, arg2, arg3));


Re: [Qemu-devel] qemu linux-user/qemu.h linux-user/signal.c linu...

2007-09-27 Thread Thayne Harbaugh
On Thu, 2007-09-27 at 16:08 +0200, Jocelyn Mayer wrote:
 On Thu, 2007-09-27 at 13:57 +, Thiemo Seufer wrote:
  CVSROOT:/sources/qemu
  Module name:qemu
  Changes by: Thiemo Seufer ths 07/09/27 13:57:58
  
  Modified files:
  linux-user : qemu.h signal.c syscall.c 
  target-alpha   : cpu.h 
  target-arm : cpu.h 
  target-i386: cpu.h 
  target-mips: cpu.h 
  target-ppc : cpu.h 
 
  static inline target_ulong get_sp_from_cpustate(CPUPPCState *state)
 {
   return state-gpr[1];
 }
 
 This is no way related to CPU emulation then has nothing to do in cpu.h.
 Furthermore, there no notion of sigaltstack or even stack pointer in the
 PowerPC specification.
 Revert this patch immediatly, please, and stop breaking others code...

My apologies.  I put get_sp_from_cpustate() in cpu.h because it is a
generic function that isn't exclusive to sigaltstack().  If it's
preferred it can be exclusive to sigaltstack().

 How should we say don't do weird things in others code ??? Again, and
 again and again...

My hope was that these types of comments would be made prior to the
patch being committed.  Is there a developer document that describes the
intentions of code layout, design philosophy, etc. so that I'm not
guessing?

Please send me additional comments so that I can rework the patch for
resubmission.

Thanks.





[Qemu-devel] linux-user mmap() for 32-bit guest on 64-bit host

2007-09-27 Thread Thayne Harbaugh
I've been using the patch posted by Kirill Shutemov
(http://www.mail-archive.com/qemu-devel@nongnu.org/msg10893.html) for
forcing mmap() addresses on 64-bit hosts to be 32-bit clean.  I just
discovered a minor problem with the patch: MAP_32BIT is not a valid flag
to mremap() and will cause mremap() to be rejected by the kernel with
EINVAL.

I've investigated the kernel and it doesn't preserve the flags from the
original mmap() call.  Essentially do_mremap() in the kernel calls
get_unmapped_area() with the only possible flag being MAP_SHARED.

The attached patch fixes qemu so that mremap() won't get rejected for
having an illegal flag, but it might cause havoc for allocating a
32-bit address.

A possible patch for the kernel is also included (and untested).
Index: qemu/linux-user/mmap.c
===
--- qemu.orig/linux-user/mmap.c	2007-09-27 10:32:45.0 -0600
+++ qemu/linux-user/mmap.c	2007-09-27 22:36:39.0 -0600
@@ -27,6 +27,10 @@
 
 #include qemu.h
 
+#if !defined(MAP_32BIT)
+#define MAP_32BIT 0
+#endif
+
 //#define DEBUG_MMAP
 
 /* NOTE: all the constants are the HOST ones, but addresses are target. */
@@ -116,7 +120,7 @@
 if (prot1 == 0) {
 /* no page was there, so we allocate one */
 ret = (long)mmap(host_start, qemu_host_page_size, prot,
- flags | MAP_ANONYMOUS, -1, 0);
+ flags | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
 if (ret == -1)
 return ret;
 prot1 = prot;
@@ -217,7 +221,8 @@
 abort();
 host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
 real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE,
-MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT,
+	-1, 0);
 if (real_start == -1)
 return real_start;
 real_end = real_start + host_len;
@@ -234,7 +239,7 @@
 host_offset = offset  qemu_host_page_mask;
 host_len = len + offset - host_offset;
 host_start = (long)mmap(real_start ? g2h(real_start) : NULL,
-host_len, prot, flags, fd, host_offset);
+host_len, prot, flags | MAP_32BIT, fd, host_offset);
 if (host_start == -1)
 return host_start;
 /* update start so that it points to the file position at 'offset' */
@@ -312,7 +317,7 @@
 	else
 	  offset1 = offset + real_start - start;
 ret = (long)mmap(g2h(real_start), real_end - real_start,
- prot, flags, fd, offset1);
+ prot, flags | MAP_32BIT, fd, offset1);
 if (ret == -1)
 return ret;
 }
--- linux-source-2.6.22/mm/mremap.c.orig	2007-09-27 23:02:13.0 -0600
+++ linux-source-2.6.22/mm/mremap.c	2007-09-27 23:07:29.0 -0600
@@ -23,6 +23,10 @@
 #include asm/cacheflush.h
 #include asm/tlbflush.h
 
+#ifndef MAP_32BIT
+#define MAP_32BIT 0
+#endif
+
 static pmd_t *get_old_pmd(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
@@ -255,7 +259,7 @@
 	unsigned long ret = -EINVAL;
 	unsigned long charged = 0;
 
-	if (flags  ~(MREMAP_FIXED | MREMAP_MAYMOVE))
+	if (flags  ~(MREMAP_FIXED | MREMAP_MAYMOVE | MAP_32BIT))
 		goto out;
 
 	if (addr  ~PAGE_MASK)
@@ -388,6 +392,9 @@
 			if (vma-vm_flags  VM_MAYSHARE)
 map_flags |= MAP_SHARED;
 
+			if (flags  MAP_32BIT)
+map_flags |= MAP_32BIT;
+
 			new_addr = get_unmapped_area(vma-vm_file, 0, new_len,
 		vma-vm_pgoff, map_flags);
 			ret = new_addr;


[Qemu-devel] Don't install tools if $(TOOLS) is empty

2007-10-09 Thread Thayne Harbaugh
Install will fail if $(TOOLS) is empty - which happens when only user
emulation is built

Index: qemu/Makefile
===
--- qemu.orig/Makefile  2007-10-09 21:31:43.0 -0600
+++ qemu/Makefile   2007-10-09 21:40:05.0 -0600
@@ -67,7 +67,9 @@
 
 install: all $(if $(BUILD_DOCS),install-doc)
mkdir -p $(DESTDIR)$(bindir)
+ifneq ($(TOOLS),)
$(INSTALL) -m 755 -s $(TOOLS) $(DESTDIR)$(bindir)
+endif
mkdir -p $(DESTDIR)$(datadir)
for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
video.x openbios-sparc32 pxe-ne2k_pci.bin \






Re: [Qemu-devel] What happened with NPTL/TLS support?

2007-10-12 Thread Thayne Harbaugh

On Fri, 2007-10-12 at 18:12 +0300, Felipe Contreras wrote:
 Hi,
 
 When I try to use codesourcery's toolchain arm-2006q3-27 in my Fedora
 7 box I always have the following issue:
 
 qemu: Unsupported syscall: 983045

Yep, I've seen that before.

 I guess it's a problem of NPTL incompatibility. Anyway, the patch that
 Paul Brook sent a while ago solves it [1].
 
 I wonder if it can be integrated or what would be the right way to
 solve this issue. Am I the only one having it?
 
 Best regards.
 
 [1] http://lists.gnu.org/archive/html/qemu-devel/2005-08/msg00128.html


I've been using this patch, as well as other NPTL/TLS patches as well as
some of my own work and have a set of patches for NPTL/TLS that works
reasonably well for arm and i386.  The patches don't apply cleanly to
CVS current, but I'm more than happy to rework them so that they will if
someone is serious about getting NPTL/TLS/futex stuff working for
linux-user.  I haven't submitted my patches because I kept expecting the
other patches to be accepted.





Re: [Qemu-devel] [PATCH] syscall_target_errno.patch

2007-10-12 Thread Thayne Harbaugh

On Wed, 2007-10-10 at 21:38 -0600, Thayne Harbaugh wrote:
SNIP

 I have noticed that many functions in syscall.c return a *host* errno
 when a *target* errno should be return.  At the same time, there are
 several places in syscall.c:do_syscall() that immediately return an
 errno rather than setting the return value and exiting through the
 syscall return value reporting at the end of do_syscall().
 
 This patch addresses both of those problems at once rather than touching
 the exact same errno return lines twice in do_syscall().

The patch is better with parenthesis around the arguments of the
return_err() macro:

#define return_err(err) do { ret = -(err); goto fail; } while(0)







Re: [Qemu-devel] [PATCH] syscall_target_errno.patch

2007-10-15 Thread Thayne Harbaugh

On Thu, 2007-10-11 at 14:10 +0200, J. Mayer wrote: 
 On Wed, 2007-10-10 at 21:38 -0600, Thayne Harbaugh wrote:

SNIP

  I have noticed that many functions in syscall.c return a *host* errno
  when a *target* errno should be return.  At the same time, there are
  several places in syscall.c:do_syscall() that immediately return an
  errno rather than setting the return value and exiting through the
  syscall return value reporting at the end of do_syscall().
  
  This patch addresses both of those problems at once rather than touching
  the exact same errno return lines twice in do_syscall().  It also
  touches a few functions in linux-user/signal.c that are called from
  do_syscall().

SNIP

 Hi,
 
 there are still a lot of problems hidden in syscalls.c and signal.c, as
 you noticed.
 Your patch seems OK to me and adding all those comments is imho really
 great.
 My only remark is a cosmetic one: I don't like too much hidding 'goto'
 in macros...

This is another version of the same patch that doesn't hide goto in a
macro.  It also makes do_sigaltstack() return target values which are
more like the other do_*() functions called from do_syscalls().
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-10-15 08:31:52.0 -0600
+++ qemu/linux-user/syscall.c	2007-10-15 08:32:45.0 -0600
@@ -166,6 +166,8 @@
 #ifdef __NR_gettid
 _syscall0(int, gettid)
 #else
+/* This is a replacement for the host gettid() and must return a host
+ * errno. */
 static int gettid(void) {
 return -ENOSYS;
 }
@@ -387,6 +389,7 @@
 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
 }
 
+/* do_brk() must return target values and target errnos. */
 target_long do_brk(target_ulong new_brk)
 {
 target_ulong brk_page;
@@ -396,7 +399,7 @@
 if (!new_brk)
 return target_brk;
 if (new_brk  target_original_brk)
-return -ENOMEM;
+return -TARGET_ENOMEM;
 
 brk_page = HOST_PAGE_ALIGN(target_brk);
 
@@ -530,6 +533,7 @@
 }
 
 
+/* do_select() must return target values and target errnos. */
 static target_long do_select(int n,
  target_ulong rfd_p, target_ulong wfd_p,
  target_ulong efd_p, target_ulong target_tv)
@@ -704,6 +708,7 @@
 msgh-msg_controllen = tswapl(space);
 }
 
+/* do_setsockopt() Must return target values and target errnos. */
 static target_long do_setsockopt(int sockfd, int level, int optname,
  target_ulong optval, socklen_t optlen)
 {
@@ -714,7 +719,7 @@
 case SOL_TCP:
 /* TCP options all take an 'int' value.  */
 if (optlen  sizeof(uint32_t))
-return -EINVAL;
+return -TARGET_EINVAL;
 
 val = tget32(optval);
 ret = get_errno(setsockopt(sockfd, level, optname, val, sizeof(val)));
@@ -812,7 +817,7 @@
 goto unimplemented;
 }
 	if (optlen  sizeof(uint32_t))
-	return -EINVAL;
+	return -TARGET_EINVAL;
 
 	val = tget32(optval);
 	ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, val, sizeof(val)));
@@ -820,11 +825,12 @@
 default:
 unimplemented:
 gemu_log(Unsupported setsockopt level=%d optname=%d \n, level, optname);
-ret = -ENOSYS;
+ret = -TARGET_ENOSYS;
 }
 return ret;
 }
 
+/* do_getsockopt() Must return target values and target errnos. */
 static target_long do_getsockopt(int sockfd, int level, int optname,
  target_ulong optval, target_ulong optlen)
 {
@@ -851,7 +857,7 @@
 int_case:
 len = tget32(optlen);
 if (len  0)
-return -EINVAL;
+return -TARGET_EINVAL;
 lv = sizeof(int);
 ret = get_errno(getsockopt(sockfd, level, optname, val, lv));
 if (ret  0)
@@ -884,7 +890,7 @@
 case IP_MULTICAST_LOOP:
 len = tget32(optlen);
 if (len  0)
-return -EINVAL;
+return -TARGET_EINVAL;
 lv = sizeof(int);
 ret = get_errno(getsockopt(sockfd, level, optname, val, lv));
 if (ret  0)
@@ -908,7 +914,7 @@
 unimplemented:
 gemu_log(getsockopt level=%d optname=%d not yet supported\n,
  level, optname);
-ret = -ENOSYS;
+ret = -TARGET_ENOSYS;
 break;
 }
 return ret;
@@ -945,6 +951,7 @@
 unlock_user (target_vec, target_addr, 0);
 }
 
+/* do_socket() Must return target values and target errnos. */
 static target_long do_socket(int domain, int type, int protocol)
 {
 #if defined(TARGET_MIPS)
@@ -972,6 +979,7 @@
 return get_errno(socket(domain, type, protocol));
 }
 
+/* do_bind() Must return target values and target errnos. */
 static target_long do_bind(int sockfd, target_ulong target_addr,
socklen_t addrlen)
 {
@@ -981,6 +989,7 @@
 return get_errno(bind(sockfd, addr, addrlen

Re: [Qemu-devel] qemu-i386 does not start on x86_64 or i686

2007-10-22 Thread Thayne Harbaugh

On Thu, 2007-10-18 at 23:46 +0200, Ronan Keryell wrote:
 Anybody kind enough to have a look at :
 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=446868
 
 I've asked some other people and they hit the same issue.
 It's not clear to me where the bug is since it happens very early in the
 starting process...


I've been using this patch:

Index: qemu/linux-user/main.c
===
--- qemu.orig/linux-user/main.c 2007-10-15 13:52:13.0 -0600
+++ qemu/linux-user/main.c  2007-10-15 13:52:13.0 -0600
@@ -44,7 +44,7 @@
 
 /* for recent libc, we add these dummy symbols which are not declared
when generating a linked object (bug in ld ?) */
-#if (__GLIBC__  2 || (__GLIBC__ == 2  __GLIBC_MINOR__ = 3))  
!defined(CONFIG_STATIC)
+#if (__GLIBC__ == 2  __GLIBC_MINOR__ == 3)  !defined(CONFIG_STATIC)
 long __preinit_array_start[0];
 long __preinit_array_end[0];
 long __init_array_start[0];






Re: [Qemu-devel] What happened with NPTL/TLS support?

2007-10-22 Thread Thayne Harbaugh

On Sat, 2007-10-20 at 21:34 +0100, Thiemo Seufer wrote:
 Thayne Harbaugh wrote:
  
  On Fri, 2007-10-12 at 18:12 +0300, Felipe Contreras wrote:
   Hi,
   
   When I try to use codesourcery's toolchain arm-2006q3-27 in my Fedora
   7 box I always have the following issue:
   
   qemu: Unsupported syscall: 983045
  
  Yep, I've seen that before.
  
   I guess it's a problem of NPTL incompatibility. Anyway, the patch that
   Paul Brook sent a while ago solves it [1].
   
   I wonder if it can be integrated or what would be the right way to
   solve this issue. Am I the only one having it?
   
   Best regards.
   
   [1] http://lists.gnu.org/archive/html/qemu-devel/2005-08/msg00128.html
  
  
  I've been using this patch, as well as other NPTL/TLS patches as well as
  some of my own work and have a set of patches for NPTL/TLS that works
  reasonably well for arm and i386.  The patches don't apply cleanly to
  CVS current, but I'm more than happy to rework them so that they will if
  someone is serious about getting NPTL/TLS/futex stuff working for
  linux-user.  I haven't submitted my patches because I kept expecting the
  other patches to be accepted.
 
 Please submit this patch (and resend what you think was missed).

I'll get them reworked and re-sent soon.

Thanks for the interest.





Re: [Qemu-devel] qemu-i386 does not start on x86_64 or i686

2007-10-25 Thread Thayne Harbaugh

On Thu, 2007-10-25 at 19:52 -0500, Rob Landley wrote:
 On Monday 22 October 2007 8:44:59 am Thayne Harbaugh wrote:
  On Thu, 2007-10-18 at 23:46 +0200, Ronan Keryell wrote:
   Anybody kind enough to have a look at :
   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=446868
  
   I've asked some other people and they hit the same issue.
   It's not clear to me where the bug is since it happens very early in the
   starting process...
 
  I've been using this patch:
 
  Index: qemu/linux-user/main.c
  ===
  --- qemu.orig/linux-user/main.c 2007-10-15 13:52:13.0 -0600
  +++ qemu/linux-user/main.c  2007-10-15 13:52:13.0 -0600
  @@ -44,7 +44,7 @@
 
   /* for recent libc, we add these dummy symbols which are not declared
  when generating a linked object (bug in ld ?) */
  -#if (__GLIBC__  2 || (__GLIBC__ == 2  __GLIBC_MINOR__ = 3)) 
  !defined(CONFIG_STATIC) +#if (__GLIBC__ == 2  __GLIBC_MINOR__ == 3) 
  !defined(CONFIG_STATIC) long __preinit_array_start[0];
   long __preinit_array_end[0];
   long __init_array_start[0];
 
 When I tried it, it went:
 
 gcc-3.4 -Wall -O2 -g -fno-strict-aliasing -I. -I.. 
 -I/home/landley/qemu/git/target-i386 -I/home/landley/qemu/git 
 -I/home/landley/qemu/git/linux-user -I/home/landley/qemu/git/linux-user/i386 
 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 
 -I/home/landley/qemu/git/fpu -DHAS_AUDIO -DHAS_AUDIO_CHOICE 
 -I/home/landley/qemu/git/slirp-c -o 
 main.o /home/landley/qemu/git/linux-user/main.c
 gcc-3.4 -g  -Wl,-shared   -o qemu-i386 main.o syscall.o mmap.o signal.o 
 path.o 
 osdep.o thunk.o elfload.o linuxload.o vm86.o libqemu.a gdbstub.o   -lm -lrt
 /usr/lib/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
 (.text+0x2b): undefined reference to `__init_array_end'
 /usr/lib/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
 (.text+0x34): undefined reference to `__init_array_start'
 /usr/bin/ld: qemu-i386: hidden symbol `__init_array_end' isn't defined
 /usr/bin/ld: final link failed: Nonrepresentable section on output
 collect2: ld returned 1 exit status
 make[1]: *** [qemu-i386] Error 1
 make[1]: Leaving directory `/home/landley/qemu/git/i386-linux-user'
 make: *** [subdir-i386-linux-user] Error 2

Ick.  There's some funky magic going on in qemu/x86_64.ld and the above
patch is a hack-around.  The segfault is caused by preinit_array
function pointers (which are NULL) being dereferenced.  This is a great
opportunity for you to put your super-sleuth skills to work and figure
out the details and fix it. 8^)

 Have you tried it with current cvs on Ubuntu 7.04?  (qemu-i386 has never 
 worked for me built on that.)

Sorry - I'm doing work on Debian Lenny.





[Qemu-devel] [PATCH] efault - verify pages are in cache and are read/write

2007-10-31 Thread Thayne Harbaugh
This patch adds the function page_check_range() to verify that pages are
in the cache and that they are appropriately readable/writable.  It also
hooks up access_ok() to page_check_range() so that code patterns are
similar to kernel code.

When copying data from user space access_ok() is used to check that
pages are readable.  When copying data to user space access_ok() is used
to check that pages are writable.
Index: qemu/exec.c
===
--- qemu.orig/exec.c	2007-10-31 10:49:10.0 -0600
+++ qemu/exec.c	2007-10-31 10:55:50.0 -0600
@@ -1875,6 +1875,33 @@
 spin_unlock(tb_lock);
 }
 
+int page_check_range(target_ulong start, target_ulong len, int flags)
+{
+PageDesc *p;
+target_ulong end;
+target_ulong addr;
+
+end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
+start = start  TARGET_PAGE_MASK;
+
+if( end  start )
+/* we've wrapped around */
+return -1;
+for(addr = start; addr  end; addr += TARGET_PAGE_SIZE) {
+p = page_find(addr  TARGET_PAGE_BITS);
+if( !p )
+return -1;
+if( !(p-flags  PAGE_VALID) )
+return -1;
+
+if (!(p-flags  PAGE_READ)  (flags  PAGE_READ) )
+return -1;
+if (!(p-flags  PAGE_WRITE)  (flags  PAGE_WRITE) )
+return -1;
+}
+return 0;
+}
+
 /* called from signal handler: invalidate the code and unprotect the
page. Return TRUE if the fault was succesfully handled. */
 int page_unprotect(target_ulong address, unsigned long pc, void *puc)
Index: qemu/cpu-all.h
===
--- qemu.orig/cpu-all.h	2007-10-31 10:49:10.0 -0600
+++ qemu/cpu-all.h	2007-10-31 10:55:50.0 -0600
@@ -691,6 +691,7 @@
 int page_get_flags(target_ulong address);
 void page_set_flags(target_ulong start, target_ulong end, int flags);
 void page_unprotect_range(target_ulong data, target_ulong data_size);
+int page_check_range(target_ulong start, target_ulong len, int flags);
 
 CPUState *cpu_copy(CPUState *env);
 
Index: qemu/linux-user/qemu.h
===
--- qemu.orig/linux-user/qemu.h	2007-10-31 10:55:48.0 -0600
+++ qemu/linux-user/qemu.h	2007-10-31 10:55:50.0 -0600
@@ -185,7 +185,8 @@
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
-#define access_ok(type,addr,size) (1)
+#define access_ok(type,addr,size) \
+(page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0)
 
 /* NOTE get_user and put_user use host addresses.  */
 #define __put_user(x,ptr)\


[Qemu-devel] Re: [PATCH] efault - add data type to put_user()/get_user()

2007-10-31 Thread Thayne Harbaugh
This patch updates get_user() and put_user() to take a third argument of
data type.  get_user() and put_user() use target address which are
target_ulong and don't reflect the data type pointed to in target
memory.

Simply casting the target_ulong to a type before passing to
get/put_user() is poor because target_ulong isn't always a simple cast
to a host type (consider 32 bit on 64 bit where address are either
extended or truncate).  Also, simple casting of the argument to
get/put_user() results in several warnings when target and long pointer
sizes don't match.

This patch has additional updates to fix places where get/put_user() are
already used.

Index: qemu/linux-user/qemu.h
===
--- qemu.orig/linux-user/qemu.h	2007-10-30 07:56:57.0 -0600
+++ qemu/linux-user/qemu.h	2007-10-30 17:55:57.0 -0600
@@ -230,26 +231,47 @@
 0;\
 })
 
-#define put_user(x,ptr)\
+/* put_user()/get_user() take a guest address and check access */
+#define put_user(x, gaddr, target_type)\
 ({\
 int __ret;\
-if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
-__ret = __put_user(x, ptr);\
+if (access_ok(VERIFY_WRITE, gaddr, sizeof(target_type)))\
+__ret = __put_user(x, (target_type)g2h(gaddr));	\
 else\
-__ret = -EFAULT;\
+__ret = -TARGET_EFAULT;\
 __ret;\
 })
 
-#define get_user(x,ptr)\
+#define get_user(x, gaddr, target_type)\
 ({\
 int __ret;\
-if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
-__ret = __get_user(x, ptr);\
+if (access_ok(VERIFY_READ, gaddr, sizeof(target_type)))\
+__ret = __get_user(x, (target_type)g2h(gaddr));	\
 else\
-__ret = -EFAULT;\
+__ret = -TARGET_EFAULT;\
 __ret;\
 })
 
+#define copy_from_user(hptr, gaddr, len) \
+({  \
+int __cfu_ret=0;\
+if (access_ok(VERIFY_READ, gaddr, (len)))\
+memcpy(hptr, g2h(gaddr), (len)); \
+else\
+__cfu_ret = -TARGET_EFAULT; \
+__cfu_ret;  \
+})
+
+#define copy_to_user(gaddr, hptr, len)   \
+({  \
+int __ctu_ret=0;\
+if (access_ok(VERIFY_WRITE, gaddr, (len)))   \
+memcpy(g2h(gaddr), hptr, (len)); \
+else\
+__ctu_ret = -TARGET_EFAULT; \
+__ctu_ret;  \
+})
+
 /* Functions for accessing guest memory.  The tget and tput functions
read/write single values, byteswapping as neccessary.  The lock_user
gets a pointer to a contiguous area of guest memory, but does not perform
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-10-30 07:56:57.0 -0600
+++ qemu/linux-user/syscall.c	2007-10-30 17:56:06.0 -0600
@@ -1757,7 +1757,7 @@
 break;
 	}
 	}
-	if (put_user(raddr, (target_ulong *)third))
+	if (put_user(raddr, third, target_ulong *))
 return -TARGET_EFAULT;
 ret = 0;
 	break;
@@ -3689,17 +3689,16 @@
 struct target_statfs *target_stfs;
 
 lock_user_struct(target_stfs, arg2, 0);
-/* ??? put_user is probably wrong.  */
-put_user(stfs.f_type, target_stfs-f_type);
-put_user(stfs.f_bsize, target_stfs-f_bsize);
-put_user(stfs.f_blocks, target_stfs-f_blocks);
-put_user(stfs.f_bfree, target_stfs-f_bfree);
-put_user(stfs.f_bavail, target_stfs-f_bavail);
-put_user(stfs.f_files, target_stfs-f_files);
-put_user(stfs.f_ffree, target_stfs-f_ffree);
-put_user(stfs.f_fsid.__val[0], target_stfs-f_fsid.val[0]);
-put_user(stfs.f_fsid.__val[1], target_stfs-f_fsid.val[1]);
-put_user(stfs.f_namelen, target_stfs-f_namelen);
+__put_user(stfs.f_type, target_stfs-f_type);
+__put_user(stfs.f_bsize, target_stfs-f_bsize);
+__put_user(stfs.f_blocks, target_stfs-f_blocks);
+__put_user(stfs.f_bfree, target_stfs-f_bfree);
+__put_user(stfs.f_bavail, target_stfs-f_bavail);
+__put_user(stfs.f_files, target_stfs-f_files);
+__put_user(stfs.f_ffree, target_stfs-f_ffree);
+__put_user(stfs.f_fsid.__val[0], target_stfs-f_fsid.val[0]);
+__put_user(stfs.f_fsid.__val[1], target_stfs-f_fsid.val[1]);
+__put_user(stfs.f_namelen, target_stfs-f_namelen);
 unlock_user_struct(target_stfs, arg2, 1);
 }
 break;
@@ -3716,17 +3715,16 @@
 struct target_statfs64 *target_stfs;
 
 lock_user_struct(target_stfs, arg3, 0);
-/* ??? put_user is probably wrong.  */
-

[Qemu-devel] Re: [PATCH] efault

2007-10-31 Thread Thayne Harbaugh
These three efault patches are the basis for another 30 patches which do
the following:

* Correct compiler warnings.
* Add coding consistency.
* Detect error cases and handle them properly.
* Divide syscall.c to closer resemble the Linux kernel for code
partitioning and organization.
* Add new features and functionality.
* Correct errors from previous patches that I've sent 8^)

I'd appreciate feed back and comments.  When I can make these patches
acceptable then I'll be able to send the additional patches and have
them meet the same design requirements.

Thanks.





[Qemu-devel] Re: [PATCH] efault - update __get_user() __put_user()

2007-10-31 Thread Thayne Harbaugh
This patch is a minor update to __get_user() and __put_user() to
emphasize that they take host points.
Index: qemu/linux-user/qemu.h
===
--- qemu.orig/linux-user/qemu.h	2007-10-31 11:03:03.0 -0600
+++ qemu/linux-user/qemu.h	2007-10-31 11:04:04.0 -0600
@@ -188,22 +188,22 @@
 #define access_ok(type,addr,size) \
 (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0)
 
-/* NOTE get_user and put_user use host addresses.  */
-#define __put_user(x,ptr)\
+/* NOTE __get_user and __put_user use host pointers and don't check access. */
+#define __put_user(x, hptr)\
 ({\
-int size = sizeof(*ptr);\
+int size = sizeof(*hptr);\
 switch(size) {\
 case 1:\
-*(uint8_t *)(ptr) = (typeof(*ptr))(x);\
+*(uint8_t *)(hptr) = (typeof(*hptr))(x);\
 break;\
 case 2:\
-*(uint16_t *)(ptr) = tswap16((typeof(*ptr))(x));\
+*(uint16_t *)(hptr) = tswap16((typeof(*hptr))(x));\
 break;\
 case 4:\
-*(uint32_t *)(ptr) = tswap32((typeof(*ptr))(x));\
+*(uint32_t *)(hptr) = tswap32((typeof(*hptr))(x));\
 break;\
 case 8:\
-*(uint64_t *)(ptr) = tswap64((typeof(*ptr))(x));\
+*(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\
 break;\
 default:\
 abort();\
@@ -211,21 +211,21 @@
 0;\
 })
 
-#define __get_user(x, ptr) \
+#define __get_user(x, hptr) \
 ({\
-int size = sizeof(*ptr);\
+int size = sizeof(*hptr);\
 switch(size) {\
 case 1:\
-x = (typeof(*ptr))*(uint8_t *)(ptr);\
+x = (typeof(*hptr))*(uint8_t *)(hptr);\
 break;\
 case 2:\
-x = (typeof(*ptr))tswap16(*(uint16_t *)(ptr));\
+x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\
 break;\
 case 4:\
-x = (typeof(*ptr))tswap32(*(uint32_t *)(ptr));\
+x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\
 break;\
 case 8:\
-x = (typeof(*ptr))tswap64(*(uint64_t *)(ptr));\
+x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\
 break;\
 default:\
 abort();\


Re: [Qemu-devel] [PATCH] strace rework

2007-10-31 Thread Thayne Harbaugh

On Thu, 2007-11-01 at 00:09 +, Thiemo Seufer wrote:
 Thayne Harbaugh wrote:
  
  On Sat, 2007-10-27 at 14:26 +0100, Thiemo Seufer wrote:
   Thayne Harbaugh wrote:
This is a rework of Stuart Anderson's strace patch.  I've fixed
target-to-host and host-to-target syscall lookups so that the proper
host or target errno is returned.
   
   It didn't build for me due to the a missing target_to_host_errno
   function.
  
  This isn't obvious to me.  It also doesn't appear that you included this
  error in the output you sent.
  
Could you also have a look at the compiler warnings
   from strace.c? I see e.g.:
  
  miles of warnings deleted
  
  Thank you for sending me the warnings.  I've reworked it so that
  function arguments are passed correctly, target addresses have access
  checked and locked and that proper print format codes are used.
  
  Attached is the new version.  Please send me feedback.
 
 Comitted. Could you also cook up a patch which documents the feature?

Awesome!  Thank you.

Yes, I'll be writing piles of documentation from user docs to
development code guides.  Is there a directory that we can dump things
into?





[Qemu-devel] Re: [PATCH] efault - add data type to put_user()/get_user()

2007-11-02 Thread Thayne Harbaugh

On Wed, 2007-10-31 at 16:44 -0600, Thayne Harbaugh wrote:
 This patch updates get_user() and put_user() to take a third argument of
 data type.  get_user() and put_user() use target address which are
 target_ulong and don't reflect the data type pointed to in target
 memory.
 
 Simply casting the target_ulong to a type before passing to
 get/put_user() is poor because target_ulong isn't always a simple cast
 to a host type (consider 32 bit on 64 bit where address are either
 extended or truncate).  Also, simple casting of the argument to
 get/put_user() results in several warnings when target and long pointer
 sizes don't match.
 
 This patch has additional updates to fix places where get/put_user() are
 already used.

This is an updated patch that doesn't conflict with the
abi_long/abi_ulong changes from a couple weeks ago.
Index: qemu/linux-user/qemu.h
===
--- qemu.orig/linux-user/qemu.h	2007-10-30 07:56:57.0 -0600
+++ qemu/linux-user/qemu.h	2007-10-30 17:55:57.0 -0600
@@ -230,26 +231,47 @@
 0;\
 })
 
-#define put_user(x,ptr)\
+/* put_user()/get_user() take a guest address and check access */
+#define put_user(x, gaddr, target_type)\
 ({\
 int __ret;\
-if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
-__ret = __put_user(x, ptr);\
+if (access_ok(VERIFY_WRITE, gaddr, sizeof(target_type)))\
+__ret = __put_user(x, (target_type)g2h(gaddr));	\
 else\
-__ret = -EFAULT;\
+__ret = -TARGET_EFAULT;\
 __ret;\
 })
 
-#define get_user(x,ptr)\
+#define get_user(x, gaddr, target_type)\
 ({\
 int __ret;\
-if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
-__ret = __get_user(x, ptr);\
+if (access_ok(VERIFY_READ, gaddr, sizeof(target_type)))\
+__ret = __get_user(x, (target_type)g2h(gaddr));	\
 else\
-__ret = -EFAULT;\
+__ret = -TARGET_EFAULT;\
 __ret;\
 })
 
+#define copy_from_user(hptr, gaddr, len) \
+({  \
+int __cfu_ret=0;\
+if (access_ok(VERIFY_READ, gaddr, (len)))\
+memcpy(hptr, g2h(gaddr), (len)); \
+else\
+__cfu_ret = -TARGET_EFAULT; \
+__cfu_ret;  \
+})
+
+#define copy_to_user(gaddr, hptr, len)   \
+({  \
+int __ctu_ret=0;\
+if (access_ok(VERIFY_WRITE, gaddr, (len)))   \
+memcpy(g2h(gaddr), hptr, (len)); \
+else\
+__ctu_ret = -TARGET_EFAULT; \
+__ctu_ret;  \
+})
+
 /* Functions for accessing guest memory.  The tget and tput functions
read/write single values, byteswapping as neccessary.  The lock_user
gets a pointer to a contiguous area of guest memory, but does not perform
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-10-30 07:56:57.0 -0600
+++ qemu/linux-user/syscall.c	2007-10-30 17:56:06.0 -0600
@@ -1757,7 +1757,7 @@
 break;
 	}
 	}
-	if (put_user(raddr, (abi_ulong *)third))
+if (put_user(raddr, third, abi_ulong *))
 return -TARGET_EFAULT;
 ret = 0;
 	break;
@@ -3689,17 +3689,16 @@
 struct target_statfs *target_stfs;
 
 lock_user_struct(target_stfs, arg2, 0);
-/* ??? put_user is probably wrong.  */
-put_user(stfs.f_type, target_stfs-f_type);
-put_user(stfs.f_bsize, target_stfs-f_bsize);
-put_user(stfs.f_blocks, target_stfs-f_blocks);
-put_user(stfs.f_bfree, target_stfs-f_bfree);
-put_user(stfs.f_bavail, target_stfs-f_bavail);
-put_user(stfs.f_files, target_stfs-f_files);
-put_user(stfs.f_ffree, target_stfs-f_ffree);
-put_user(stfs.f_fsid.__val[0], target_stfs-f_fsid.val[0]);
-put_user(stfs.f_fsid.__val[1], target_stfs-f_fsid.val[1]);
-put_user(stfs.f_namelen, target_stfs-f_namelen);
+__put_user(stfs.f_type, target_stfs-f_type);
+__put_user(stfs.f_bsize, target_stfs-f_bsize);
+__put_user(stfs.f_blocks, target_stfs-f_blocks);
+__put_user(stfs.f_bfree, target_stfs-f_bfree);
+__put_user(stfs.f_bavail, target_stfs-f_bavail);
+__put_user(stfs.f_files, target_stfs-f_files);
+__put_user(stfs.f_ffree, target_stfs-f_ffree);
+__put_user(stfs.f_fsid.__val[0], target_stfs-f_fsid.val[0]);
+__put_user(stfs.f_fsid.__val[1], target_stfs-f_fsid.val[1]);
+__put_user(stfs.f_namelen, target_stfs-f_namelen);
 unlock_user_struct(target_stfs, arg2, 1);
 }
 break;
@@ -3716,17 +3715,16

[Qemu-devel] [RFC] linux-user (mostly syscall.c)

2007-11-02 Thread Thayne Harbaugh
There are several things that I'd like to see addressed in linux-user.
Some of these are to fix bugs, some are to make qemu linux-user more
like the Linux kernel, some are to make the internal qemu interfaces
more consistent.

An internal coding practice that is being addressed bit-by-bit is that
of managing the interface between the host and the target.  Currently
this is a bit sloppy and inconsistent (some of which I've contributed
to).  There are examples of using target addresses for host pointers and
host errnos for target errnos, using different types between target and
host that don't sign-extend properly, as well as other things.  This
causes compiler warnings to actual run-time bugs.  Currently I'm
reviewing all of the linux-user code (mostly syscall.c) to fix these
inconsistencies.  I will be writing developer documentation describing
the coding practices that should govern the target/host interface and
submitting patches for the fixes.

As obvious as it may seem I'll re-state that the linux-user emulation is
emulating the Linux kernel (duh!).  There are portions of qemu
linux-user that are even excerpted directly from the Linux kernel.
Consequently it is useful for internal qemu data and functions to
closely mimic the kernel for best code sharing.  There are also
advantages to even structuring qemu directly and file organization in
similar divisions, groupings and locations.  Some of this organization
might lead to good division so that other user/kernel divisions are
cleaner (different kernel versions, other OSes - darwin-user and
others).

Internal qemu interfaces are consistent - except when they aren't.  This
causes coding errors when passing target and host arguments or return
codes.  I'll be documenting the coding practices as well as submitting
patches to make these consistent.  (That sounds a bit redundant with
other things I've mentioned).

I have about 40 patches already worked up that do this.  Some of those
patches might be broken up smaller.  The qemu that we've been working
with is nearly rock solid (still a few more bugs being wrung out).  It
can nearly build an entire Debian arm distribution for an arm target
being hosted on x86_64.  We're quite excited to get our patches upstream
so that others can benefit and to ease our maintenance overhead.  We're
also turning our focus to PPC and other archs.

Please let me know if you support the general idea of the coding changes
above: General clean-up, consistent target/host interfaces, file
splitting/reorganizing, etc..  In the meantime I'll be putting together
the developer documentation/coding guidelines for review.

Thank you.





Re: [Qemu-devel] [RFC] linux-user (mostly syscall.c)

2007-11-03 Thread Thayne Harbaugh

On Sat, 2007-11-03 at 13:52 +0100, J. Mayer wrote:
 On Sat, 2007-11-03 at 01:21 +, Thiemo Seufer wrote:
  Thayne Harbaugh wrote:
   There are several things that I'd like to see addressed in linux-user.
   Some of these are to fix bugs, some are to make qemu linux-user more
   like the Linux kernel, some are to make the internal qemu interfaces
   more consistent.
   
   An internal coding practice that is being addressed bit-by-bit is that
   of managing the interface between the host and the target.  Currently
   this is a bit sloppy and inconsistent (some of which I've contributed
   to).  There are examples of using target addresses for host pointers and
   host errnos for target errnos, using different types between target and
   host that don't sign-extend properly, as well as other things.  This
   causes compiler warnings to actual run-time bugs.  Currently I'm
   reviewing all of the linux-user code (mostly syscall.c) to fix these
   inconsistencies.  I will be writing developer documentation describing
   the coding practices that should govern the target/host interface and
   submitting patches for the fixes.
   
   As obvious as it may seem I'll re-state that the linux-user emulation is
   emulating the Linux kernel (duh!).  There are portions of qemu
   linux-user that are even excerpted directly from the Linux kernel.
   Consequently it is useful for internal qemu data and functions to
   closely mimic the kernel for best code sharing.  There are also
   advantages to even structuring qemu directly and file organization in
   similar divisions, groupings and locations.  Some of this organization
   might lead to good division so that other user/kernel divisions are
   cleaner (different kernel versions, other OSes - darwin-user and
   others).
   
   Internal qemu interfaces are consistent - except when they aren't.  This
   causes coding errors when passing target and host arguments or return
   codes.  I'll be documenting the coding practices as well as submitting
   patches to make these consistent.  (That sounds a bit redundant with
   other things I've mentioned).
   
   I have about 40 patches already worked up that do this.  Some of those
   patches might be broken up smaller.  The qemu that we've been working
   with is nearly rock solid (still a few more bugs being wrung out).  It
   can nearly build an entire Debian arm distribution for an arm target
   being hosted on x86_64.  We're quite excited to get our patches upstream
   so that others can benefit and to ease our maintenance overhead.  We're
   also turning our focus to PPC and other archs.
   
   Please let me know if you support the general idea of the coding changes
   above: General clean-up, consistent target/host interfaces, file
   splitting/reorganizing, etc..  In the meantime I'll be putting together
   the developer documentation/coding guidelines for review.
  
  FWIW, I agree with everything you said above.
 
 I agree too.
 Code cleanup and sanitization is needed there.
 I'm just reserved about the code splitting point: as for the vl.h
 splitting, it should not lead to get files with only a single or two
 small function inside.

Right now I have it split similar to the Linux kernel.  It has
reasonable code grouping and makes it easy to compare code with the
kernel.

  But it could be great to group the syscalls by
 categories, or so. For example, putting all POSIX compliant syscalls in
 a single file and using a syscall table could make quite easy to develop
 a BSD-user target (I did this in the past, not in Qemu though...). POSIX
 compliant interfaces can mostly be shared with Linux ones and a lot of
 other syscalls are common to the 3 BSD flavors (Net, Open and Free..).
 Being able to add a BSD target sharing the same code would be a proof
 the code is flexible and well organized; I guess large parts of the
 Darwin user target could also be merged with a FreeBSD user target...

That's a reasonable strategy as well.  I've looked through some of the
darwin code and have considered how common code could be merged.

 Just my few cents ideas, don't say it has to be implemented soon, just
 think keeping those long-term goals in mind may help having a flexible
 and clean implementation...

It's likely closer than you realize. 8-)





Re: [Qemu-devel] [RFC] linux-user (mostly syscall.c)

2007-11-03 Thread Thayne Harbaugh

On Sat, 2007-11-03 at 20:13 +0100, Fabrice Bellard wrote:
 Thayne Harbaugh wrote:
  On Sat, 2007-11-03 at 13:52 +0100, J. Mayer wrote:
  On Sat, 2007-11-03 at 01:21 +, Thiemo Seufer wrote:
  [...]
   But it could be great to group the syscalls by
  categories, or so. For example, putting all POSIX compliant syscalls in
  a single file and using a syscall table could make quite easy to develop
  a BSD-user target (I did this in the past, not in Qemu though...). POSIX
  compliant interfaces can mostly be shared with Linux ones and a lot of
  other syscalls are common to the 3 BSD flavors (Net, Open and Free..).
  Being able to add a BSD target sharing the same code would be a proof
  the code is flexible and well organized; I guess large parts of the
  Darwin user target could also be merged with a FreeBSD user target...
  
  That's a reasonable strategy as well.  I've looked through some of the
  darwin code and have considered how common code could be merged.
 
 I am strongly against such merges.
 
 Different OS emulation must be handled in different directories (and
 maybe even in different projects) as they are likely to have subtle
 differences which makes impossible to test a modification made for one
 OS without testing all the other OSes.

Agreed.





Re: [Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer of different size' problems?

2007-11-05 Thread Thayne Harbaugh

On Sat, 2007-11-03 at 18:52 +0100, Paul Brook wrote:
 On Saturday 03 November 2007, TJ wrote:
  I'm building on x86_64 GNU/Linux. There are *lots* of (1053) compiler
  warnings of the class:
 
  warning: cast to pointer from integer of different size
 
 There are at due to the recent EFAULT/access_ok changes. There should be (and 
 used to be) a clear separation between host and target addresses. The EFAULT 
 changes have broken this. Before these ghanges it wa trivial to remap the 
 target address space (e.g. place it at a high address on a 64-bit host), or 
 even enabling softmmu. I'm fairly sure that wouldn't work if you tried it 
 now.

No, the EFAULT/access_ok() didn't cause it exactly.  The problem is that
access_ok() came from kernel code and was dummied-out to always be true.
While it was turned off it was used with arguments that weren't
appropriate.  Turning on access_ok() caused all of the incorrect usages
to suddenly show up.  As an asside, the access_ok() is usually out of
order with the lock_user() calls - access_ok() should come first.

There were also additional incorrect pointer usages that have nothing to
do with EFAULT/access_ok() but usually don't get noticed when building
on 32bit arch.

  Fixing it looks to require a variety of fixes, from simple explicit
  casts in-line, to some complicated review of multiple levels of macros
  to decide where best to apply a fix.
 
 Adding a cast is never the right thing to do. There should *always* be a 
 clear 
 distinction and explicit conversion between host pointers and target 
 addresses. It is never safe to cast from one to the other.

Agreed.

 I put quite a lot of effort into getting this separation right when I 
 implemented the lock_user interfaces. It was fairly trivial to implement 
 address space translation (even softmmu) using this inerface. I'm quite 
 annoyed that we seem to have regresses so badly in this area. AFAICS the 
 whole of syscalls.c needs re-auditing to figure out which values are host 
 pointers and which are target addresses.

I've actually done the audit and have all the fixes queued to submit to
the list.

 We should have either lock_user or {get,put}_user, not both.

Now that's a bit of a discussion.  It's possible to push everything into
{get,put}_user() but I don't think that's quite appropriate.  Let's look
at everything that's going on:

1) page in cache with proper permissions
2) address translation

1 is performed by access_ok() which returns true/false.  2 is
performed by lock_user() which internally uses g2h() to perform the
address translation and returns the translated address.  lock_user() can
also do memory replication/flushing to test that the memory calls are
coded correctly even when the implementation doesn't actually perform
address translation.

access_ok() and lock_user() perform essential functions.  lock_user(),
however, isn't directly comparable to how the kernel operates and should
therefore be encapsulated inside more typical kernel functions such as
{get,put}_user(), copy_{to,from}_user() and the like.  access_ok() and
lock_user() also have overhead and should therefore be used with the
largest memory hunks possible (e.g.: they should be used with an entire
structure - not with each individual data member of the structure).
That is why __{get,put}_user() exist: for copying the individual data
members of a structure once the *entire* structure has had access
checked and the address translation is performed.

The clean-ups that I am sending will follow the following guidelines:

* abi_long/abi_ulong will be passed as function arguments at the
high-level and all direct syscall wrappers, as well as do_*() functions
will only receive those types from user space as well as will only
return abi_long types.

* type casts will be removed.

* all target/host interactions will happen through {get,put}_user() and
copy_{to,from}_user() just like in the kernel.  These will accept a
target address in an abi_ulong, do access_ok(), do lock_user() and map
the target address to a host address and then perform the get/put or
copy_to/from with the appropriate unlock_user() afterwords.

  * {get,put}_user() will be used for individual data types that are
passed.

  * copy_{to,from}_user_struct() will be used for structures:

static inline abi_long copy_from_user_flock(struct flock *host_fl,
abi_ulong target_fl_addr)
{
struct target_flock *target_fl;

if (!access_ok(VERIFY_READ, target_fl_addr, sizeof(*target_fl)))
return -TARGET_EFAULT;

lock_user_struct(target_fl, target_fl_addr, 1);

__get_user(host_fl-l_type, (target_fl-l_type));
__get_user(host_fl-l_whence, (target_fl-l_whence));
__get_user(host_fl-l_start, (target_fl-l_start));
__get_user(host_fl-l_len, (target_fl-l_len));
__get_user(host_fl-l_pid, (target_fl-l_pid));

lock_user_struct(target_fl, target_fl_addr, 0);

return 0;
}


This effectively eliminates all 

Re: [Qemu-devel] Re: [PATCH] efault - add data type to put_user()/get_user()

2007-11-05 Thread Thayne Harbaugh

On Sat, 2007-11-03 at 20:05 +0100, Fabrice Bellard wrote:
 I think that using host addresses in __put_user and __get_user is not
 logical. They should use target addresses as get_user and put_user. As
 Paul said, It is not worth mixing get/put/copy and lock/unlock functions.

Please see the RFC: x86_64 Best way to fix 'cast to pointer' email for
some discussion of get/put/copy and lock/unlock.  {get,put}_user() is
used for individual ints or other atomically writable types that are
passed as pointers into a syscall.  copy_{to,from}_user_struct() are
used for structures that are passed to a syscall.  lock/unlock() will be
used internally in these because lock/unlock does address translation.
lock/unlock() are still needed and are independent.  __{get,put}_user()
will operate internally in these functions on structure data members
where lock/unlock() access_ok() have already been called.

 The ultimate goal of such cleanup is not only to generate -EFAULT
 correctly but also to be able to have arbitrary address space changes.

Yes.  This will be possible once all my clean-ups are pushed.

 In fact it would be good to be able to introduce an arbitrary address
 space change (such as a translation as Paul did) so that we can verify
 that all the Linux emulation stills works in this case.

I'll be testing this way.

 Regards,
 
 Fabrice.
 
 Thayne Harbaugh wrote:
  On Wed, 2007-10-31 at 16:44 -0600, Thayne Harbaugh wrote:
  This patch updates get_user() and put_user() to take a third argument of
  data type.  get_user() and put_user() use target address which are
  target_ulong and don't reflect the data type pointed to in target
  memory.
 
  Simply casting the target_ulong to a type before passing to
  get/put_user() is poor because target_ulong isn't always a simple cast
  to a host type (consider 32 bit on 64 bit where address are either
  extended or truncate).  Also, simple casting of the argument to
  get/put_user() results in several warnings when target and long pointer
  sizes don't match.
 
  This patch has additional updates to fix places where get/put_user() are
  already used.
  
  This is an updated patch that doesn't conflict with the
  abi_long/abi_ulong changes from a couple weeks ago.





Re: [Qemu-devel] Re: [PATCH] efault - add data type to put_user()/get_user()

2007-11-05 Thread Thayne Harbaugh
Uhhh, I'm quite uncomfortable now.  After sending the emails describing
how everything should be done I realized that I had never reworked my
base patches.  All my higher-level patches are sound, but I never
reworked my {get,put}_user() and copy_{to,from}_user() patches to follow
the same pattern.

Fixes are short coming.

Thanks for your patience.





Re: [Qemu-devel] Re: [PATCH] efault - add data type to put_user()/get_user()

2007-11-05 Thread Thayne Harbaugh

On Mon, 2007-11-05 at 22:42 +0100, Fabrice Bellard wrote:
 Thayne Harbaugh wrote:
  On Sat, 2007-11-03 at 20:05 +0100, Fabrice Bellard wrote:
  I think that using host addresses in __put_user and __get_user is not
  logical. They should use target addresses as get_user and put_user. As
  Paul said, It is not worth mixing get/put/copy and lock/unlock functions.
  
  Please see the RFC: x86_64 Best way to fix 'cast to pointer' email for
  some discussion of get/put/copy and lock/unlock.  {get,put}_user() is
  used for individual ints or other atomically writable types that are
  passed as pointers into a syscall.  copy_{to,from}_user_struct() are
  used for structures that are passed to a syscall.  lock/unlock() will be
  used internally in these because lock/unlock does address translation.
  lock/unlock() are still needed and are independent.  __{get,put}_user()
  will operate internally in these functions on structure data members
  where lock/unlock() access_ok() have already been called.
 
 I believed I was clear : once you keep lock/unlock, there is no point in
 modifying the code to use put_user/get_user and copy[to,from]_user.

without lock/unlock how do you propose that target/host address
translation be performed?  Are you suggesting a g2h() inside of
copy_{to,from}_user()?

 So either you keep the code as it is and extend lock and unlock to
 return an error code or you suppress all lock/unlock to use a Linux like
 API (i.e. put_user/get_user , copy[to,from]_user, access_ok,
 __put_user/__get_user).

The error code because lock/unlock_user would then call access_ok()?

 So for gettimeofday, if we exclude the fact that the conversion of
 struct timeval will be factorized, you have either:
 
 {
 struct timeval tv;
 ret = get_errno(gettimeofday(tv, NULL));
 if (!is_error(ret)) {
   struct target_timeval *target_tv;
 
   lock_user_struct(target_tv, arg1, 0);
   target_tv-tv_sec = tswapl(tv-tv_sec);
   target_tv-tv_usec = tswapl(tv-tv_usec);
   if (unlock_user_struct(target_tv, arg1, 1)) {
   ret = -TARGET_EFAULT;
   goto fail;
   }
 }
 }
 
 Or
 
 {
 struct timeval tv;
 ret = get_errno(gettimeofday(tv, NULL));
 if (!is_error(ret)) {
   struct target_timeval target_tv;
 
   target_tv.tv_sec = tswapl(tv-tv_sec);
   target_tv.tv_usec = tswapl(tv-tv_usec);
   if (copy_to_user(arg1, target_tv, sizeof(target_tv)) {
   ret = -TARGET_EFAULT;
   goto fail;
   }
 }
 }

I don't see where the second one is handling target/host address
translation.

A problem with both of the above examples is that they use tswapl().
Without the proper type casting tswapl() doesn't do proper sign
extension when dealing with 64bit/32bit host/target relationships.  I've
fixed more than one location where this has resulted in bugs.  What I'm
suggesting is the following:

static inline abi_long copy_to_user_timeval(abi_ulong target_timeval_addr,
const struct timeval *tv)
{
if (!access_ok(VERIFY_WRITE, target_tv_addr, sizeof(*target_tv)))
return -TARGET_EFAULT;

lock_user_struct(target_tv, target_tv_addr, 0);

__put_user(tv-tv_sec, target_tv-tv_sec);
__put_user(tv-tv_usec, target_tv-tv_usec);

unlock_user_struct(target_tv, target_tv_addr, 1);

return 0;
}

.
.
.
{
struct timeval tv;
ret = get_errno(gettimeofday(tv, NULL));
if (!is_error(ret)) {
if (copy_to_user_timeval(arg1, tv)) {
ret = -TARGET_EFAULT;
goto fail;
}
}
}

(Ignoring the factorization of the timeval struct)
copy_to_user_timeval() here properly handles target/host address
translation.  It also uses __put_user() which properly handles any sign
extension.  The difference between the main syscall code and the linux
kernel is simply this:

copy_to_user(arg1, tv, sizeof(tv)) - copy_to_user_timeval(arg1, tv)
   

Allowing that minor difference (since qemu needs to do translation
between the structure types) is reasonable.  Furthermore the access_ok()
is kept inside the copy_to_user*() function just like in the linux
kernel.  The construct I've shown above is very comparable to kernel
code.


 Personally I prefer the Linux API style, but Paul's lock/unlock is also
 perfectly logical. The advantage of keeping the Paul's API is that you
 can minimize the number of changes.

Sure, there are advantages to minimal changes.  Personally I prefer the
Linux API style because that's what is being emulated.

 Another point is that if you use the Linux

Re: [Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer of different size' problems?

2007-11-07 Thread Thayne Harbaugh

On Wed, 2007-11-07 at 20:18 +0100, Fabrice Bellard wrote:
 Hi,
 
 Regarding the user memory access, here is my suggestion which should
 minimize the changes:

The virtue of making the minimum changes is that there are likely fewer
errors.  Other than that, it's more important to me to make the
*changes*.

 - Keep __put_user() and __get_user() as you did.

good.

 - Remove put_user(), get_user(), copy_from_user() and copy_to_user()

I'd prefer to keep put_user(), get_user(), copy_from_user() and
copy_to_user() and have them internally perform
lock_user()/unlock_user().  I like how lock_user()/unlock_user()
minimizes copying - I think that's good.  I also like keeping functions
that work in similar ways as the kernel counterparts - this is important
for maintaining functions that emulate kernel behavior so that code is
more comparable to the kernel.  This is also very near the way my
current patches are written and is the minimum work for me.

 - Modify the signal.c code so that it uses __put_user, __get_user and
 lock/unlock_user.

good.

 - Modify lock_user() so that it automatically does access_ok() and
 returns NULL if access_ok() fails.

Yes - this is good.  This is something that I missed with my first set
of patches and it's significant.

 - Test lock_user/lock_user_struct/... return value explicitely at every
 call.

yep.

 - Fix page_check_range() so that it handles writes to pages containing
 code by calling page_unprotect when necessary (the current code can fail
 in this case !).

Good.

 - Suppress no longer needed page_unprotect_range() call in syscall.c.

sure.

 - Suppress or fix tput/tget macros so that they do access_ok().

I think it's better to use get_user()/put_user() for these which would
handle assigning to different sized types and with proper sign-extension
when the target and host aren't the same sized word.





Re: [Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer of different size' problems?

2007-11-12 Thread Thayne Harbaugh

On Wed, 2007-11-07 at 20:18 +0100, Fabrice Bellard wrote:

 - Fix page_check_range() so that it handles writes to pages containing
 code by calling page_unprotect when necessary (the current code can fail
 in this case !).
 
 - Suppress no longer needed page_unprotect_range() call in syscall.c.

Something like this?

Looks like exec.c needs some attention regarding target_ulong/abi_ulong.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-12 09:56:01.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-12 09:56:12.0 -0700
@@ -2745,7 +2745,6 @@
 ret = 0; /* avoid warning */
 break;
 case TARGET_NR_read:
-page_unprotect_range(arg2, arg3);
 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
 goto efault;
 ret = get_errno(read(arg1, p, arg3));
@@ -4538,7 +4537,6 @@
 break;
 #ifdef TARGET_NR_pread
 case TARGET_NR_pread:
-page_unprotect_range(arg2, arg3);
 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
 goto efault;
 ret = get_errno(pread(arg1, p, arg3, arg4));
Index: qemu/exec.c
===
--- qemu.orig/exec.c	2007-11-12 09:56:01.0 -0700
+++ qemu/exec.c	2007-11-12 10:00:41.0 -0700
@@ -1898,6 +1898,9 @@
 return -1;
 if (!(p-flags  PAGE_WRITE)  (flags  PAGE_WRITE) )
 return -1;
+if ((p-flags  PAGE_EXEC)  (flags  PAGE_WRITE)
+ page_unprotect(addr, 0, NULL))
+return -1;
 }
 return 0;
 }
@@ -1942,21 +1945,6 @@
 return 0;
 }
 
-/* call this function when system calls directly modify a memory area */
-/* ??? This should be redundant now we have lock_user.  */
-void page_unprotect_range(target_ulong data, target_ulong data_size)
-{
-target_ulong start, end, addr;
-
-start = data;
-end = start + data_size;
-start = TARGET_PAGE_MASK;
-end = TARGET_PAGE_ALIGN(end);
-for(addr = start; addr  end; addr += TARGET_PAGE_SIZE) {
-page_unprotect(addr, 0, NULL);
-}
-}
-
 static inline void tlb_set_dirty(CPUState *env,
  unsigned long addr, target_ulong vaddr)
 {


Re: [Qemu-devel] [PATCH] Fix TLS support on x86

2007-11-13 Thread Thayne Harbaugh

On Tue, 2007-11-13 at 19:44 +0100, Stefan Weil wrote:
 Hi,
 
 I'd like to test user mode emulation on MIPS host.
 
 Do you have newer versions of your patches which match
 current CVS HEAD? TLS support is still missing there,
 so QEMU user mode emulation is not really usable without
 working patches.

I don't know about anyone else, but I have some patches for TLS for arm
and i386.  The patches are significantly out of date with the recent
linux-user changes.  I won't be updating them until I finish with the
current set of changes to linux-user.

 Alexander Graf schrieb:
  Hi,
 
  these are the updated patches for TLS support:
 
  qemu-cvs-futex.patch
 
  This patches futex support into qemu-user. It is basically done by David
  Woodhouse and I implemented FUTEX_WAKE_OP because actually one
  application did not work without (I don't really remember which one
  though). If FUTEX_WAKE_OP gets triggered qemu throws a warning though so
  if anyone experiences problems with it and it works without we should
  disable it then.
 
  qemu-cvs-sched_getaffinity.patch
 
  Flash9 needs sys_get_getaffinity to work properly. As far as I can tell
  there should be no need for endianness-conversion, because the
  information is written bit-wise.
 
  qemu-cvs-tls.patch
 
  implements set_thread_area for x86 and modifies the do_clone function,
  so TLS is evaluated. This is 90% done by David Woodhouse, I only changed
  it so it works for me (TID setters, proper segment register setters,
  fork() fix, made clone() work).
 
  Alex
 
 





[Qemu-devel] [PATCH] target_posix_types.h

2007-11-14 Thread Thayne Harbaugh
This patch, 44_target_posix_types.patch provides target specific posix
types.  These types improve target structure creation, code similarity
to kernel code and improve type casting for assignment between target
and host.
Index: qemu/linux-user/alpha/target_posix_types.h
===
--- /dev/null	1970-01-01 00:00:00.0 +
+++ qemu/linux-user/alpha/target_posix_types.h	2007-11-13 15:36:14.0 -0700
@@ -0,0 +1,55 @@
+/*
+ * Borrowed with minor changes from:
+ *  linux/include/asm-alpha/posix_types.h
+ */
+
+#ifndef TARGET_POSIX_TYPES_H
+#define TARGET_POSIX_TYPES_H
+
+typedef int8_t			target_char;
+typedef int16_t			target_short;
+typedef int32_t			target_int;
+/* target_long defined in qemu/cpu-defs.h */
+typedef int64_t			target_long_long;
+
+typedef uint8_t			target_uchar;
+typedef uint16_t		target_ushort;
+typedef uint32_t		target_uint;
+/* target_ulong defined in qemu/cpu-defs.h */
+typedef uint64_t		target_ulong_long;
+
+typedef target_uint		target_ino_t;
+typedef target_uint		target_mode_t;
+typedef target_uint		target_nlink_t;
+typedef abi_long		target_off_t;
+typedef target_long_long	target_loff_t;
+typedef target_int		target_pid_t;
+typedef target_int		target_ipc_pid_t;
+typedef target_uint		target_uid_t;
+typedef target_uint		target_gid_t;
+typedef abi_ulong		target_size_t;
+typedef abi_long		target_ssize_t;
+typedef abi_long		target_ptrdiff_t;
+typedef abi_long		target_time_t;
+typedef abi_long		target_suseconds_t;
+typedef abi_long		target_clock_t;
+typedef target_int		target_daddr_t;
+typedef target_char *		target_caddr_t;
+/* typedef unsigned long	target_sigset_t; (conflicts in syscall_defs.h) */
+typedef target_ushort		target_uid16_t;
+typedef target_ushort		target_gid16_t;
+typedef target_int		target_clockid_t;
+typedef target_int		target_timer_t;
+
+typedef struct {
+	target_int	val[2];
+} target_fsid_t;
+
+typedef target_uid_t		target_old_uid_t;
+typedef target_gid_t		target_old_gid_t;
+typedef target_uid_t		target_uid32_t;
+typedef target_gid_t		target_gid32_t;
+
+typedef target_uint		target_old_dev_t;
+
+#endif /* TARGET_POSIX_TYPES_H */
Index: qemu/linux-user/arm/target_posix_types.h
===
--- /dev/null	1970-01-01 00:00:00.0 +
+++ qemu/linux-user/arm/target_posix_types.h	2007-11-13 15:36:14.0 -0700
@@ -0,0 +1,62 @@
+/*
+ * Borrowed with minor changes from:
+ *  linux/include/asm-arm/posix_types.h
+ *
+ *  Copyright (C) 1996-1998 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Changelog:
+ *   27-06-1996	RMK	Created
+ */
+#ifndef TARGET_POSIX_TYPES_H
+#define TARGET_POSIX_TYPES_H
+
+typedef int8_t			target_char;
+typedef int16_t			target_short;
+typedef int32_t			target_int;
+/* target_long defined in qemu/cpu-defs.h */
+typedef int64_t			target_long_long;
+
+typedef uint8_t			target_uchar;
+typedef uint16_t		target_ushort;
+typedef uint32_t		target_uint;
+/* target_ulong defined in qemu/cpu-defs.h */
+typedef uint64_t		target_ulong_long;
+
+typedef abi_ulong		target_ino_t;
+typedef target_ushort		target_mode_t;
+typedef target_ushort		target_nlink_t;
+typedef abi_long		target_off_t;
+typedef target_int		target_pid_t;
+typedef target_ushort		target_ipc_pid_t;
+typedef target_ushort		target_uid_t;
+typedef target_ushort		target_gid_t;
+typedef target_uint		target_size_t;
+typedef target_int		target_ssize_t;
+typedef target_int		target_ptrdiff_t;
+typedef abi_long		target_time_t;
+typedef abi_long		target_suseconds_t;
+typedef abi_long		target_clock_t;
+typedef target_int		target_timer_t;
+typedef target_int		target_clockid_t;
+typedef target_int		target_daddr_t;
+typedef target_char *		target_caddr_t;
+typedef target_ushort		id16_t;
+typedef target_ushort		target_gid16_t;
+typedef target_uint		target_uid32_t;
+typedef target_uint		target_gid32_t;
+
+typedef target_ushort		target_old_uid_t;
+typedef target_ushort		target_old_gid_t;
+typedef target_ushort		target_old_dev_t;
+
+typedef target_long_long	target_loff_t;
+
+typedef struct {
+	target_int	val[2];
+} target_fsid_t;
+
+#endif /* TARGET_POSIX_TYPES */
Index: qemu/linux-user/i386/target_posix_types.h
===
--- /dev/null	1970-01-01 00:00:00.0 +
+++ qemu/linux-user/i386/target_posix_types.h	2007-11-13 15:36:14.0 -0700
@@ -0,0 +1,55 @@
+/*
+ * Borrowed with minor changes from:
+ *  linux/include/asm-i386/posix_types.h
+ */
+
+#ifndef TARGET_POSIX_TYPES_H
+#define TARGET_POSIX_TYPES_H
+
+typedef int8_t			target_char;
+typedef int16_t			target_short;
+typedef int32_t			target_int;
+/* target_long defined in qemu/cpu-defs.h */
+typedef int64_t			target_long_long;
+
+typedef uint8_t			target_uchar;
+typedef uint16_t		target_ushort;
+typedef 

Re: [Qemu-devel] Re: [PATCH] tget/tput deprecation

2007-11-14 Thread Thayne Harbaugh
I didn't mention that this patch depends on the previous
44_target_posix_types.patch.

On Wed, 2007-11-14 at 09:03 -0700, Thayne Harbaugh wrote:
 This patch deprecates tget/tput and replaces them with get_user() and
 put_user() which perform proper locking.  It also checks return codes
 (in most places) and fails with EFAULT where appropriate.





Re: [Qemu-devel] [PATCH] target_posix_types.h

2007-11-14 Thread Thayne Harbaugh

On Wed, 2007-11-14 at 17:25 +0100, Jocelyn Mayer wrote:
 On Wed, 2007-11-14 at 08:59 -0700, Thayne Harbaugh wrote:
  This patch, 44_target_posix_types.patch provides target specific posix
  types.  These types improve target structure creation, code similarity
  to kernel code and improve type casting for assignment between target
  and host.
 
 Hi,
 
 This seems not OK for ppc/ppc64. There is no ppc64 subdirectory anymore
 in the linux-user directory. ppc and ppc64 targets have been merged, as
 it is in recent kernels, so all the definitions should go in the ppc
 subdirectory, using #ifdef TARGET_PPC64 when there are differences; but
 there should be very few: there are only 2 ifdef __powerpc64__ in the
 linux-2.6.23/include/asm-powerpc/posix_types.h file.

How is this?
Index: qemu/linux-user/alpha/target_posix_types.h
===
--- /dev/null	1970-01-01 00:00:00.0 +
+++ qemu/linux-user/alpha/target_posix_types.h	2007-11-13 15:36:14.0 -0700
@@ -0,0 +1,55 @@
+/*
+ * Borrowed with minor changes from:
+ *  linux/include/asm-alpha/posix_types.h
+ */
+
+#ifndef TARGET_POSIX_TYPES_H
+#define TARGET_POSIX_TYPES_H
+
+typedef int8_t			target_char;
+typedef int16_t			target_short;
+typedef int32_t			target_int;
+/* target_long defined in qemu/cpu-defs.h */
+typedef int64_t			target_long_long;
+
+typedef uint8_t			target_uchar;
+typedef uint16_t		target_ushort;
+typedef uint32_t		target_uint;
+/* target_ulong defined in qemu/cpu-defs.h */
+typedef uint64_t		target_ulong_long;
+
+typedef target_uint		target_ino_t;
+typedef target_uint		target_mode_t;
+typedef target_uint		target_nlink_t;
+typedef abi_long		target_off_t;
+typedef target_long_long	target_loff_t;
+typedef target_int		target_pid_t;
+typedef target_int		target_ipc_pid_t;
+typedef target_uint		target_uid_t;
+typedef target_uint		target_gid_t;
+typedef abi_ulong		target_size_t;
+typedef abi_long		target_ssize_t;
+typedef abi_long		target_ptrdiff_t;
+typedef abi_long		target_time_t;
+typedef abi_long		target_suseconds_t;
+typedef abi_long		target_clock_t;
+typedef target_int		target_daddr_t;
+typedef target_char *		target_caddr_t;
+/* typedef unsigned long	target_sigset_t; (conflicts in syscall_defs.h) */
+typedef target_ushort		target_uid16_t;
+typedef target_ushort		target_gid16_t;
+typedef target_int		target_clockid_t;
+typedef target_int		target_timer_t;
+
+typedef struct {
+	target_int	val[2];
+} target_fsid_t;
+
+typedef target_uid_t		target_old_uid_t;
+typedef target_gid_t		target_old_gid_t;
+typedef target_uid_t		target_uid32_t;
+typedef target_gid_t		target_gid32_t;
+
+typedef target_uint		target_old_dev_t;
+
+#endif /* TARGET_POSIX_TYPES_H */
Index: qemu/linux-user/arm/target_posix_types.h
===
--- /dev/null	1970-01-01 00:00:00.0 +
+++ qemu/linux-user/arm/target_posix_types.h	2007-11-13 15:36:14.0 -0700
@@ -0,0 +1,62 @@
+/*
+ * Borrowed with minor changes from:
+ *  linux/include/asm-arm/posix_types.h
+ *
+ *  Copyright (C) 1996-1998 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Changelog:
+ *   27-06-1996	RMK	Created
+ */
+#ifndef TARGET_POSIX_TYPES_H
+#define TARGET_POSIX_TYPES_H
+
+typedef int8_t			target_char;
+typedef int16_t			target_short;
+typedef int32_t			target_int;
+/* target_long defined in qemu/cpu-defs.h */
+typedef int64_t			target_long_long;
+
+typedef uint8_t			target_uchar;
+typedef uint16_t		target_ushort;
+typedef uint32_t		target_uint;
+/* target_ulong defined in qemu/cpu-defs.h */
+typedef uint64_t		target_ulong_long;
+
+typedef abi_ulong		target_ino_t;
+typedef target_ushort		target_mode_t;
+typedef target_ushort		target_nlink_t;
+typedef abi_long		target_off_t;
+typedef target_int		target_pid_t;
+typedef target_ushort		target_ipc_pid_t;
+typedef target_ushort		target_uid_t;
+typedef target_ushort		target_gid_t;
+typedef target_uint		target_size_t;
+typedef target_int		target_ssize_t;
+typedef target_int		target_ptrdiff_t;
+typedef abi_long		target_time_t;
+typedef abi_long		target_suseconds_t;
+typedef abi_long		target_clock_t;
+typedef target_int		target_timer_t;
+typedef target_int		target_clockid_t;
+typedef target_int		target_daddr_t;
+typedef target_char *		target_caddr_t;
+typedef target_ushort		id16_t;
+typedef target_ushort		target_gid16_t;
+typedef target_uint		target_uid32_t;
+typedef target_uint		target_gid32_t;
+
+typedef target_ushort		target_old_uid_t;
+typedef target_ushort		target_old_gid_t;
+typedef target_ushort		target_old_dev_t;
+
+typedef target_long_long	target_loff_t;
+
+typedef struct {
+	target_int	val[2];
+} target_fsid_t;
+
+#endif /* TARGET_POSIX_TYPES */
Index: qemu/linux-user/i386/target_posix_types.h

[Qemu-devel] Build m68k-linux-user on x86_64

2007-11-14 Thread Thayne Harbaugh
m68k-linux-user fails to build on x86_64.  It has never built for me in
the last six months.  It's a dyngen failure.  Does anyone have any
patches or suggestions as to how I might fix this?

thank you.

compile output:

gcc-3.4 -Wall -O2 -g -fno-strict-aliasing -I. -I.. 
-I/home/thayne/dev/c2/olmectools/trunk/qemu/target-m68k 
-I/home/thayne/dev/c2/olmectools/trunk/qemu -MMD -MP 
-I/home/thayne/dev/c2/olmectools/trunk/qemu/linux-user 
-I/home/thayne/dev/c2/olmectools/trunk/qemu/linux-user/m68k -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 
-I/home/thayne/dev/c2/olmectools/trunk/qemu/fpu  
-I/home/thayne/dev/c2/olmectools/trunk/qemu/slirp-c -o translate-op.o 
/home/thayne/dev/c2/olmectools/trunk/qemu/translate-op.c
In file included from 
/home/thayne/dev/c2/olmectools/trunk/qemu/translate-op.c:36:
./op.h: In function `dyngen_code':
./op.h:22: error: syntax error before ')' token
./op.h:23: error: syntax error before ')' token
./op.h:36: error: syntax error before ')' token
./op.h:49: error: syntax error before ')' token
./op.h:50: error: syntax error before ')' token
./op.h:61: error: syntax error before ')' token
./op.h:74: error: syntax error before ')' token
./op.h:76: error: syntax error before ')' token
./op.h:78: error: syntax error before ')' token

(there are over 100 lines of similar errors)





Re: [Qemu-devel] Re: [PATCH] tget/tput deprecation

2007-11-14 Thread Thayne Harbaugh

On Wed, 2007-11-14 at 11:21 -0700, Thayne Harbaugh wrote:
 On Wed, 2007-11-14 at 09:03 -0700, Thayne Harbaugh wrote:
  This patch deprecates tget/tput and replaces them with get_user() and
  put_user() which perform proper locking.  It also checks return codes
  (in most places) and fails with EFAULT where appropriate.
 
 I just noticed that I missed m68k-semi.c.  New patch is forthcoming.

Updated patch.
Index: qemu/linux-user/elfload.c
===
--- qemu.orig/linux-user/elfload.c	2007-11-14 09:19:09.0 -0700
+++ qemu/linux-user/elfload.c	2007-11-14 11:23:00.0 -0700
@@ -179,8 +179,9 @@
   regs-ARM_cpsr |= CPSR_T;
 regs-ARM_pc = infop-entry  0xfffe;
 regs-ARM_sp = infop-start_stack;
-regs-ARM_r2 = tgetl(stack + 8); /* envp */
-regs-ARM_r1 = tgetl(stack + 4); /* envp */
+/* FIXME - what to for failure of get_user()? */
+get_user(regs-ARM_r2, stack + 8, abi_long); /* envp */
+get_user(regs-ARM_r1, stack + 4, abi_long); /* envp */
 /* XXX: it seems that r0 is zeroed after ! */
 regs-ARM_r0 = 0;
 /* For uClinux PIC binaries.  */
@@ -341,7 +342,8 @@
  * but this is what the ABI wants and is needed to allow
  * execution of PPC BSD programs.
  */
-_regs-gpr[3] = tgetl(pos);
+/* FIXME - what to for failure of get_user()? */
+get_user(_regs-gpr[3], pos, abi_long);
 pos += sizeof(abi_ulong);
 _regs-gpr[4] = pos;
 for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
@@ -733,7 +735,8 @@
 if (nbyte) {
 	nbyte = qemu_host_page_size - nbyte;
 	do {
-		tput8(elf_bss, 0);
+/* FIXME - what to do if put_user() fails? */
+		put_user(0, elf_bss, uint8_t);
 elf_bss++;
 	} while (--nbyte);
 }
@@ -782,17 +785,11 @@
 /* This is correct because Linux defines
  * elf_addr_t as Elf32_Off / Elf64_Off
  */
-#if ELF_CLASS == ELFCLASS32
-#define NEW_AUX_ENT(id, val) do { \
-sp -= n; tput32(sp, val); \
-sp -= n; tput32(sp, id); \
+#define NEW_AUX_ENT(id, val) do {			\
+sp -= n; put_user(val, sp, abi_ulong);	\
+sp -= n; put_user(id, sp, abi_ulong);	\
   } while(0)
-#else
-#define NEW_AUX_ENT(id, val) do { \
-sp -= n; tput64(sp, val); \
-sp -= n; tput64(sp, id); \
-  } while(0)
-#endif
+
 NEW_AUX_ENT (AT_NULL, 0);
 
 /* There must be exactly DLINFO_ITEMS entries here.  */
Index: qemu/linux-user/flatload.c
===
--- qemu.orig/linux-user/flatload.c	2007-11-14 09:19:09.0 -0700
+++ qemu/linux-user/flatload.c	2007-11-14 11:23:00.0 -0700
@@ -598,14 +598,16 @@
 rp = datapos;
 while (1) {
 abi_ulong addr;
-addr = tgetl(rp);
+if (get_user(addr, rp, abi_ulong))
+return -EFAULT;
 if (addr == -1)
 break;
 if (addr) {
 addr = calc_reloc(addr, libinfo, id, 0);
 if (addr == RELOC_FAILED)
 return -ENOEXEC;
-tputl(rp, addr);
+if (put_user(addr, rp, abi_ulong))
+return -EFAULT;
 }
 rp += sizeof(abi_ulong);
 }
@@ -629,14 +631,16 @@
 /* Get the address of the pointer to be
relocated (of course, the address has to be
relocated first).  */
-relval = tgetl(reloc + i * sizeof (abi_ulong));
+if (get_user(relval, reloc + i * sizeof(abi_ulong), abi_ulong))
+return -EFAULT;
 addr = flat_get_relocate_addr(relval);
 rp = calc_reloc(addr, libinfo, id, 1);
 if (rp == RELOC_FAILED)
 return -ENOEXEC;
 
 /* Get the pointer's value.  */
-addr = tgetl(rp);
+if (get_user(addr, rp, abi_ulong))
+return -EFAULT;
 if (addr != 0) {
 /*
  * Do the relocation.  PIC relocs in the data section are
@@ -652,13 +656,15 @@
 return -ENOEXEC;
 
 /* Write back the relocated pointer.  */
-tputl(rp, addr);
+if (put_user(addr, rp, abi_ulong))
+return -EFAULT;
 }
 }
 } else {
 for (i = 0; i  relocs; i++) {
 abi_ulong relval;
-relval = tgetl(reloc + i * sizeof (abi_ulong));
+if (get_user(relval, reloc + i * sizeof(abi_ulong), abi_ulong))
+return -EFAULT;
 old_reloc(libinfo[0], relval);
 }
 }
@@ -744,9 +750,13 @@
 p = libinfo[i].start_data;
 for (j=0; jMAX_SHARED_LIBS; j++) {
 p -= 4;
-tput32(p, libinfo[j].loaded
-  ? libinfo[j].start_data

Re: [Qemu-devel] [PATCH] target_posix_types.h

2007-11-14 Thread Thayne Harbaugh

On Wed, 2007-11-14 at 20:14 +0100, Fabrice Bellard wrote:
 Thayne Harbaugh wrote:
  On Wed, 2007-11-14 at 19:32 +0100, Fabrice Bellard wrote:
  Thayne Harbaugh wrote:
  This patch, 44_target_posix_types.patch provides target specific posix
  types.  These types improve target structure creation, code similarity
  to kernel code and improve type casting for assignment between target
  and host.
  Why is it needed ?
  
  
  It's not *necessary*, but it makes code more readable and it simplifies
  having to always check for what a typedef on a target might map to.  It
  makes target structures more comparable to their structures in the
  kernel.
  
  A simple example:
  
  struct target_timeval {
  abi_long tv_sec;
  abi_long tv_usec;
  };
  
  vs.
  
  struct target_timeval {
  target_time_t tv_sec;
  target_suseconds_t tv_usec;
  };
  
  
  It also makes type conversion between target and host more obvious.
  
  It also means that more code can be shared rather than #ifdef'ed when
  targets differ on their base definitions.
  
  It's just another level of abstraction, we can always stick with
  abi_long, abi_ulong, etc..  I've just noticed that size and sign
  handling when converting between target and host are a common source of
  errors and this simplifies things.  We use it in all our patches and it
  has helped simplify and fix errors.
 
 I don't like adding levels of abstraction unless I am really forced. I 
 think these types makes the code more difficult to understand without 
 real added value. In particular, it does not help for sign conversions.

I should have provided an example:

Let's look at time_t and target_time_t which might have a size of 4 or
of 8.

IMO it's easier to write this:

time_t time;
get_user(time, time_addr, target_time_t);
and
put_user(time, time_addr, target_time_t);

get_user then does the lock and calls __get_user() which uses the type
information when assigning to time - that is what correctly handles any
sign extending.

What is common now is this:

time_t time;
time = tget32(time_addr);
and
tput32(time_addr, time);

This means that time_t had to be tracked down on varying architectures
to find the size and there was an assumption made that time_t is 32 bits
- which isn't true for all targets.  The next problem is that if the
target is 32 bits but the host is 64 bits then there's a sign extension
problem because (time_t)-1 is used for an error condition.  If you don't
correctly assign assign the 32-bit -1 to a 64-bit type then, rather than
-1, you get 4294967295.

Now maybe a solution is this:

time = tget1(time_addr);
and
tputl(time_addr, time);

That may fix the problem of getting the size correct depending on
whether the target is 32 or 64 bit, but it still doesn't solve the
problem of correctly sign-extending when assigning between the target
and the host.

I've sent patches to fix this type of bug to the list.  I have possibly
half-a-dozen more patches in my tree that fix this same type of bug: -1
becoming a very large positive number.

Maybe I'm missing the current, correct way of doing this.  Please
enlighten me.  If I've missed something then I apologize for wasting
everyone's time.

Thank you.









Re: [Qemu-devel] [PATCH] target_posix_types.h

2007-11-14 Thread Thayne Harbaugh
On Wed, 2007-11-14 at 20:14 +0100, Fabrice Bellard wrote:
 Thayne Harbaugh wrote:
  On Wed, 2007-11-14 at 19:32 +0100, Fabrice Bellard wrote:
  Thayne Harbaugh wrote:
  This patch, 44_target_posix_types.patch provides target specific posix
  types.  These types improve target structure creation, code similarity
  to kernel code and improve type casting for assignment between target
  and host.
  Why is it needed ?
  
  
  It's not *necessary*, but it makes code more readable and it simplifies
  having to always check for what a typedef on a target might map to.  It
  makes target structures more comparable to their structures in the
  kernel.
  
  A simple example:
  
  struct target_timeval {
  abi_long tv_sec;
  abi_long tv_usec;
  };
  
  vs.
  
  struct target_timeval {
  target_time_t tv_sec;
  target_suseconds_t tv_usec;
  };
  
  
  It also makes type conversion between target and host more obvious.
  
  It also means that more code can be shared rather than #ifdef'ed when
  targets differ on their base definitions.
  
  It's just another level of abstraction, we can always stick with
  abi_long, abi_ulong, etc..  I've just noticed that size and sign
  handling when converting between target and host are a common source of
  errors and this simplifies things.  We use it in all our patches and it
  has helped simplify and fix errors.
 
 I don't like adding levels of abstraction unless I am really forced. I 
 think these types makes the code more difficult to understand without 
 real added value. In particular, it does not help for sign conversions.

I should have provided an example:

Let's look at time_t and target_time_t which might have a size of 4 or
of 8.

IMO it's easier to write this:

time_t time;
get_user(time, time_addr, target_time_t);
and
put_user(time, time_addr, target_time_t);

get_user then does the lock and calls __get_user() which uses the type
information when assigning to time - that is what correctly handles any
sign extending.

What is common now is this:

time_t time;
time = tget32(time_addr);
and
tput32(time_addr, time);

This means that time_t had to be tracked down on varying architectures
to find the size and there was an assumption made that time_t is 32 bits
- which isn't true for all targets.  The next problem is that if the
target is 32 bits but the host is 64 bits then there's a sign extension
problem because (time_t)-1 is used for an error condition.  If you don't
correctly assign assign the 32-bit -1 to a 64-bit type then, rather than
-1, you get 4294967295.

Now maybe a solution is this:

time = tget1(time_addr);
and
tputl(time_addr, time);

That means that someone still needed to track down what a target time_t
is.  That may fix the problem of getting the size correct, depending on
whether the target is 32 or 64 bit, but it still doesn't solve the
problem of correctly sign-extending when assigning between the target
and the host.

I've sent patches to fix this type of bug to the list.  I have possibly
half-a-dozen more patches in my tree that fix this same type of bug: -1
becoming a very large positive number.

Maybe I'm missing the current, correct way of doing this.  Please
enlighten me.  If I've missed something then I apologize for wasting
everyone's time.

Thank you.









Re: [Qemu-devel] [PATCH] target_posix_types.h

2007-11-14 Thread Thayne Harbaugh

On Wed, 2007-11-14 at 20:39 +, Paul Brook wrote:
  This means that time_t had to be tracked down on varying architectures
  to find the size and there was an assumption made that time_t is 32 bits
  - which isn't true for all targets.  The next problem is that if the
  target is 32 bits but the host is 64 bits then there's a sign extension
  problem because (time_t)-1 is used for an error condition.  If you don't
  correctly assign assign the 32-bit -1 to a 64-bit type then, rather than
  -1, you get 4294967295.
 
 Is there any guarantee that time_t is a signed type? The fact that you said 
 (time_t)-1 suggests it could be an unsigned type. If time_t is an unsigned 
 type, then casting to a wider value is still wrong. You have to special-case 
 the error condition.
 
 In the case of time_t this only becomes relevant after 32-bit time_t wrap in 
 approx. 99 years time, but I'd expect there are cases where it matters.

time_t is only one example.  There are similar problems with the
handling of struct target_iovec.  There are still other places with
similar problems.

Yes, special casing can work.  There's the possible problem of value
truncation when moving between 32 and 64 bits.





Re: [Qemu-devel] [PATCH] target_posix_types.h

2007-11-14 Thread Thayne Harbaugh

On Wed, 2007-11-14 at 14:06 -0700, Warner Losh wrote:
 From: Paul Brook [EMAIL PROTECTED]
 Subject: Re: [Qemu-devel] [PATCH] target_posix_types.h
 Date: Wed, 14 Nov 2007 20:39:36 +
 
   This means that time_t had to be tracked down on varying architectures
   to find the size and there was an assumption made that time_t is 32 bits
   - which isn't true for all targets.  The next problem is that if the
   target is 32 bits but the host is 64 bits then there's a sign extension
   problem because (time_t)-1 is used for an error condition.  If you don't
   correctly assign assign the 32-bit -1 to a 64-bit type then, rather than
   -1, you get 4294967295.
  
  Is there any guarantee that time_t is a signed type? The fact that you said 
  (time_t)-1 suggests it could be an unsigned type. If time_t is an unsigned 
  type, then casting to a wider value is still wrong. You have to 
  special-case 
  the error condition.
  
  In the case of time_t this only becomes relevant after 32-bit time_t wrap 
  in 
  approx. 99 years time, but I'd expect there are cases where it matters.
 
 The wrap on 32-bit signed time_t happens after ~68 years since the
 next looming time thing in unix is 2038:
 
 % date -r 2147483647
 Mon Jan 18 20:14:07 MST 2038
 %  date -r 2147483648
 Fri Dec 13 13:45:52 MST 1901
 
 The standard says:
 
7.23  Date and time time.h
7.23.1  Components of time
[#3] The types declared are size_t (described in 7.17);
clock_t
and
time_t
which are arithmetic types capable  of  representing  times;
 
 Which is uselessly vague (no: it doesn't imply time_t is a signed
 number or unsigned or even an int):
 
6.2.5  Types
 ...
[#21]  Integer  and  floating  types are collectively called
arithmetic types. Arithmetic types  and  pointer  types  are
collectively  called scalar types. Array and structure types
are collectively called aggregate types.
 
 Traditionally, time_t is defined as
 
 typedef long time_t;
 
 but recently you'll see it defined like so
 
 typedef int32_t time_t;
 
 or
 
 typedef int64_t time_t;

Interesting.  Thank you.

My intention wasn't to discuss time_t in particular but to point out an
example of a class of bugs.





Re: [Qemu-devel] Re: [PATCH] tget/tput deprecation

2007-11-15 Thread Thayne Harbaugh

On Wed, 2007-11-14 at 09:03 -0700, Thayne Harbaugh wrote:
 This patch deprecates tget/tput and replaces them with get_user() and
 put_user() which perform proper locking.  It also checks return codes
 (in most places) and fails with EFAULT where appropriate.

This version doesn't depend on 44_target_posix_types.patch.
Index: qemu/linux-user/elfload.c
===
--- qemu.orig/linux-user/elfload.c	2007-11-15 14:04:26.0 -0700
+++ qemu/linux-user/elfload.c	2007-11-15 21:21:19.0 -0700
@@ -179,8 +179,9 @@
   regs-ARM_cpsr |= CPSR_T;
 regs-ARM_pc = infop-entry  0xfffe;
 regs-ARM_sp = infop-start_stack;
-regs-ARM_r2 = tgetl(stack + 8); /* envp */
-regs-ARM_r1 = tgetl(stack + 4); /* envp */
+/* FIXME - what to for failure of get_user()? */
+get_user_ual(regs-ARM_r2, stack + 8); /* envp */
+get_user_ual(regs-ARM_r1, stack + 4); /* envp */
 /* XXX: it seems that r0 is zeroed after ! */
 regs-ARM_r0 = 0;
 /* For uClinux PIC binaries.  */
@@ -341,7 +342,8 @@
  * but this is what the ABI wants and is needed to allow
  * execution of PPC BSD programs.
  */
-_regs-gpr[3] = tgetl(pos);
+/* FIXME - what to for failure of get_user()? */
+get_user_ual(_regs-gpr[3], pos);
 pos += sizeof(abi_ulong);
 _regs-gpr[4] = pos;
 for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
@@ -733,7 +735,8 @@
 if (nbyte) {
 	nbyte = qemu_host_page_size - nbyte;
 	do {
-		tput8(elf_bss, 0);
+/* FIXME - what to do if put_user() fails? */
+		put_user_u8(0, elf_bss);
 elf_bss++;
 	} while (--nbyte);
 }
@@ -782,17 +785,11 @@
 /* This is correct because Linux defines
  * elf_addr_t as Elf32_Off / Elf64_Off
  */
-#if ELF_CLASS == ELFCLASS32
-#define NEW_AUX_ENT(id, val) do { \
-sp -= n; tput32(sp, val); \
-sp -= n; tput32(sp, id); \
+#define NEW_AUX_ENT(id, val) do {		\
+sp -= n; put_user_ual(val, sp);	\
+sp -= n; put_user_ual(id, sp);	\
   } while(0)
-#else
-#define NEW_AUX_ENT(id, val) do { \
-sp -= n; tput64(sp, val); \
-sp -= n; tput64(sp, id); \
-  } while(0)
-#endif
+
 NEW_AUX_ENT (AT_NULL, 0);
 
 /* There must be exactly DLINFO_ITEMS entries here.  */
Index: qemu/linux-user/flatload.c
===
--- qemu.orig/linux-user/flatload.c	2007-11-15 14:04:26.0 -0700
+++ qemu/linux-user/flatload.c	2007-11-15 21:22:59.0 -0700
@@ -598,14 +598,16 @@
 rp = datapos;
 while (1) {
 abi_ulong addr;
-addr = tgetl(rp);
+if (get_user_ual(addr, rp))
+return -EFAULT;
 if (addr == -1)
 break;
 if (addr) {
 addr = calc_reloc(addr, libinfo, id, 0);
 if (addr == RELOC_FAILED)
 return -ENOEXEC;
-tputl(rp, addr);
+if (put_user_ual(addr, rp))
+return -EFAULT;
 }
 rp += sizeof(abi_ulong);
 }
@@ -629,14 +631,16 @@
 /* Get the address of the pointer to be
relocated (of course, the address has to be
relocated first).  */
-relval = tgetl(reloc + i * sizeof (abi_ulong));
+if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
+return -EFAULT;
 addr = flat_get_relocate_addr(relval);
 rp = calc_reloc(addr, libinfo, id, 1);
 if (rp == RELOC_FAILED)
 return -ENOEXEC;
 
 /* Get the pointer's value.  */
-addr = tgetl(rp);
+if (get_user_ual(addr, rp))
+return -EFAULT;
 if (addr != 0) {
 /*
  * Do the relocation.  PIC relocs in the data section are
@@ -652,13 +656,15 @@
 return -ENOEXEC;
 
 /* Write back the relocated pointer.  */
-tputl(rp, addr);
+if (put_user_ual(addr, rp))
+return -EFAULT;
 }
 }
 } else {
 for (i = 0; i  relocs; i++) {
 abi_ulong relval;
-relval = tgetl(reloc + i * sizeof (abi_ulong));
+if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
+return -EFAULT;
 old_reloc(libinfo[0], relval);
 }
 }
@@ -744,9 +750,12 @@
 p = libinfo[i].start_data;
 for (j=0; jMAX_SHARED_LIBS; j++) {
 p -= 4;
-tput32(p, libinfo[j].loaded
-  ? libinfo[j].start_data
-  : UNLOADED_LIB);
+/* FIXME - handle put_user() failures */
+if (put_user_ual(libinfo[j].loaded

[Qemu-devel] [PATCH] additional EFAULT patches

2007-11-20 Thread Thayne Harbaugh
These are some additional EFAULT patches.  They improve the code
consistency, check return values of copy_{to,from}_user() operations and
provide minor fixes.





[Qemu-devel] Re: [PATCH] 06_efault.3.patch - copy_from_user_fdset()

2007-11-20 Thread Thayne Harbaugh
This updates target_to_host_fds() to match the copy_from_user() code.
It drops some unused variables, checks and handles return values for
copy_from_user_fdset() and corrects an error where the n value was
incorrectly multiplied with abi_long instead of used as one greater than
the number of descriptors (which are bits).
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-17 09:00:14.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-17 09:09:08.0 -0700
@@ -443,50 +443,66 @@
 }
 }
 
-static inline fd_set *target_to_host_fds(fd_set *fds,
- abi_long *target_fds, int n)
+static inline abi_long copy_from_user_fdset(fd_set *fds,
+abi_ulong target_fds_addr,
+int n)
 {
-#if !defined(BSWAP_NEEDED)  !defined(WORDS_BIGENDIAN)
-return (fd_set *)target_fds;
-#else
-int i, b;
-if (target_fds) {
-FD_ZERO(fds);
-for(i = 0;i  n; i++) {
-b = (tswapl(target_fds[i / TARGET_ABI_BITS]) 
- (i  (TARGET_ABI_BITS - 1)))  1;
-if (b)
-FD_SET(i, fds);
+int i, nw, j, k;
+abi_ulong b, *target_fds;
+
+nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+if (!(target_fds = lock_user(VERIFY_READ,
+ target_fds_addr,
+ sizeof(abi_ulong) * nw,
+ 1)))
+return -TARGET_EFAULT;
+
+FD_ZERO(fds);
+k = 0;
+for (i = 0; i  nw; i++) {
+/* grab the abi_ulong */
+__get_user(b, target_fds[i]);
+for (j = 0; j  TARGET_ABI_BITS; j++) {
+/* check the bit inside the abi_ulong */
+if ((b  j)  1)
+FD_SET(k, fds);
+k++;
 }
-return fds;
-} else {
-return NULL;
 }
-#endif
+
+unlock_user(target_fds, target_fds_addr, 0);
+
+return 0;
 }
 
-static inline void host_to_target_fds(abi_long *target_fds,
-  fd_set *fds, int n)
+static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
+  fd_set *fds,
+  int n)
 {
-#if !defined(BSWAP_NEEDED)  !defined(WORDS_BIGENDIAN)
-/* nothing to do */
-#else
 int i, nw, j, k;
 abi_long v;
+abi_ulong *target_fds;
 
-if (target_fds) {
-nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
-k = 0;
-for(i = 0;i  nw; i++) {
-v = 0;
-for(j = 0; j  TARGET_ABI_BITS; j++) {
-v |= ((FD_ISSET(k, fds) != 0)  j);
-k++;
-}
-target_fds[i] = tswapl(v);
+nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+if (!(target_fds = lock_user(VERIFY_WRITE,
+ target_fds_addr,
+ sizeof(abi_ulong) * nw,
+ 0)))
+return -TARGET_EFAULT;
+
+k = 0;
+for (i = 0; i  nw; i++) {
+v = 0;
+for (j = 0; j  TARGET_ABI_BITS; j++) {
+v |= ((FD_ISSET(k, fds) != 0)  j);
+k++;
 }
+__put_user(v, target_fds[i]);
 }
-#endif
+
+unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
+
+return 0;
 }
 
 #if defined(__alpha__)
@@ -567,74 +583,57 @@
 
 /* do_select() must return target values and target errnos. */
 static abi_long do_select(int n,
-  abi_ulong rfd_p, abi_ulong wfd_p,
-  abi_ulong efd_p, abi_ulong target_tv)
+  abi_ulong rfd_addr, abi_ulong wfd_addr,
+  abi_ulong efd_addr, abi_ulong target_tv_addr)
 {
 fd_set rfds, wfds, efds;
 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
-abi_long *target_rfds, *target_wfds, *target_efds;
 struct timeval tv, *tv_ptr;
 abi_long ret;
-int ok;
 
-if (rfd_p) {
-target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1);
-if (!target_rfds) {
-ret = -TARGET_EFAULT;
-goto end;
-}
-rfds_ptr = target_to_host_fds(rfds, target_rfds, n);
+if (rfd_addr) {
+if (copy_from_user_fdset(rfds, rfd_addr, n))
+return -TARGET_EFAULT;
+rfds_ptr = rfds;
 } else {
-target_rfds = NULL;
 rfds_ptr = NULL;
 }
-if (wfd_p) {
-target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1);
-if (!target_wfds) {
-ret = -TARGET_EFAULT;
-goto end;
-}
-wfds_ptr = target_to_host_fds(wfds, target_wfds, n);
+if (wfd_addr) {
+if (copy_from_user_fdset(wfds, wfd_addr, n))
+return -TARGET_EFAULT;
+wfds_ptr = wfds;
 } else {
-target_wfds = NULL;

[Qemu-devel] Re: [PATCH] 06_efault.3.patch - copy_from_user_fdset()

2007-11-20 Thread Thayne Harbaugh

On Tue, 2007-11-20 at 12:08 -0700, Thayne Harbaugh wrote:
 This updates target_to_host_fds() to match the copy_from_user() code.
 It drops some unused variables, checks and handles return values for
 copy_from_user_fdset() and corrects an error where the n value was
 incorrectly multiplied with abi_long instead of used as one greater than
 the number of descriptors (which are bits).

The previous patch missed a minor detail.  This is an update to make the
fd_set *fds parameter of copy_to_user_fdset() into const fd_set
*fds.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-20 11:53:16.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-20 12:52:33.0 -0700
@@ -443,50 +443,66 @@
 }
 }
 
-static inline fd_set *target_to_host_fds(fd_set *fds,
- abi_long *target_fds, int n)
+static inline abi_long copy_from_user_fdset(fd_set *fds,
+abi_ulong target_fds_addr,
+int n)
 {
-#if !defined(BSWAP_NEEDED)  !defined(WORDS_BIGENDIAN)
-return (fd_set *)target_fds;
-#else
-int i, b;
-if (target_fds) {
-FD_ZERO(fds);
-for(i = 0;i  n; i++) {
-b = (tswapl(target_fds[i / TARGET_ABI_BITS]) 
- (i  (TARGET_ABI_BITS - 1)))  1;
-if (b)
-FD_SET(i, fds);
+int i, nw, j, k;
+abi_ulong b, *target_fds;
+
+nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+if (!(target_fds = lock_user(VERIFY_READ,
+ target_fds_addr,
+ sizeof(abi_ulong) * nw,
+ 1)))
+return -TARGET_EFAULT;
+
+FD_ZERO(fds);
+k = 0;
+for (i = 0; i  nw; i++) {
+/* grab the abi_ulong */
+__get_user(b, target_fds[i]);
+for (j = 0; j  TARGET_ABI_BITS; j++) {
+/* check the bit inside the abi_ulong */
+if ((b  j)  1)
+FD_SET(k, fds);
+k++;
 }
-return fds;
-} else {
-return NULL;
 }
-#endif
+
+unlock_user(target_fds, target_fds_addr, 0);
+
+return 0;
 }
 
-static inline void host_to_target_fds(abi_long *target_fds,
-  fd_set *fds, int n)
+static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
+  const fd_set *fds,
+  int n)
 {
-#if !defined(BSWAP_NEEDED)  !defined(WORDS_BIGENDIAN)
-/* nothing to do */
-#else
 int i, nw, j, k;
 abi_long v;
+abi_ulong *target_fds;
 
-if (target_fds) {
-nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
-k = 0;
-for(i = 0;i  nw; i++) {
-v = 0;
-for(j = 0; j  TARGET_ABI_BITS; j++) {
-v |= ((FD_ISSET(k, fds) != 0)  j);
-k++;
-}
-target_fds[i] = tswapl(v);
+nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
+if (!(target_fds = lock_user(VERIFY_WRITE,
+ target_fds_addr,
+ sizeof(abi_ulong) * nw,
+ 0)))
+return -TARGET_EFAULT;
+
+k = 0;
+for (i = 0; i  nw; i++) {
+v = 0;
+for (j = 0; j  TARGET_ABI_BITS; j++) {
+v |= ((FD_ISSET(k, fds) != 0)  j);
+k++;
 }
+__put_user(v, target_fds[i]);
 }
-#endif
+
+unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
+
+return 0;
 }
 
 #if defined(__alpha__)
@@ -567,74 +583,57 @@
 
 /* do_select() must return target values and target errnos. */
 static abi_long do_select(int n,
-  abi_ulong rfd_p, abi_ulong wfd_p,
-  abi_ulong efd_p, abi_ulong target_tv)
+  abi_ulong rfd_addr, abi_ulong wfd_addr,
+  abi_ulong efd_addr, abi_ulong target_tv_addr)
 {
 fd_set rfds, wfds, efds;
 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
-abi_long *target_rfds, *target_wfds, *target_efds;
 struct timeval tv, *tv_ptr;
 abi_long ret;
-int ok;
 
-if (rfd_p) {
-target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1);
-if (!target_rfds) {
-ret = -TARGET_EFAULT;
-goto end;
-}
-rfds_ptr = target_to_host_fds(rfds, target_rfds, n);
+if (rfd_addr) {
+if (copy_from_user_fdset(rfds, rfd_addr, n))
+return -TARGET_EFAULT;
+rfds_ptr = rfds;
 } else {
-target_rfds = NULL;
 rfds_ptr = NULL;
 }
-if (wfd_p) {
-target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1);
-if (!target_wfds) {
-ret = -TARGET_EFAULT;
-goto end;
-}
-wfds_ptr

[Qemu-devel] Re: [PATCH] 06_efault.4.patch - timeval

2007-11-20 Thread Thayne Harbaugh
This is the EFAULT for copy_{to,from}_user_timeval().  This updates to
use __get_user()/__put_user(), check return values of
copy_{to,from}_user_timeval().
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-20 12:52:33.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-20 12:52:47.0 -0700
@@ -552,30 +552,34 @@
 return 0;
 }
 
-static inline abi_long target_to_host_timeval(struct timeval *tv,
-  abi_ulong target_addr)
+static inline abi_long copy_from_user_timeval(struct timeval *tv,
+  abi_ulong target_tv_addr)
 {
 struct target_timeval *target_tv;
 
-if (!lock_user_struct(VERIFY_READ, target_tv, target_addr, 1))
+if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
 return -TARGET_EFAULT;
-tv-tv_sec = tswapl(target_tv-tv_sec);
-tv-tv_usec = tswapl(target_tv-tv_usec);
-unlock_user_struct(target_tv, target_addr, 0);
+
+__get_user(tv-tv_sec, target_tv-tv_sec);
+__get_user(tv-tv_usec, target_tv-tv_usec);
+
+unlock_user_struct(target_tv, target_tv_addr, 0);
 
 return 0;
 }
 
-static inline abi_long host_to_target_timeval(abi_ulong target_addr,
-  const struct timeval *tv)
+static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
+const struct timeval *tv)
 {
 struct target_timeval *target_tv;
 
-if (!lock_user_struct(VERIFY_WRITE, target_tv, target_addr, 0))
+if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
 return -TARGET_EFAULT;
-target_tv-tv_sec = tswapl(tv-tv_sec);
-target_tv-tv_usec = tswapl(tv-tv_usec);
-unlock_user_struct(target_tv, target_addr, 1);
+
+__put_user(tv-tv_sec, target_tv-tv_sec);
+__put_user(tv-tv_usec, target_tv-tv_usec);
+
+unlock_user_struct(target_tv, target_tv_addr, 1);
 
 return 0;
 }
@@ -614,7 +618,8 @@
 }
 
 if (target_tv_addr) {
-target_to_host_timeval(tv, target_tv_addr);
+if (copy_from_user_timeval(tv, target_tv_addr))
+return -TARGET_EFAULT;
 tv_ptr = tv;
 } else {
 tv_ptr = NULL;
@@ -630,8 +635,8 @@
 if (efd_addr  copy_to_user_fdset(efd_addr, efds, n))
 return -TARGET_EFAULT;
 
-if (target_tv_addr)
-host_to_target_timeval(target_tv_addr, tv);
+if (target_tv_addr  copy_to_user_timeval(target_tv_addr, tv))
+return -TARGET_EFAULT;
 }
 
 return ret;
@@ -3392,9 +3397,10 @@
 {
 struct timeval *tvp, tv[2];
 if (arg2) {
-target_to_host_timeval(tv[0], arg2);
-target_to_host_timeval(tv[1],
-arg2 + sizeof (struct target_timeval));
+if (copy_from_user_timeval(tv[0], arg2)
+|| copy_from_user_timeval(tv[1],
+  arg2 + sizeof(struct target_timeval)))
+goto efault;
 tvp = tv;
 } else {
 tvp = NULL;
@@ -3934,14 +3940,16 @@
 struct timeval tv;
 ret = get_errno(gettimeofday(tv, NULL));
 if (!is_error(ret)) {
-host_to_target_timeval(arg1, tv);
+if (copy_to_user_timeval(arg1, tv))
+goto efault;
 }
 }
 break;
 case TARGET_NR_settimeofday:
 {
 struct timeval tv;
-target_to_host_timeval(tv, arg1);
+if (copy_from_user_timeval(tv, arg1))
+goto efault;
 ret = get_errno(settimeofday(tv, NULL));
 }
 break;
@@ -4316,19 +4324,20 @@
 
 if (arg2) {
 pvalue = value;
-target_to_host_timeval(pvalue-it_interval,
-   arg2);
-target_to_host_timeval(pvalue-it_value,
-   arg2 + sizeof(struct target_timeval));
+if (copy_from_user_timeval(pvalue-it_interval, arg2)
+|| copy_from_user_timeval(pvalue-it_value,
+  arg2 + sizeof(struct target_timeval)))
+goto efault;
 } else {
 pvalue = NULL;
 }
 ret = get_errno(setitimer(arg1, pvalue, ovalue));
 if (!is_error(ret)  arg3) {
-host_to_target_timeval(arg3,
-   ovalue.it_interval);
-host_to_target_timeval(arg3 + sizeof(struct target_timeval),
-   ovalue.it_value);
+if (copy_to_user_timeval(arg3,
+ ovalue.it_interval)
+|| copy_to_user_timeval(arg3 

[Qemu-devel] Re: [PATCH] 06_efault.5.timespec.patch

2007-11-20 Thread Thayne Harbaugh
This uses __get_user()/__put_user() for copy_{to,from}_user_timespec().
It checks and handles return values.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-20 13:21:38.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-20 13:51:28.0 -0700
@@ -3026,28 +3026,36 @@
 }
 #endif
 
-static inline abi_long target_to_host_timespec(struct timespec *host_ts,
-   abi_ulong target_addr)
+static inline abi_long copy_from_user_timespec(struct timespec *host_ts,
+   abi_ulong target_ts_addr)
 {
 struct target_timespec *target_ts;
 
-if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
+if (!lock_user_struct(VERIFY_READ, target_ts, target_ts_addr, 1))
 return -TARGET_EFAULT;
-host_ts-tv_sec = tswapl(target_ts-tv_sec);
-host_ts-tv_nsec = tswapl(target_ts-tv_nsec);
-unlock_user_struct(target_ts, target_addr, 0);
+
+__get_user(host_ts-tv_sec, target_ts-tv_sec);
+__get_user(host_ts-tv_nsec, target_ts-tv_nsec);
+
+unlock_user_struct(target_ts, target_ts_addr, 0);
+
+return 0;
 }
 
-static inline abi_long host_to_target_timespec(abi_ulong target_addr,
-   struct timespec *host_ts)
+static inline abi_long copy_to_user_timespec(abi_ulong target_ts_addr,
+ const struct timespec *host_ts)
 {
 struct target_timespec *target_ts;
 
-if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
+if (!lock_user_struct(VERIFY_WRITE, target_ts, target_ts_addr, 0))
 return -TARGET_EFAULT;
-target_ts-tv_sec = tswapl(host_ts-tv_sec);
-target_ts-tv_nsec = tswapl(host_ts-tv_nsec);
-unlock_user_struct(target_ts, target_addr, 1);
+
+__put_user(host_ts-tv_sec, target_ts-tv_sec);
+__put_user(host_ts-tv_nsec, target_ts-tv_nsec);
+
+unlock_user_struct(target_ts, target_ts_addr, 1);
+
+return 0;
 }
 
 /* do_syscall() should always have a single exit point at the end so
@@ -3855,7 +3863,8 @@
 unlock_user(p, arg1, 0);
 if (arg3) {
 puts = uts;
-target_to_host_timespec(puts, arg3);
+if (copy_from_user_timespec(puts, arg3))
+goto efault;
 } else {
 puts = NULL;
 }
@@ -4807,17 +4816,21 @@
 struct timespec ts;
 ret = get_errno(sched_rr_get_interval(arg1, ts));
 if (!is_error(ret)) {
-host_to_target_timespec(arg2, ts);
+if (copy_to_user_timespec(arg2, ts))
+goto efault;
 }
 }
 break;
 case TARGET_NR_nanosleep:
 {
 struct timespec req, rem;
-target_to_host_timespec(req, arg1);
+
+if (copy_from_user_timespec(req, arg1))
+goto efault;
 ret = get_errno(nanosleep(req, rem));
-if (is_error(ret)  arg2) {
-host_to_target_timespec(arg2, rem);
+if (!is_error(ret)  arg2) {
+if (copy_to_user_timespec(arg2, rem))
+goto efault;
 }
 }
 break;
@@ -5491,7 +5504,8 @@
 struct timespec ts;
 ret = get_errno(clock_gettime(arg1, ts));
 if (!is_error(ret)) {
-host_to_target_timespec(arg2, ts);
+if (copy_to_user_timespec(arg2, ts))
+goto efault;
 }
 break;
 }
@@ -5502,7 +5516,8 @@
 struct timespec ts;
 ret = get_errno(clock_getres(arg1, ts));
 if (!is_error(ret)) {
-host_to_target_timespec(arg2, ts);
+if (copy_to_user_timespec(arg2, ts))
+goto efault;
 }
 break;
 }
@@ -5535,8 +5550,10 @@
 case TARGET_NR_utimensat:
 {
 struct timespec ts[2];
-target_to_host_timespec(ts, arg3);
-target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
+
+if (copy_from_user_timespec(ts, arg3)
+|| copy_from_user_timespec(ts+1, arg3+sizeof(struct target_timespec)))
+goto efault;
 if (!arg2)
 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
 else {


[Qemu-devel] [BUG][PATCH] execve processesing NULL args

2007-12-11 Thread Thayne Harbaugh
Here's a patch to avoid processing NULL args in execve.  It prevents
trying to dereference NULL.

Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-19 20:45:20.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-19 20:48:54.0 -0700
@@ -3515,7 +3515,7 @@
 
 argc = 0;
 guest_argp = arg2;
-for (gp = guest_argp; ; gp += sizeof(abi_ulong)) {
+for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
 if (get_user_ual(addr, gp))
 goto efault;
 if (!addr)
@@ -3524,7 +3524,7 @@
 }
 envc = 0;
 guest_envp = arg3;
-for (gp = guest_envp; ; gp += sizeof(abi_ulong)) {
+for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
 if (get_user_ual(addr, gp))
 goto efault;
 if (!addr)
@@ -3535,7 +3535,7 @@
 argp = alloca((argc + 1) * sizeof(void *));
 envp = alloca((envc + 1) * sizeof(void *));
 
-for (gp = guest_argp, q = argp; ;
+for (gp = guest_argp, q = argp; gp;
   gp += sizeof(abi_ulong), q++) {
 if (get_user_ual(addr, gp))
 goto execve_efault;
@@ -3546,7 +3546,7 @@
 }
 *q = NULL;
 
-for (gp = guest_envp, q = envp; ;
+for (gp = guest_envp, q = envp; gp;
   gp += sizeof(abi_ulong), q++) {
 if (get_user_ual(addr, gp))
 goto execve_efault;
@@ -3568,14 +3568,14 @@
 ret = -TARGET_EFAULT;
 
 execve_end:
-for (gp = guest_argp, q = argp; *q;
+for (gp = guest_argp, q = argp; gp  *q;
   gp += sizeof(abi_ulong), q++) {
 if (get_user_ual(addr, gp)
 || !addr)
 break;
 unlock_user(*q, addr, 0);
 }
-for (gp = guest_envp, q = envp; *q;
+for (gp = guest_envp, q = envp; gp  *q;
   gp += sizeof(abi_ulong), q++) {
 if (get_user_ual(addr, gp)
 || !addr)


[Qemu-devel] [PATCH] print default cpu_model

2007-12-11 Thread Thayne Harbaugh
The linux-user qemu help usage doesn't output the default cpu_model in
the usage.  This patch is a minimal code change to output the default
cpu_model.
Index: qemu/linux-user/main.c
===
--- qemu.orig/linux-user/main.c	2007-12-11 16:14:01.0 -0700
+++ qemu/linux-user/main.c	2007-12-11 16:54:32.0 -0700
@@ -1890,6 +1890,43 @@
 }
 #endif /* TARGET_ALPHA */
 
+static const char *get_cpu_model_default()
+{
+const char *cpu_model = any;
+
+#if defined(TARGET_I386)
+#ifdef TARGET_X86_64
+cpu_model = qemu64;
+#else
+cpu_model = qemu32;
+#endif
+#elif defined(TARGET_ARM)
+cpu_model = arm926;
+#elif defined(TARGET_M68K)
+cpu_model = any;
+#elif defined(TARGET_SPARC)
+#ifdef TARGET_SPARC64
+cpu_model = TI UltraSparc II;
+#else
+cpu_model = Fujitsu MB86904;
+#endif
+#elif defined(TARGET_MIPS)
+#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
+cpu_model = 20Kc;
+#else
+cpu_model = 24Kf;
+#endif
+#elif defined(TARGET_PPC)
+#ifdef TARGET_PPC64
+cpu_model = 970;
+#else
+cpu_model = 750;
+#endif
+#endif
+
+return cpu_model;
+}
+
 void usage(void)
 {
 printf(qemu- TARGET_ARCH  version  QEMU_VERSION , Copyright (c) 2003-2007 Fabrice Bellard\n
@@ -1900,7 +1937,7 @@
-g port   wait gdb connection to port\n
-L path   set the elf interpreter prefix (default=%s)\n
-s size   set the stack size in bytes (default=%ld)\n
-   -cpu modelselect CPU (-cpu ? for list)\n
+   -cpu modelselect CPU (default=\%s\; -cpu ? for list)\n
-drop-ld-preload  drop LD_PRELOAD for target process\n
\n
debug options:\n
@@ -1910,6 +1947,7 @@
TARGET_ARCH,
interp_prefix,
x86_stack_size,
+   get_cpu_model_default(),
DEBUG_LOGFILE);
 _exit(1);
 }
@@ -2023,38 +2061,9 @@
 init_paths(interp_prefix);
 
 if (cpu_model == NULL) {
-#if defined(TARGET_I386)
-#ifdef TARGET_X86_64
-cpu_model = qemu64;
-#else
-cpu_model = qemu32;
-#endif
-#elif defined(TARGET_ARM)
-cpu_model = arm926;
-#elif defined(TARGET_M68K)
-cpu_model = any;
-#elif defined(TARGET_SPARC)
-#ifdef TARGET_SPARC64
-cpu_model = TI UltraSparc II;
-#else
-cpu_model = Fujitsu MB86904;
-#endif
-#elif defined(TARGET_MIPS)
-#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
-cpu_model = 20Kc;
-#else
-cpu_model = 24Kf;
-#endif
-#elif defined(TARGET_PPC)
-#ifdef TARGET_PPC64
-cpu_model = 970;
-#else
-cpu_model = 750;
-#endif
-#else
-cpu_model = any;
-#endif
+cpu_model = get_cpu_model_default();
 }
+
 /* NOTE: we need to init the CPU at this stage to get
qemu_host_page_size */
 env = cpu_init(cpu_model);


[Qemu-devel] [PATCH] arm eabi TLS

2007-12-11 Thread Thayne Harbaugh
I believe Paul Brook did the original patch for arm eabi TLS.  The patch
has bounced around for a bit but hasn't been applied.  We've been using
this patch for a while and have tweaked it to be a bit more correct as
far as code organization.

Please let me know what else should be improved for this so that it can
be applied.

Thanks.
Index: qemu/configure
===
--- qemu.orig/configure	2007-12-11 10:16:49.0 -0700
+++ qemu/configure	2007-12-11 10:16:50.0 -0700
@@ -105,6 +105,7 @@
 darwin_user=no
 build_docs=no
 uname_release=
+nptl=yes
 
 # OS specific
 targetos=`uname -s`
@@ -318,6 +319,8 @@
   ;;
   *) echo ERROR: unknown option $opt; show_help=yes
   ;;
+  --disable-nptl) nptl=no
+  ;;
   esac
 done
 
@@ -413,6 +416,7 @@
 echo   --disable-linux-user disable all linux usermode emulation targets
 echo   --enable-darwin-user enable all darwin usermode emulation targets
 echo   --disable-darwin-userdisable all darwin usermode emulation targets
+echo   --disable-nptl   disable usermode NPTL guest support
 echo   --fmod-lib   path to FMOD library
 echo   --fmod-inc   path to FMOD includes
 echo   --enable-uname-release=R Return R for uname -r in usermode emulation
@@ -579,6 +583,23 @@
 }
 EOF
 
+# check NPTL support
+cat  $TMPC EOF
+#include sched.h
+void foo()
+{
+#ifndef CLONE_SETTLS
+#error bork
+#endif
+}
+EOF
+
+if $cc -c -o $TMPO $TMPC 2 /dev/null ; then
+  :
+else
+   nptl=no
+fi
+
 ##
 # SDL probe
 
@@ -743,6 +764,7 @@
 echo Documentation $build_docs
 [ ! -z $uname_release ]  \
 echo uname -r  $uname_release
+echo NPTL support  $nptl
 
 if test $sdl_too_old = yes; then
 echo - Your SDL version is too old - please upgrade to have SDL support
@@ -948,6 +970,7 @@
 echo SDL_CFLAGS=`$sdl_config --cflags`  $config_mak
   fi
 fi
+
 if test $cocoa = yes ; then
 echo #define CONFIG_COCOA 1  $config_h
 echo CONFIG_COCOA=yes  $config_mak
@@ -1183,6 +1206,15 @@
   echo #define TARGET_HAS_ELFLOAD32 1  $config_h
 fi
 
+if test $nptl = yes ; then
+case $target_cpu in
+  arm | armeb | ppc | ppc64)
+echo USE_NPTL=yes  $config_mak
+echo #define USE_NPTL 1  $config_h
+  ;;
+esac
+fi
+
 test -f ${config_h}~  cmp -s $config_h ${config_h}~  mv ${config_h}~ $config_h
 
 done # for target in $targets
Index: qemu/exec-all.h
===
--- qemu.orig/exec-all.h	2007-12-11 10:16:49.0 -0700
+++ qemu/exec-all.h	2007-12-11 10:16:50.0 -0700
@@ -340,170 +340,7 @@
 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 
-#if defined(__powerpc__)
-static inline int testandset (int *p)
-{
-int ret;
-__asm__ __volatile__ (
-  0:lwarx %0,0,%1\n
-xor. %0,%3,%0\n
-bne 1f\n
-stwcx. %2,0,%1\n
-bne- 0b\n
-  1:
-  : =r (ret)
-  : r (p), r (1), r (0)
-  : cr0, memory);
-return ret;
-}
-#elif defined(__i386__)
-static inline int testandset (int *p)
-{
-long int readval = 0;
-
-__asm__ __volatile__ (lock; cmpxchgl %2, %0
-  : +m (*p), +a (readval)
-  : r (1)
-  : cc);
-return readval;
-}
-#elif defined(__x86_64__)
-static inline int testandset (int *p)
-{
-long int readval = 0;
-
-__asm__ __volatile__ (lock; cmpxchgl %2, %0
-  : +m (*p), +a (readval)
-  : r (1)
-  : cc);
-return readval;
-}
-#elif defined(__s390__)
-static inline int testandset (int *p)
-{
-int ret;
-
-__asm__ __volatile__ (0: cs%0,%1,0(%2)\n
-			 jl0b
-			  : =d (ret)
-			  : r (1), a (p), 0 (*p)
-			  : cc, memory );
-return ret;
-}
-#elif defined(__alpha__)
-static inline int testandset (int *p)
-{
-int ret;
-unsigned long one;
-
-__asm__ __volatile__ (0:	mov 1,%2\n
-			  	ldl_l %0,%1\n
-			  	stl_c %2,%1\n
-			  	beq %2,1f\n
-			  .subsection 2\n
-			  1:	br 0b\n
-			  .previous
-			  : =r (ret), =m (*p), =r (one)
-			  : m (*p));
-return ret;
-}
-#elif defined(__sparc__)
-static inline int testandset (int *p)
-{
-	int ret;
-
-	__asm__ __volatile__(ldstub	[%1], %0
-			 : =r (ret)
-			 : r (p)
-			 : memory);
-
-	return (ret ? 1 : 0);
-}
-#elif defined(__arm__)
-static inline int testandset (int *spinlock)
-{
-register unsigned int ret;
-__asm__ __volatile__(swp %0, %1, [%2]
- : =r(ret)
- : 0(1), r(spinlock));
-
-return ret;
-}
-#elif defined(__mc68000)
-static inline int testandset (int *p)
-{
-   

[Qemu-devel] [PATCH] futimesat()

2007-12-11 Thread Thayne Harbaugh
This futimesat() patch for linux-user was never applied.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-20 21:02:40.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-20 21:03:59.0 -0700
@@ -154,6 +154,7 @@
 #define __NR_sys_faccessat __NR_faccessat
 #define __NR_sys_fchmodat __NR_fchmodat
 #define __NR_sys_fchownat __NR_fchownat
+#define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
@@ -197,6 +198,10 @@
 _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
   uid_t,owner,gid_t,group,int,flags)
 #endif
+#if defined(TARGET_NR_futimesat)  defined(__NR_futimesat)
+_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
+  const struct timeval *,times)
+#endif
 _syscall2(int,sys_getcwd1,char *,buf,size_t,size)
 _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
 #if defined(TARGET_NR_getdents64)  defined(__NR_getdents64)
@@ -5747,6 +5752,25 @@
 	break;
 #endif
 
+#if defined(TARGET_NR_futimesat)  defined(__NR_futimesat)
+case TARGET_NR_futimesat:
+{
+struct timeval tv[2];
+if (copy_from_user_timeval(tv, arg3)
+|| copy_from_user_timeval(tv+1, arg3+sizeof(struct target_timeval))) {
+goto efault;
+}
+if (!arg2)
+ret = get_errno(sys_futimesat(arg1, NULL, tv));
+else {
+p = lock_user_string(arg2);
+ret = get_errno(sys_futimesat(arg1, path(p), tv));
+unlock_user(p, arg2, 0);
+}
+}
+break;
+#endif
+
 #ifdef TARGET_NR_set_robust_list
 case TARGET_NR_set_robust_list:
 	goto unimplemented_nowarn;


[Qemu-devel] [PATCH] QEMU_STRACE documentation

2007-12-11 Thread Thayne Harbaugh
This patch adds documentation for the QEMU_STRACE environment setting.

Index: qemu/qemu-doc.texi
===
--- qemu.orig/qemu-doc.texi	2007-12-11 19:00:53.0 -0700
+++ qemu/qemu-doc.texi	2007-12-11 19:16:28.0 -0700
@@ -2437,6 +2437,17 @@
 Act as if the host page size was 'pagesize' bytes
 @end table
 
+Environment variables:
+
[EMAIL PROTECTED] @env
[EMAIL PROTECTED] QEMU_STRACE
+Print system calls and arguments similar to the 'strace' program
+(NOTE: the actual 'strace' program will not work because the user
+space emulator hasn't implemented ptrace).  At the moment this is
+incomplete.  All system calls that don't have a specific argument
+format are printed with information for six arguments.  Many
+flag-style arguments don't have decoders and will show up as numbers.
+
 @node Other binaries
 @subsection Other binaries
 
Index: qemu/linux-user/main.c
===
--- qemu.orig/linux-user/main.c	2007-12-11 19:02:01.0 -0700
+++ qemu/linux-user/main.c	2007-12-11 19:14:57.0 -0700
@@ -1943,7 +1943,12 @@
debug options:\n
-d options   activate log (logfile=%s)\n
-p pagesize  set the host page size to 'pagesize'\n
-   -strace  log system calls\n,
+   -strace  log system calls\n
+   \n
+   environment variables:\n
+   QEMU_STRACE   Print system calls and arguments similar to the\n
+ 'strace' program.  Enable by setting to any value.\n
+   ,
TARGET_ARCH,
interp_prefix,
x86_stack_size,


[Qemu-devel] [PATCH] m68k missing get_sp_from_cpustate()

2007-12-12 Thread Thayne Harbaugh
This patch adds the missing get_sp_from_cpustate() for m68k.
Index: qemu/linux-user/m68k/target_signal.h
===
--- qemu.orig/linux-user/m68k/target_signal.h	2007-12-11 10:33:23.0 -0700
+++ qemu/linux-user/m68k/target_signal.h	2007-12-11 10:33:54.0 -0700
@@ -21,4 +21,9 @@
 #define TARGET_MINSIGSTKSZ	2048
 #define TARGET_SIGSTKSZ	8192
 
+static inline abi_ulong get_sp_from_cpustate(CPUM68KState *state)
+{
+return state-aregs[7];
+}
+
 #endif /* TARGET_SIGNAL_H */


[Qemu-devel] [BUG][PATCH] signal translation (48_signal_xlate.ptach)

2007-12-12 Thread Thayne Harbaugh
There are some places where target signals and host signals aren't
correctly differentiated.  This patch addresses proper signal
translation between target and host.

* Changes variable names to be more explicit about target and host
signals.

* Calls target_to_host_signal() and host_to_target_signal() when
appropriate.

* Adds the TARGET_ prefix to locations that were incorrectly using
host signal names.

* Moves target_to_host_signal() and host_to_target_signal() to qsignal.h
to make them available to syscall.c.
Index: qemu/linux-user/signal.c
===
--- qemu.orig/linux-user/signal.c	2007-12-12 07:12:00.0 -0700
+++ qemu/linux-user/signal.c	2007-12-12 11:17:26.0 -0700
@@ -28,6 +28,7 @@
 
 #include qemu.h
 #include target_signal.h
+#include qsignal.h
 
 /*
  * Enable the DEBUG define and then set the individual DEBUG_*
@@ -66,7 +67,7 @@
 static void host_signal_handler(int host_signum, siginfo_t *info,
 void *puc);
 
-static uint8_t host_to_target_signal_table[65] = {
+uint8_t host_to_target_signal_table[65] = {
 [SIGHUP] = TARGET_SIGHUP,
 [SIGINT] = TARGET_SIGINT,
 [SIGQUIT] = TARGET_SIGQUIT,
@@ -103,7 +104,7 @@
 [SIGSYS] = TARGET_SIGSYS,
 /* next signals stay the same */
 };
-static uint8_t target_to_host_signal_table[65];
+uint8_t target_to_host_signal_table[65];
 
 static inline int on_sig_stack(unsigned long sp)
 {
@@ -117,16 +118,6 @@
 : on_sig_stack(sp) ? SS_ONSTACK : 0);
 }
 
-static inline int host_to_target_signal(int sig)
-{
-return host_to_target_signal_table[sig];
-}
-
-static inline int target_to_host_signal(int sig)
-{
-return target_to_host_signal_table[sig];
-}
-
 static void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s)
 {
@@ -334,13 +325,13 @@
 first_free = q;
 }
 
-/* abort execution with signal */
-void __attribute((noreturn)) force_sig(int sig)
+/* abort execution with target signal */
+void __attribute((noreturn)) force_sig(int target_sig)
 {
 int host_sig;
-host_sig = target_to_host_signal(sig);
+host_sig = target_to_host_signal(target_sig);
 fprintf(stderr, qemu: uncaught target signal %d (%s) - exiting\n,
-sig, strsignal(host_sig));
+target_sig, strsignal(host_sig));
 #if 1
 _exit(-host_sig);
 #else
@@ -355,23 +346,23 @@
 #endif
 }
 
-/* queue a signal so that it will be send to the virtual CPU as soon
-   as possible */
-int queue_signal(int sig, target_siginfo_t *info)
+/* queue a target signal so that it will be sent to the virtual CPU as
+   soon as possible */
+int queue_signal(int target_sig, target_siginfo_t *info)
 {
 struct emulated_sigaction *k;
 struct sigqueue *q, **pq;
 abi_ulong handler;
 
-debugf(DEBUG_SIGNAL, queue_signal: sig=%d\n, sig);
-k = sigact_table[sig - 1];
+debugf(DEBUG_SIGNAL, queue_signal: target_sig=%d\n, target_sig);
+k = sigact_table[target_sig - 1];
 handler = k-sa._sa_handler;
 if (handler == TARGET_SIG_DFL) {
 /* default handler : ignore some signal. The other are fatal */
-if (sig != TARGET_SIGCHLD 
-sig != TARGET_SIGURG 
-sig != TARGET_SIGWINCH) {
-force_sig(sig);
+if (target_sig != TARGET_SIGCHLD 
+target_sig != TARGET_SIGURG 
+target_sig != TARGET_SIGWINCH) {
+force_sig(target_sig);
 } else {
 return 0; /* indicate ignored */
 }
@@ -379,10 +370,10 @@
 /* ignore signal */
 return 0;
 } else if (handler == TARGET_SIG_ERR) {
-force_sig(sig);
+force_sig(target_sig);
 } else {
 pq = k-first;
-if (sig  TARGET_SIGRTMIN) {
+if (target_sig  TARGET_SIGRTMIN) {
 /* if non real time signal, we queue exactly one signal */
 if (!k-pending)
 q = k-info;
@@ -413,7 +404,7 @@
 static void host_signal_handler(int host_signum, siginfo_t *info,
 void *puc)
 {
-int sig;
+int target_sig;
 target_siginfo_t tinfo;
 
 /* the CPU emulator uses some host signals to detect exceptions,
@@ -424,12 +415,12 @@
 }
 
 /* get target signal number */
-sig = host_to_target_signal(host_signum);
-if (sig  1 || sig  TARGET_NSIG)
+target_sig = host_to_target_signal(host_signum);
+if (target_sig  1 || target_sig  TARGET_NSIG)
 return;
-debugf(DEBUG_SIGNAL, qemu: got signal %d\n, sig);
+debugf(DEBUG_SIGNAL, qemu: got target signal %d\n, target_sig);
 host_to_target_siginfo_noswap(tinfo, info);
-if (queue_signal(sig, tinfo) == 1) {
+if (queue_signal(target_sig, tinfo) == 1) {
 /* interrupt the virtual CPU as soon as possible */
 cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
 }
@@ -1343,7 +1334,7 @@
 
 badframe:
 	unlock_user_struct(frame, 

[Qemu-devel] [BUG][PATCH] signal termination (48_signal_terminate.patch)

2007-12-12 Thread Thayne Harbaugh
Qemu doesn't exit with the proper code when dieing from an uncaught
signal.  Exit codes for uncaught signals are -signum.  Unfortunately
the kernel filters values from exit() and _exit().

A solution is to actually die from an uncaught signal.  This patch
detects an uncaught signal, installs the default handler, and then sends
itself the signal and waits for it.  It depends on the previous
48_signal_xlate.patch that I sent.
Index: qemu/linux-user/signal.c
===
--- qemu.orig/linux-user/signal.c	2007-12-12 11:17:26.0 -0700
+++ qemu/linux-user/signal.c	2007-12-12 11:26:42.0 -0700
@@ -330,20 +330,31 @@
 {
 int host_sig;
 host_sig = target_to_host_signal(target_sig);
+struct sigaction act;
 fprintf(stderr, qemu: uncaught target signal %d (%s) - exiting\n,
 target_sig, strsignal(host_sig));
-#if 1
-_exit(-host_sig);
-#else
-{
-struct sigaction act;
-sigemptyset(act.sa_mask);
-act.sa_flags = SA_SIGINFO;
-act.sa_sigaction = SIG_DFL;
-sigaction(SIGABRT, act, NULL);
-abort();
-}
-#endif
+
+/* The proper exit code for dieing from an uncaught signal is
+ * -signal.  The kernel doesn't allow exit() or _exit() to pass
+ * a negative value.  To get the proper exit code we need to
+ * actually die from an uncaught signal.  Here the default signal
+ * handler is installed, we send ourself a signal and we wait for
+ * it to arrive. */
+sigfillset(act.sa_mask);
+act.sa_handler = SIG_DFL;
+sigaction(host_sig, act, NULL);
+
+/* For some reason raise(host_sig) doesn't send the signal when
+ * statically linked on x86-64. */
+kill(getpid(), host_sig);
+
+/* Make sure the signal isn't masked (just reuse the mask inside
+of act) */
+sigdelset(act.sa_mask, host_sig);
+sigsuspend(act.sa_mask);
+
+/* unreachable */
+assert(0);
 }
 
 /* queue a target signal so that it will be sent to the virtual CPU as


Re: [Qemu-devel] [PATCH] arm eabi TLS

2007-12-12 Thread Thayne Harbaugh

On Thu, 2007-12-13 at 01:21 +, Paul Brook wrote:
  - It would be good to limit the changes in the CPU emulation code to
  handle the TLS. For example, on MIPS, the TLS register must not be
  stored in the CPU state. Same for ARM.
 
 I disagree. The TLS register is part of the CPU state. On many machines 
 (including ARMv6 CPUs) it's an actual CPU register. I'm fairly sure the same 
 is true for recent MIPS revisions.

I agree with Paul.  Some archs actually use a CPU register and require
the kernel to help manage TLS.  Other archs can manage TLS completely in
user space.  It's been a while since I've investigated all the details
for each arch but I'll go review it.





[Qemu-devel] [BUG][PATCH] getsockopt() errno

2007-12-12 Thread Thayne Harbaugh
linux-user getsockopt() doesn't return the correct errnos for certain
cases.  This fixes errnos for unsupported levels and unsupported SOL_IP
option names.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-12-12 20:48:56.0 -0700
+++ qemu/linux-user/syscall.c	2007-12-12 20:50:05.0 -0700
@@ -1010,14 +1010,15 @@
 }
 break;
 default:
-goto unimplemented;
+ret = -TARGET_ENOPROTOOPT;
+break;
 }
 break;
 default:
 unimplemented:
 gemu_log(getsockopt level=%d optname=%d not yet supported\n,
  level, optname);
-ret = -TARGET_ENOSYS;
+ret = -TARGET_EOPNOTSUPP;
 break;
 }
 return ret;


[Qemu-devel] [BUG][PATCH] nanosleep doesn't write remaining time

2007-12-12 Thread Thayne Harbaugh
nanosleep() doesn't write remaining time if there's an error - but it's
when return value == -1 and errno == EINTR when the remaining time must
be written.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-12-12 22:01:13.0 -0700
+++ qemu/linux-user/syscall.c	2007-12-12 22:08:49.0 -0700
@@ -5134,7 +5134,7 @@
 if (copy_from_user_timespec(req, arg1))
 goto efault;
 ret = get_errno(nanosleep(req, rem));
-if (!is_error(ret)  arg2) {
+if (ret == -TARGET_EINTR  arg2) {
 if (copy_to_user_timespec(arg2, rem))
 goto efault;
 }


[Qemu-devel] [BUG][PATCH] setsockopt() errno

2007-12-12 Thread Thayne Harbaugh
linux-user setsockopt() doesn't return the correct errno for certain
cases.  This fixes errno for unsupported levels.  It's similar to the
bug in getsockopt().
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-12-12 22:26:51.0 -0700
+++ qemu/linux-user/syscall.c	2007-12-12 22:27:41.0 -0700
@@ -920,7 +920,7 @@
 default:
 unimplemented:
 gemu_log(Unsupported setsockopt level=%d optname=%d \n, level, optname);
-ret = -TARGET_ENOSYS;
+ret = -TARGET_ENOPROTOOPT;
 }
 return ret;
 }


[Qemu-devel] [BUG][PATCH] check socklen_t values in linux-user

2007-12-17 Thread Thayne Harbaugh
Qemu doesn't check socklen_t values before using them.  If a value is
provided that is large (say -1) then qemu will merrily use it in
alloca() (which will blow the stack).  The kernel checks all socklen_t
values for  0 or  MAX_SOCK_ADDR.

This patch mimics the kernel behavior - which prevents SEGVs.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-12-17 21:16:47.0 -0700
+++ qemu/linux-user/syscall.c	2007-12-17 21:51:14.0 -0700
@@ -1221,11 +1221,19 @@
 return get_errno(socket(domain, type, protocol));
 }
 
+/* MAX_SOCK_ADDR from linux/net/socket.c */
+#define MAX_SOCK_ADDR	128
+
 /* do_bind() Must return target values and target errnos. */
 static abi_long do_bind(int sockfd, abi_ulong target_saddr_addr,
 socklen_t addrlen)
 {
-void *addr = alloca(addrlen);
+void *addr;
+
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR)
+return -TARGET_EINVAL;
+
+addr = alloca(addrlen);
 
 if (copy_from_user_sockaddr(addr, target_saddr_addr, addrlen))
 return -TARGET_EFAULT;
@@ -1237,7 +1245,12 @@
 static abi_long do_connect(int sockfd, abi_ulong target_saddr_addr,
socklen_t addrlen)
 {
-void *addr = alloca(addrlen);
+void *addr;
+
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR)
+return -TARGET_EINVAL;
+
+addr = alloca(addrlen);
 
 if (copy_from_user_sockaddr(addr, target_saddr_addr, addrlen))
 return -TARGET_EFAULT;
@@ -1318,6 +1331,9 @@
 if (get_user_u32(addrlen, target_addrlen_addr))
 return -TARGET_EINVAL;
 
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR)
+return -TARGET_EINVAL;
+
 addr = alloca(addrlen);
 
 ret = get_errno(accept(fd, addr, addrlen));
@@ -1340,6 +1356,9 @@
 if (get_user_u32(addrlen, target_addrlen_addr))
 return -TARGET_EFAULT;
 
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR)
+return -TARGET_EINVAL;
+
 addr = alloca(addrlen);
 
 ret = get_errno(getpeername(fd, addr, addrlen));
@@ -1362,6 +1381,9 @@
 if (get_user_u32(addrlen, target_addrlen_addr))
 return -TARGET_EFAULT;
 
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR)
+return -TARGET_EINVAL;
+
 addr = alloca(addrlen);
 
 ret = get_errno(getsockname(fd, addr, addrlen));
@@ -1397,9 +1419,13 @@
 void *host_msg;
 abi_long ret;
 
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR)
+return -TARGET_EINVAL;
+
 host_msg = lock_user(VERIFY_READ, msg, len, 1);
 if (!host_msg)
 return -TARGET_EFAULT;
+
 if (target_saddr_addr) {
 addr = alloca(addrlen);
 if (copy_from_user_sockaddr(addr, target_saddr_addr, addrlen))
@@ -1415,7 +1441,7 @@
 /* do_recvfrom() Must return target values and target errnos. */
 static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
 abi_ulong target_saddr_addr,
-abi_ulong target_addrlen)
+abi_ulong target_addrlen_addr)
 {
 socklen_t addrlen;
 void *addr;
@@ -1426,10 +1452,14 @@
 return -TARGET_EFAULT;
 
 if (target_saddr_addr) {
-if (get_user_u32(addrlen, target_addrlen)) {
+if (get_user_u32(addrlen, target_addrlen_addr)) {
 ret = -TARGET_EFAULT;
 goto fail;
 }
+if (addrlen  0 || addrlen  MAX_SOCK_ADDR) {
+ret = -TARGET_EINVAL;
+goto fail;
+}
 if (addrlen  sizeof(struct sockaddr_storage)) {
 ret = -TARGET_EINVAL;
 goto fail;
@@ -1444,7 +1474,7 @@
 if (!is_error(ret)) {
 if (target_saddr_addr) {
 if (copy_to_user_sockaddr(target_saddr_addr, addr, addrlen)
-|| put_user_u32(addrlen, target_addrlen)) {
+|| put_user_u32(addrlen, target_addrlen_addr)) {
 ret = -TARGET_EFAULT;
 goto fail;
 }


[Qemu-devel] [BUG][PATCH] DEBUG_REMAP

2007-12-19 Thread Thayne Harbaugh
This fixes a compile error for a variable that wasn't changed (it was
previously renamed to make the variable more descriptive).  It also adds
#include stdlib for prototypes of malloc() and free().
Index: qemu/linux-user/qemu.h
===
--- qemu.orig/linux-user/qemu.h	2007-12-18 09:11:41.0 -0700
+++ qemu/linux-user/qemu.h	2007-12-18 09:26:26.0 -0700
@@ -7,6 +7,11 @@
 
 #include cpu.h
 
+#undef DEBUG_REMAP
+#ifdef DEBUG_REMAP
+#include stdlib.h
+#endif /* DEBUG_REMAP */
+
 #ifdef TARGET_ABI32
 typedef uint32_t abi_ulong;
 typedef int32_t abi_long;
@@ -374,7 +379,7 @@
 if (host_ptr == g2h(guest_addr))
 return;
 if (len  0)
-memcpy(g2h(guest_ptr), host_ptr, len);
+memcpy(g2h(guest_addr), host_ptr, len);
 free(host_ptr);
 #endif
 }


[Qemu-devel] PPC linux-user

2007-12-26 Thread Thayne Harbaugh
I'm wondering if there's a known problem with PPC linux-user.  It
appears that static binaries work, but those that are dynamically linked
seem to always fail in the same way:

./ppc-linux-user/c2-qemu-ppc -L /var/chroots/ppc /var/chroots/ppc/bin/ls /
Invalid data memory access: 0x662c2008
NIP 4008b3d8   LR 4008b4ac CTR  XER 
MSR 6040 HID0   HF 6000 idx 0
TB   
GPR00 0001e087 4007edd0  8a502010
GPR04 4009da2c 000b 0002 0003
GPR08  48480010 42082000 662c1ff4
GPR12 400913a0  4007ee34 
GPR16 000b 400b0730 0001 
GPR20 400b0550 400b1658  10001575
GPR24 8a502010 42082000 b7b9e077 0605
GPR28  0302 400b0ff4 2423fff4
CR 44042022  [ G  G  -  G  E  -  E  E  ] RES 
FPR00    
FPR04    
FPR08    
FPR12    
FPR16    
FPR20    
FPR24    
FPR28    
qemu: uncaught target signal 11 (Segmentation fault) - exiting
Segmentation fault

qemu.log shows that the last two tb appear to be identical - which is
odd that it fails (sorry for the spewage):

NIP 4008b3b4   LR 4008b4ac CTR  XER 2000
MSR 6040 HID0   HF 6000 idx 0
TB   
GPR00 0001e087 4007ede0  8a502010
GPR04 4009da2c 000b 0002 0004
GPR08  0606 42082000 4208200b
GPR12 400913a0  4007ee44 
GPR16 000b 400b0730 0001 
GPR20 400b0550 400b1658  10001575
GPR24  42082000  0605
GPR28 400b15e8 0001e087 400b0ff4 42082000
CR 44042022  [ G  G  -  G  E  -  E  E  ] RES 
FPR00    
FPR04    
FPR08    
FPR12    
FPR16    
FPR20    
FPR24    
FPR28    
IN: 
0x4008b3b4:  srawi  r29,r27,1
0x4008b3b8:  addze  r29,r29
0x4008b3bc:  mulli  r9,r9,12
0x4008b3c0:  li r28,0
0x4008b3c4:  mulli  r31,r29,12
0x4008b3c8:  addi   r9,r9,16
0x4008b3cc:  subf   r26,r9,r0
0x4008b3d0:  addr24,r25,r9
0x4008b3d4:  addr11,r31,r25
0x4008b3d8:  lwzr0,20(r11)
0x4008b3dc:  cmplw  cr7,r0,r26
0x4008b3e0:  bltcr7,4008B41C

OP:
0x: load_gpr_T0_gpr27
0x0001: move_T1_T0
0x0002: srawi 0x1 0x1
0x0003: store_T0_gpr_gpr29
0x0004: load_gpr_T0_gpr29
0x0005: move_T2_T0
0x0006: add_ze
0x0007: check_addc
0x0008: store_T0_gpr_gpr29
0x0009: load_gpr_T0_gpr9
0x000a: mulli 0xc
0x000b: store_T0_gpr_gpr9
0x000c: set_T0 0x0
0x000d: store_T0_gpr_gpr28
0x000e: load_gpr_T0_gpr29
0x000f: mulli 0xc
0x0010: store_T0_gpr_gpr31
0x0011: load_gpr_T0_gpr9
0x0012: addi 0x10
0x0013: store_T0_gpr_gpr9
0x0014: load_gpr_T0_gpr9
0x0015: load_gpr_T1_gpr0
0x0016: subf
0x0017: store_T0_gpr_gpr26
0x0018: load_gpr_T0_gpr25
0x0019: load_gpr_T1_gpr9
0x001a: add
0x001b: store_T0_gpr_gpr24
0x001c: load_gpr_T0_gpr31
0x001d: load_gpr_T1_gpr25
0x001e: add
0x001f: store_T0_gpr_gpr11
0x0020: load_gpr_T0_gpr11
0x0021: addi 0x14
0x0022: print_mem_EA
0x0023: lwz_raw
0x0024: store_T1_gpr_gpr0
0x0025: load_gpr_T0_gpr0
0x0026: load_gpr_T1_gpr26
0x0027: cmpl
0x0028: store_T0_crf_crf7
0x0029: load_crf_T0_crf7
0x002a: test_true 0x8
0x002b: jz_T0 0x0
0x002c: goto_tb0 0x60234810
0x002d: set_T1 0x4008b41c
0x002e: b_T1
0x002f: set_T0 0x60234810
0x0030: exit_tb
0x0031: goto_tb1 0x60234810
0x0032: set_T1 0x4008b3e4
0x0033: b_T1
0x0034: set_T0 0x60234811
0x0035: exit_tb
0x0036: end

OUT: [size=460]
0x61c46920:  mov0x108(%r14),%r15
0x61c46927:  mov%r15,%r12
0x61c4692a:  lea-1640261935(%rip),%ecx# 0x1

Re: [Qemu-devel] [PATCH] zero/NULL fixes.

2008-01-09 Thread Thayne Harbaugh

On Wed, 2008-01-09 at 16:14 -0300, Lauro Ramos Venancio wrote:
 I think these patches are important bugfixes and they should be
 applied on the qemu head.
 They fix some LTP tests.

Tonight I'll be pulling my local tree up to CVS current and I'll resend
any remaining EFAULT and zero/NULL patches that haven't been included.
Right now I simply haven't tracked which patches have been incorporated
and which ones are pending.

Thanks for the interest.

 2007/12/11, Thayne Harbaugh [EMAIL PROTECTED]:
  The EFAULT changes use a result of NULL to detect a failure from lock*()
  functions.  There are syscalls that accept NULL as a valid argument and
  now the syscalls return -EFAULT.  These patches allow appropriate
  syscalls to accept NULL.
 
  I have put together a regression test harness wrapped around the Linux
  Test Project (LTP).  I've been able to find regressions that were caused
  by the EFAULT changes.  It's more exhaustive than running an ls
  executable and has helped find existing bugs as well as regressions.  It
  will run regression tests for multiple architectures.
 
  I'll be sending a few more patches for this same type of regression.  I
  should also be sending in the test harness once I've worked out a few
  more details.