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.
> >
> >





[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

[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 " 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 
+#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] [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] 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] 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] 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;


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] 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 -.  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
+ * -.  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


[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 @@
 
 badfra

[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] [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] 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] 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 <
+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]"
-  

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

2007-12-11 Thread Thayne Harbaugh
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.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-28 16:36:53.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-28 17:03:31.0 -0700
@@ -5399,7 +5399,7 @@
 
 grouplist = alloca(gidsetsize * sizeof(gid_t));
 ret = get_errno(getgroups(gidsetsize, grouplist));
-if (!is_error(ret)) {
+if (!is_error(ret) && arg1) {
 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
 if (!target_grouplist)
 goto efault;
@@ -5549,7 +5549,7 @@
 
 grouplist = alloca(gidsetsize * sizeof(gid_t));
 ret = get_errno(getgroups(gidsetsize, grouplist));
-if (!is_error(ret)) {
+if (!is_error(ret) && arg1) {
 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
 if (!target_grouplist) {
 ret = -TARGET_EFAULT;
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-28 17:26:46.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-28 17:29:11.0 -0700
@@ -3398,10 +3398,14 @@
 ret = 0; /* avoid warning */
 break;
 case TARGET_NR_read:
-if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
-goto efault;
-ret = get_errno(read(arg1, p, arg3));
-unlock_user(p, arg2, ret);
+if (!arg3)
+ret = 0;
+else {
+if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+goto efault;
+ret = get_errno(read(arg1, p, arg3));
+unlock_user(p, arg2, ret);
+}
 break;
 case TARGET_NR_write:
 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-28 22:44:27.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-28 22:46:16.0 -0700
@@ -1203,7 +1203,7 @@
 abi_long ret;
 
 if (get_user_u32(addrlen, target_addrlen_addr))
-return -TARGET_EFAULT;
+return -TARGET_EINVAL;
 
 addr = alloca(addrlen);
 
Index: qemu/linux-user/path.c
===
--- qemu.orig/linux-user/path.c	2007-11-28 23:13:12.0 -0700
+++ qemu/linux-user/path.c	2007-11-28 23:13:24.0 -0700
@@ -152,7 +152,7 @@
 {
 /* Only do absolute paths: quick and dirty, but should mostly be OK.
Could do relative by tracking cwd. */
-if (!base || name[0] != '/')
+if (!base || !name || name[0] != '/')
 	return name;
 
 return follow_path(base, name) ?: name;
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-11-28 23:01:10.0 -0700
+++ qemu/linux-user/syscall.c	2007-11-28 23:13:06.0 -0700
@@ -3864,8 +3864,12 @@
 goto unimplemented;
 #endif
 case TARGET_NR_acct:
-if (!(p = lock_user_string(arg1)))
-goto efault;
+if (arg1) {
+if (!(p = lock_user_string(arg1)))
+goto efault;
+} else {
+p = NULL;
+}
 ret = get_errno(acct(path(p)));
 unlock_user(p, arg1, 0);
 break;


[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] [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] 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] 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_interv

[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

[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 {
-

[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.





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; j0; i--) {
 if (libinfo[i].loaded) {
 /* Push previos first to call address */
---sp;	put_user(start_addr, sp);
+--sp;
+if (

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 
>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] [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 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: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.









[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; j0; i--) {
 i

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

2007-11-14 Thread Thayne Harbaugh

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.





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

2007-11-14 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.

I just noticed that I missed m68k-semi.c.  New patch is forthcoming.





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_TYP

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.





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

2007-11-14 Thread Thayne Harbaugh
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.
Index: qemu/linux-user/elfload.c
===
--- qemu.orig/linux-user/elfload.c	2007-11-13 16:32:38.0 -0700
+++ qemu/linux-user/elfload.c	2007-11-13 16:32:44.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-13 16:32:38.0 -0700
+++ qemu/linux-user/flatload.c	2007-11-13 22:47:06.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; j0; i--) {
 if (libinfo[i].loaded) {
 /* Push previos first to call address */
---sp;	put_user(start_addr, sp);
+--sp;
+if (put_user(start_addr, sp, abi_ulong))
+return -EFAULT;
 start_addr = libinfo[i].entry;

[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 uin

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
> 
> 





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] 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-05 Thread Thayne Harbaugh
Here's a better explanation as to why I initially mixed lock_user() and
copy_to_user():

On Tue, 2007-11-06 at 01:05 +, Paul Brook wrote:
> > 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.
> 
> >   I don't think there's an appropriate way
> > to eliminate either {lock,unlock}_user() or {get,put}_user() and keep
> > comparable coding semantics to the kernel.
> 
> Your argument seems inconsistent to me. The kernel doesn't have lock_user at 
> all, so how can using it be consistent with kernel code?

See your comment below about how qemu differs from the kernel.

> There are two different strategies for accessing user data. Either:
> 
> - Use a copying interface. i.e. get_user (for single values) or  
> copy_from_user (for blocks/structures).
> - Use a locking interface. i.e. lock_user.
> 
> Personally I like the locking interface as it allows a zero-copy 
> implementation. However the kernel uses a copying interface, and my 
> understanding is that other qemu maintainers also prefer the copying 
> interface.

The "zero-copy" nature of lock_user() is why I mixed the two.
lock_user() was pushed down inside of wrapper functions.  External to
the wrapper functions the code was very comparable to the kernel code.
It was the best of both worlds.

> Part of the problem may be that linux assumes that both kernel and userspace 
> pointers can be represented by the compiler. This allows it to do address 
> arithmetic and take the address of members of pointers to userspace 
> structures. qemu can not do this.

It is precisely this difference that I felt that a minor deviation was
acceptable: mixing lock_user() with copy_to_user().  My solution had the
zero-copy capability while making high-level syscall wrapper code very
comparable to kernel code.

In the end I'd just rather code it your way and move on then argue why I
think my way is better - just keep in mind that there were intelligent
decisions behind why I did it the way I did it - it wasn't haphazard
(although I did send a few half-baked patches that weren't correct to
the list - I can be a bonehead in other ways 8-)).





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_() 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.  

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 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_() 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] 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_() 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);

re

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] 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-)





[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.





[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]);
+  

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

2007-11-02 Thread Thayne Harbaugh

On Fri, 2007-11-02 at 15:28 +0200, Felipe Contreras wrote:
> On 10/22/07, Thayne Harbaugh <[EMAIL PROTECTED]> wrote:
> >
> > On Sat, 2007-10-20 at 21:34 +0100, Thiemo Seufer wrote:



> > > Please submit this patch (and resend what you think was missed).
> >
> > I'll get them reworked and re-sent soon.
> >
> > Thanks for the interest.
> 
> Do you have anything that can be tried out already?

Try these:

09_arm_eabitls.patch:  This is for TLS on arm.  We have used it
extensively and it appears quite solid.  It should apply to a stock CVS
tree - although we use it on top of about 15 other patches so YMMV.

40_tls.patch: This is more for i386.  It works mostly, but I don't trust
it.  It doesn't apply to a stock CVS tree.

There are a few things that should be reworked on both of these patches.
I haven't sent them up-stream because I'm working to get foundational
patches accepted first.  The sooner I can get the EFAULT patches
accepted then the sooner I can rework these patches and make them more
acceptable to be committed.  Right now I don't think either of them
should be committed (although 09_arm_eabitls.patch is better than
40_tls.patch).

Good luck!
Index: qemu/configure
===
--- qemu.orig/configure	2007-10-15 13:52:07.0 -0600
+++ qemu/configure	2007-10-15 13:52:38.0 -0600
@@ -102,6 +102,7 @@
 darwin_user="no"
 build_docs="no"
 uname_release=""
+nptl="yes"
 
 # OS specific
 targetos=`uname -s`
@@ -303,6 +304,8 @@
 *) echo "undefined SPARC architecture. Exiting";exit 1;;
   esac
   ;;
+  --disable-nptl) nptl="no"
+  ;;
   esac
 done
 
@@ -388,6 +391,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"
@@ -554,6 +558,23 @@
 }
 EOF
 
+# check NPTL support
+cat > $TMPC <
+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
 
@@ -717,6 +738,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"
@@ -1122,6 +1144,14 @@
 echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
 fi
 fi
+else
+if test "$nptl" = "yes" ; then
+case "$target_cpu" in
+  arm | armeb | ppc | ppc64)
+echo "#define USE_NPTL 1" >> $config_h
+  ;;
+esac
+fi
 fi
 
 if test "$cocoa" = "yes" ; then
Index: qemu/exec-all.h
===
--- qemu.orig/exec-all.h	2007-10-15 13:52:07.0 -0600
+++ qemu/exec-all.h	2007-10-15 13:52:32.0 -0600
@@ -391,170 +391,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"

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.:
> > 
> > 
> > 
> > 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

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 - 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 prob

[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();\


[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)\


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.





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-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] [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:



> > 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().



> 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 tar

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:


> 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)







[Qemu-devel] [PATCH] syscall_target_errno.patch

2007-10-10 Thread Thayne Harbaugh
I appreciate the work that Jocelyn did to correct the types used
throughout linux-user/syscall.c.  Along those same lines I am working on
several patches to eliminate some incorrect constructs that have crept
into syscall.c - some of which I have ignorantly propagated in previous
patches that I have submitted.

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().

Please send comments - I have several more patches that will build on
this one as well as a few more patches that will fix other incorrect
constructs with target/host address handling.

Thanks.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-10-10 17:00:00.0 -0600
+++ qemu/linux-user/syscall.c	2007-10-10 17:09:34.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));
 }
 
+/* do_connect() Must return target values and target errnos. */
 static target_long do_connect(in

[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] qemu Makefile.target

2007-10-09 Thread Thayne Harbaugh

On Tue, 2007-10-09 at 11:43 +0200, J. Mayer wrote:
> On Mon, 2007-10-08 at 21:33 +0200, Stefan Weil wrote:
> > Blue Swirl schrieb:
> > > On 6/1/07, Stefan Weil <[EMAIL PROTECTED]> wrote:
> > >> Wouldn't it be better to let the compiler create dependency files
> > >> which make can read? I posted a patch some time ago and use it
> > >> since many months for different QEMU target platforms.
> > >
> > > I don't know, the dependencies aren't changing very often.

With the many features that I have been adding to our private branch the
dependencies are changing and I've been considering how to make the
dependencies more automated.

> > The current Makefile.target contains a lot of dependencies,
> > and I think they change often, their number is growing and
> > nevertheless they are far from being complete.
> > 
> > The appended patch removes most explicit dependencies and
> > adds gcc flags which create dependency files during normal
> > compilation (so they are always up-to-date).
> 
> I arrived to the same conclusion, that hand coded dependencies are
> always bugged and/or incomplete.

I'm interested in seeing this, also.  I have begun building out new
features for linux-user emulation and auto-generating the dependencies
will be helpful - as well as ensure that the dependencies are
up-to-date.

>  I then was to propose a similar patch
> with a few small differences. As -MMD / -MP is a preprocessor option, it
> seems more logical to add them in CPPFLAGS. The second difference is
> that it seems better to use the following syntax to include dependency
> files:
> -include $(wildcard *.d)
> -include $(wildcard */*.d)
> (some also include /dev/null in the list then it's never empty...)
> 
> This patch has a great drawback; you are to recompile almost everything
> any time you change vl.h or target-xxx/cpu.h, for example. This, imho,
> should not prevent us to apply it but shows us that most headers should
> be splitted in a better way.

A similar example is linux-user/qemu.h.  I want to submit some patches
that will start breaking up the linux-user files.  The linux-user
emulation will benefit by breaking files up according to architecture
rather than #ifdef'ing all the archs in the same file.  If have also run
into problems with too many #include files causing collisions of
typedefs from system headers (yes, this indicates poorly constructed
system headers).

>  As an example, it seems strange to me to
> declare all devices prototypes in vl.h when those declaration should
> never be used outside of hw subdirectory, where all hardware devices
> emulation related stuff should stay. I guess we could find a lot of
> examples of declarations/prototypes globally exported but only used
> locally. Fixing this would make the code cleaner and, as a side effect,
> would avoid a lot of waste of time recompiling useless stuff when doing
> changes in headers.

I agree.





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

2007-10-02 Thread Thayne Harbaugh
On Wed, 2007-09-19 at 06:53 -0600, Thayne Harbaugh wrote:
> This patch adds the futimesat syscall to linux-user.

The previous futimesat() patch that was sent was horribly brain-damaged:
it used timespec in a few places that should have used timeval.  This is
a corrected patch.

I'm sure the previous patch was composed and sent by my evil twin from a
parallel universe.  I will find him and discipline him appropriately.

Yeah, that's it.
Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-28 13:08:43.0 -0600
+++ qemu/linux-user/syscall.c	2007-10-02 14:56:47.0 -0600
@@ -151,6 +151,7 @@
 
 
 #define __NR_sys_uname __NR_uname
+#define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
@@ -172,6 +173,10 @@
 }
 #endif
 _syscall1(int,sys_uname,struct new_utsname *,buf)
+#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)
@@ -4873,6 +4878,30 @@
 	break;
 #endif
 
+#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
+case TARGET_NR_futimesat:
+{
+struct timeval tv[2];
+if (copy_from_user_timeval(tv, (struct target_timeval *)arg3)
+|| copy_from_user_timeval(tv+1, (struct target_timeval *)arg3+1)) {
+	ret = -EFAULT;
+	goto fail;
+}
+if (!arg2)
+ret = get_errno(sys_futimesat(arg1, NULL, tv));
+else {
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret =  -EFAULT;
+		else
+ret = get_errno(sys_futimesat(arg1, path(p), tv));
+if (p)
+unlock_user(p, arg2, 0);
+}
+}
+break;
+#endif
+
 #ifdef TARGET_NR_set_robust_list
 case TARGET_NR_set_robust_list:
 	goto unimplemented_nowarn;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-28 13:08:43.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-10-02 14:54:56.0 -0600
@@ -325,4 +325,5 @@
 #define TARGET_NR_mbind			319
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
+#define TARGET_NR_futimesat			326
 #define TARGET_NR_utimensat			348
Index: qemu/linux-user/i386/syscall_nr.h
===
--- qemu.orig/linux-user/i386/syscall_nr.h	2007-09-28 13:08:43.0 -0600
+++ qemu/linux-user/i386/syscall_nr.h	2007-10-02 14:54:56.0 -0600
@@ -274,6 +274,8 @@
 #define TARGET_NR_tgkill		270
 #define TARGET_NR_utimes		271
 
+#define TARGET_NR_futimesat		299
+
 #define TARGET_NR_set_robust_list	311
 
 #define TARGET_NR_utimensat		320


[Qemu-devel] [PATCH] mixed types in target_mremap() return incorrect value

2007-10-01 Thread Thayne Harbaugh
There are mixed types (long vs target_ulong) in
linux-user/mmap.c:target_mremap() and consequently the wrong value is
returned (automatic type casting fails) when the host long is larger
than the guest long and -1 is returned for an error condition.

Consider the initial lines of target_mremap() where a failure is tested:

long target_mremap(target_ulong old_addr, target_ulong old_size,
   target_ulong new_size, unsigned long flags,
   target_ulong new_addr)
{
int prot;

/* XXX: use 5 args syscall */
new_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
if (new_addr == -1)
return new_addr;

Note that signed long is the return type for target_mremap() while
target_ulong is used for new_addr and the return value of mremap().
When the host long is larger than the target long the following can
happen on mremap() failure: -1 is stored in new_addr which is unsigned.
The test for new_addr == -1 is true because the -1 is cast to
target_ulong.  When new_addr is returned, however, new_addr is cast to
long, which is larger than target_ulong for the case of i386 target on
x86_64 guest and the -1 is now a positive number that can be fully
represented as a positive number even though the return value is signed.

This patch is one way to ensure that -1 is always returned for an error
condition:

Index: qemu/linux-user/mmap.c
===
--- qemu.orig/linux-user/mmap.c 2007-10-02 00:27:36.0 -0600
+++ qemu/linux-user/mmap.c  2007-10-02 00:31:41.0 -0600
@@ -395,7 +395,7 @@
 /* XXX: use 5 args syscall */
 new_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags);
 if (new_addr == -1)
-return new_addr;
+return -1;
 new_addr = h2g(new_addr);
 prot = page_get_flags(old_addr);
 page_set_flags(old_addr, old_addr + old_size, 0);






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

2007-10-01 Thread Thayne Harbaugh
On Wed, 2007-09-26 at 14:06 -0600, Thayne Harbaugh wrote:
> 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.

I didn't see any discussion about this nor did I see it committed.  Were
there any concerns or objections?  It fixes several failures in the LTP
test suite.

The bug is that the kernel returns -1 on error and 1-40 on success - the
libc wrapper remaps this to -1 or error and -20 - 19 on succes (errno
must be cleared and checked for the -1 case to determine if there was an
error).  If qemu uses the libc wrapper then the return value is aleady
remapped to negative numbers - which appear to be errors.






[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 
 #include 
 
+#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;


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  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] [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] [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 
 #include 
 
+#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->fp

[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 
 #include 
 
+#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 i

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.





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] Re: [PATCH] linux-user utimensat() syscall

2007-09-24 Thread Thayne Harbaugh
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.





[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


[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(

[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 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 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 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 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 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 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 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 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 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 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 futimesat() syscall

2007-09-19 Thread Thayne Harbaugh
This patch adds the futimesat syscall to linux-user.

Index: qemu/linux-user/syscall.c
===
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:17:45.0 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:18:58.0 -0600
@@ -151,6 +151,7 @@
 
 
 #define __NR_sys_uname __NR_uname
+#define __NR_sys_futimesat __NR_futimesat
 #define __NR_sys_getcwd1 __NR_getcwd
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
@@ -172,6 +173,10 @@
 }
 #endif
 _syscall1(int,sys_uname,struct new_utsname *,buf)
+#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)
@@ -4873,6 +4878,30 @@
 	break;
 #endif
 
+#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
+case TARGET_NR_futimesat:
+{
+struct timeval tv[2];
+if (copy_from_user_timespec(tv, (struct target_timespec *)arg3)
+|| copy_from_user_timespec(tv+1, (struct target_timespec *)arg3+1)) {
+	ret = -EFAULT;
+	goto fail;
+}
+if (!arg2)
+ret = get_errno(sys_futimesat(arg1, NULL, tv));
+else {
+p = lock_user_string(arg2);
+if (!access_ok(VERIFY_READ, p, 1))
+ret =  -EFAULT;
+		else
+ret = get_errno(sys_futimesat(arg1, path(p), tv));
+if (p)
+unlock_user(p, arg2, 0);
+}
+}
+break;
+#endif
+
 #ifdef TARGET_NR_set_robust_list
 case TARGET_NR_set_robust_list:
 	goto unimplemented_nowarn;
Index: qemu/linux-user/arm/syscall_nr.h
===
--- qemu.orig/linux-user/arm/syscall_nr.h	2007-09-19 06:17:18.0 -0600
+++ qemu/linux-user/arm/syscall_nr.h	2007-09-19 06:18:22.0 -0600
@@ -325,4 +325,5 @@
 #define TARGET_NR_mbind			319
 #define TARGET_NR_get_mempolicy		320
 #define TARGET_NR_set_mempolicy		321
+#define TARGET_NR_futimesat			326
 #define TARGET_NR_utimensat			348


[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] [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.





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:



> >>> ./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 ()



> 
> 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.





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 ()



> >   
> 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.






[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] 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] 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] 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