[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] pwrite64 error because of argument position
From: |
Alexander Graf |
Subject: |
Re: [Qemu-devel] pwrite64 error because of argument position |
Date: |
Mon, 1 Oct 2012 13:52:07 +0200 |
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)));
- Re: [Qemu-devel] pwrite64 error because of argument position,
Alexander Graf <=