ok, thank you very much. Now I understand the problem... and I see the correct way of mending it.
Your patch works for me. >On Mon, Oct 1, 2012 at 1:52 PM, Alexander Graf <ag...@suse.de> wrote: > > On 30.09.2012, at 20:50, Alex Barcelo wrote: > >> This error may be a PPC specific problem, but I don't have another >> environment where I can test it (i386 doesn't seem to use pwrite64), >> so I ask for a bit of help/check. >> >> I am in a 32bit linux testing the qemu-ppc. >> >> My test program: >> >> // ------------------------------- >> #include <unistd.h> >> #include <stdio.h> >> #include <sys/types.h> >> #include <sys/stat.h> >> #include <fcntl.h> >> >> int main (void) { >> int fd, len; >> >> char* asd = "This is a random test"; >> char asd2[20]; >> >> fd = open ("./test.pwrite", O_RDWR | O_CREAT); >> >> printf ( "fd: %d\n", fd); >> pwrite ( fd, asd, 15, 0 ); >> pwrite ( fd, asd+5, 6, 10); >> pwrite ( fd, asd, 4, 30); >> >> len = pread ( fd, asd2, 5, 5); >> asd2[len]='\0'; >> printf ( "Read %d bytes: %s", len, asd2); >> >> // This is to force two int arguments for 64bit >> //len = pread ( fd, asd2, -1, -1); >> close(fd); >> return 0; >> } >> // ------------------------------- >> >> Then I do >> $ powerpc-linux-gnu-gcc -g --static -o pwrite-alien pwrite-test.c >> >> and when I launch a qemu-ppc to test, it should be (on the file) >> This is a is a rThis >> >> instead I get: >> This rs a randorThis >> >> and if I print some debug information inside pwrite64 and pread64 I see: >> syscall: pwrite arg_i: 3 268909324 15 0 0 0 0 0 >> syscall: pwrite arg_i: 3 268909329 6 0 0 10 0 0 >> syscall: pwrite arg_i: 3 268909324 4 0 0 30 0 0 >> syscall: pread arg_i: 3 1082133156 5 0 0 5 0 0 >> (those are arg1, arg2, arg3, arg4, arg5, arg6 and the unused arg7 and arg8) >> >> As can be seen, arg4 is not used, and the line >> ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); >> should be, in my case >> ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg5, arg6))); >> >> With this changes, the qemu "Works For Me (TM)". >> >> So, anybody can confirm it or (if it is indeed my problem) can give me >> some pointers? I will not post this as a patch until I understand the >> problem... and first step is making sure that it really is a qemu >> problem. And not my toolchain or something random. > > Running the above code on a real ppc machine (compiled with -m32, running a > ppc64 kernel) I get: > > 00000000 54 68 69 73 20 69 73 20 61 20 69 73 20 61 20 72 |This is a is a r| > 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 54 68 |..............Th| > 00000020 69 73 |is| > > as output. Is this the expected result? Running it in qemu-ppc, I get: > > 00000000 54 68 69 73 20 72 73 20 61 20 72 61 6e 64 6f |This rs a rando| > 0000000f > > So yes, something looks broken here. > > According to arch/powerpc/kernel/sys_ppc32.c, the ppc32 ABI carries 64bit > parameters on odd/even pairs: > > /* > * long long munging: > * The 32 bit ABI passes long longs in an odd even register pair. > */ > > which is almost the same as what ARM or MIPS do and which explains why you > see arg5/arg6 (r7/r8) used instead of arg4/arg5 (r6/r7). > > Could you please try the below patch? > > > Alex > > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 1a38169..e03b3a8 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -587,12 +587,16 @@ extern int setfsgid(int); > extern int setgroups(int, gid_t *); > > /* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ > -#ifdef TARGET_ARM > +#ifdef TARGET_ARM > static inline int regpairs_aligned(void *cpu_env) { > return ((((CPUARMState *)cpu_env)->eabi) == 1) ; > } > #elif defined(TARGET_MIPS) > static inline int regpairs_aligned(void *cpu_env) { return 1; } > +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) > +/* PPC32 expects 64bit parameters to be passed on odd/even pairs of registers > + which is the same as ARM/MIPS, because we start with r3 as arg1. */ > +static inline int regpairs_aligned(void *cpu_env) { return 1; } > #else > static inline int regpairs_aligned(void *cpu_env) { return 0; } > #endif > @@ -7419,12 +7423,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > #endif > #ifdef TARGET_NR_pread64 > case TARGET_NR_pread64: > + if (regpairs_aligned(cpu_env)) { > + arg4 = arg5; > + arg5 = arg6; > + } > if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) > goto efault; > ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); > unlock_user(p, arg2, ret); > break; > case TARGET_NR_pwrite64: > + if (regpairs_aligned(cpu_env)) { > + arg4 = arg5; > + arg5 = arg6; > + } > if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) > goto efault; > ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, > arg5)));